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.
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.
integrator:order:read
- Reading order information.integrator:order:write
- Submitting new orders, requesting order changes or cancellationsThe 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
}
]
}
]
}
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.
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.
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.
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.
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.
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:
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.
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.
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.
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.
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.
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.
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"
}
}
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.
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.
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.
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 |
rejection_reasons
: An array of strings describing the reasons for the rejection. Each reason is a human-readable description of a validation error that occurred during the validation process.shipments
: An array of objects describing the shipments associated with the order. Each object contains:
tracking_number
: The tracking number for the shipment.carrier
: The carrier used for the shipment.{
"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"
}
]
}
}
This feature is a work in progress, and is not yet available. It will be documented here once it is ready for use.
This feature is a work in progress, and is not yet available. It will be documented here once it is ready for use.