Access to the V2 order API must be enabled for your integrator account. If you do not have access, please contact your account manager. The root of the API is at https://order-api.bayphoto.com/order_api/v2. All endpoint paths are relative to this URL.


Authentication

All requests to the API must be authenticated using the OAuth 2.0 client credentials flow. During the initial setup of your integrator account, you will be provided with a client ID and client secret. These credentials must be used to obtain an access token, which must be included in the Authorization header of each request to the API. The URL for obtaining the access token is https://order-api.bayphoto.com/oauth/token.

The access token is valid for 2 hours, and must be refreshed periodically. It is recommended to implement a mechanism which can store an existing access token and reuse it until it expires, at which point a new token can be obtained.

Available scopes

Building an order

The order JSON schema defines the structure and requirements for orders submitted to the API. It is based on the JSON Schema specification, and provides a way to validate the JSON structure of an order. Visit the v2 order JSON schema docs page for a more detailed description of the schema, as well as the full schema itself.

A typical simple order will look like this:

{
  "integrator_identifier": "XXX-123456",
  "placed_at": "2023-10-01T12:00:00Z",
  "shipping": {
    "code": "GROUND",
    "destination_address": {
      "name": "Some Person",
      "street_address": ["123 Main St", "Apt 4B"]
      "city": "Anytown",
      "state_or_region": "CA",
      "postal_code": "12345",
      "country": "US"
    }
  },
  "images": {
    "iid-12345": {
      "url": "https://example.com/images/1.jpg",
      "filename": "my_image.jpg"
    }
  },
  "products": [
    {
      "name": "8x10 Metal print",
      "code": "90591",
      "quantity": 1,
      "images": {
        "1": {
          "image_id": "iid-12345"
        }
      },
      "options": [
        {
          "name": "Satin finish",
          "code": "381893",
          "quantity": 1
        }
      ]
    }
  ]
}

Identifying products and options

Products and options in the order are identified by their unique codes. These are string values within the order JSON, and they must match the codes defined in your Order API product catalog. The ID column is the value we are looking for. In practice these codes will be integers in string format.

Identifying 'image nodes' and assigning images within products

When a product contains one or more 'image nodes' in which an image can be placed, you must assign an image to each image node. The list of nodes within a product can be seen when viewing a product in the catalog on Order API. As with products, each node has an ID (unique within only that product), which is a string value within the order JSON. Image node IDs almost always start at "1" and increment by 1 for each node in the product.

Order submission

Due to the inherent complexity of orders and the images they contain, the order submission process involves multiple steps. Once an integrator builds and submits an order, the API will respond according to whether the order meets basic validation criteria, including:

However, this does not mean the order has been accepted for processing. The order will undergo a robust validation process, which will take some time, typically proportional to the size and complexity of the order.

If the order passes validation, it will be accepted for processing and a notifiaction will be sent to the integrator. More information about this notification, and other order event notifications, can be found in the appropriate documentation section.

If the order fails validation, the integrator will receive an error response with details about why the validation failed. See below for more specific information on what kinds of validation errors can occur.

API request

POST /orders

Requires the integrator:order:write scope.

The request body should contain JSON that conforms to the order JSON schema.

A successful response will be 202 Accepted, indicating that the order has been received and is enqueued for validation.

A failed response will be a 400-level HTTP response code, typically 400 Bad request or 409 Conflict, with a JSON body containing details about the errors.

Validation process

Orders submitted to the API will undergo a comprehensive validation process before being accepted for processing. The primary task is to validate the image URLs (and accompanying images) provided in the order. These issues almost always require manual intervention to resolve, which would otherwise significantly delay the processing of the order. Each unique image URL in the order will be validated to ensure it is accessible and usable.

URL validation

Each URL will receive a HEAD request, and it is expected to return a 200-level HTTP response code. Non-200-level responses to the HEAD request will cause a fallback GET request. If the GET request also fails, the URL will be considered invalid. In the interest of speed and minimizing bandwidth usage, it is strongly recommended to provide image URLs which respond to HEAD requests.

Common issues with image URLs include:

Image validation

After a URL is validated, the images itself will be validated. This involves downloading the images (partially, when possible) and checking them for various issues. The validation process checks for:

In the interest of speed and minimizing bandwidth usage, it is strongly recommended to host images on a server which supports HTTP range requests, which allows us to only download as much of an image as is necessary to validate it, rather than downloading the entire image file.

The world of digital image formats is vast and complex, and there are many potential issues that can arise. The validation process is designed to catch the most common issues, but it is not exhaustive. Generally, at this stage, we will only reject an image if it is clearly invalid or unsupported. Our goal is to avoid false positives.

Image rules and requirements

Here are some specific rules and requirements for images submitted in orders, based on the file type. File types not included in this list are not supported and will likely be rejected during the validation process. File types are never determined by file extension (the filename could be a part of the provided image URL), but rather by the actual content of the file.

Product and option validation

We will always ensure that the product codes and option codes in the order match the codes defined in your Order API product catalog. If you use codes that do not exist in your catalog, or use option codes that do not exist for the specified product, the order will be rejected.

Validation result notification

After the validation process for a new order is finished, the API will send a notification to the integrator. It takes the same general format as all other notifications that may be sent during the lifecycle of an order. They are sent as HTTP POST requests to a URL specified by the integrator during the initial setup of their account. For more information about the notification format, see the lifecycle notifications section.

Acting on an 'accepted' order notification

After receiving a notification than an order has been successfully validated, no further action is required from the integrator. The order will be processed according to the normal workflow, and the integrator will receive further notifications as the order progresses through its lifecycle.

Acting on a 'rejected' order notification

If an order is rejected during the validation process, the integrator will receive a notification with details about the validation errors. The integrator should review the errors and take appropriate action to correct them.

Rejected orders visible in the orders index, but they will not be processed further. The validation errors will be visible within the Order API interface, if needed. Orders with duplicate integrator_identifier values would normally be rejected before validation, but in the case of rejected orders, subsequent order creation requests with the same integrator_identifier will update the existing order with the new information, and then enqueue the order for validation again.

Retrieving existing order information

Retrieving basic information

GET /orders/<integrator_identifier>

Requires the integrator:order:read scope.

Given an integrator_identifier, which is the unique identifier (usually an order number) that has meaning to the integrator. The response contains the order information in JSON format, including timestamps for order events. A notifications section includes information about when our system recorded successful outgoing notification requests to the integrator.

{
  "number": "ABC00012345",
  "integrator_identifier": "XXX-123456",
  "reference": null,
  "created_at": "2023-10-01T12:00:00Z",
  "accepted_at": "2023-10-01T12:05:00Z",
  "rejected_at": null,
  "released_to_production_at": "2023-10-01T12:10:00Z",
  "invoiced_at": "2023-10-01T12:15:00Z",
  "shipped_at": "2023-10-01T12:20:00Z",
  "notifications": {
    "accepted_notification_sent_at": "2023-10-01T12:06:00Z",
    "rejected_notification_sent_at": null,
    "released_to_production_notification_sent_at": "2023-10-01T12:11:00Z",
    "invoiced_notification_sent_at": "2023-10-01T12:16:00Z",
    "shipped_notification_sent_at": "2023-10-01T12:21:00Z"
  }
}

Retrieving an order's original JSON

GET /orders/<integrator_identifier>/order_json

Requires the integrator:order:read scope.

Returns the order body in JSON format, as it was submitted by the integrator - aside from possible ordering/formatting/prettification changes.

Lifecycle notifications

The Order API sends notifications to the integrator at various stages of the order lifecycle. These notifications are sent as HTTP POST requests to a URL specified by the integrator during the initial setup of their account. The notifications follow a standard format, which includes information about the order, and depending on the nature of the event itself, metadata about the event.

Notification format

The notifications are sent as JSON objects:

{
  "event": "accepted",
  "integrator_identifier": "XXX-123456",
  "order_number": "ABC00012345",
  "occurred_at": "2023-10-01T12:06:00Z"
}

Some event types include additional metadata, found in the top-level metadata JSON property.

Notification types

Event type Description Metadata sub-properties
accepted Accepted for processing after passing validation. None
rejected Rejected due to errors during the validation process. rejection_reasons
released_to_production Finished processing and released to the production floor. None
invoiced Finished production and invoiced in accounting system. None
shipped Shipping label generated and either awaiting pickup, or picked up by the carrier. In the case of split shipment, only sent when every part of an order has been shipped. shipments

Metadata details

Example shipment notification

{
  "event": "shipped",
  "integrator_identifier": "XXX-123456",
  "order_number": "ABC00012345",
  "occurred_at": "2023-10-01T12:06:00Z",
  "metadata": {
    "shipments": [
      {
        "tracking_number": "1Z999AA10123456784",
        "carrier": "UPS"
      },
      {
        "tracking_number": "9400110200888888888888",
        "carrier": "USPS"
      }
    ]
  }
}

Requesting order changes

This feature is a work in progress, and is not yet available. It will be documented here once it is ready for use.

Requesting order cancellation

This feature is a work in progress, and is not yet available. It will be documented here once it is ready for use.