Error Handling
When interacting with our API, various error responses may be returned depending on the nature of the request and the current system state. This section outlines how to interpret and troubleshoot the most common HTTP error codes.
All endpoints return standard HTTP status codes to indicate the success or failure of an API request. When a request fails, the response typically includes a JSON object with additional details, such as the error message, a code, and where applicable, information about which fields caused the error.
Understanding these errors can help you quickly resolve issues and improve the stability of your integration.
Common HTTP Error Codes
|
Code |
Error Name |
Description |
|
400 |
Bad Request |
The request is malformed or missing required parameters. The API will return details about which fields are invalid or missing. |
|
401 |
Unauthorized |
The request requires valid authentication. Ensure that your API key or access token is correctly provided and has not expired. |
|
403 |
Forbidden |
You are authenticated but do not have permission to access this resource. Check your account permissions. |
|
404 |
Not Found |
The resource you are trying to access does not exist or the endpoint URL is incorrect. |
|
406 |
Not Acceptable |
The server cannot produce a response matching the list of acceptable values defined in the |
|
409 |
Conflict |
The resource is in a conflicting state. For example, the resource you are trying to update is currently being processed or cannot be modified in its current status. |
|
415 |
Unsupported Media Type |
The server does not support the media type of the request payload. Check that you are using a valid |
|
422 |
Unprocessable Entity |
The request was well-formed but contains semantic errors. For example, trying to create an item with logically inconsistent fields. |
|
429 |
Too Many Requests |
You have exceeded the rate limit for API calls. Please wait before making new requests. Implement retry logic with exponential backoff if needed. |
|
500 |
Internal Server Error |
A generic error occurred on the server. This is typically not caused by your request. Try again later or contact support if the issue persists. |
|
502 |
Bad Gateway |
The API gateway received an invalid response from an upstream service. Temporary, often network-related. |
|
503 |
Service Unavailable |
The service is temporarily unavailable. This can occur during maintenance or due to temporary server overload. |
|
504 |
Gateway Timeout |
The upstream server took too long to respond. Consider retrying with a delay. |
Though most errors are self explanatory and contain textual information on the reason of the failure. Most cases can be resolved through timed retries.
It is strongly advised to avoid spamming the API while retrying, and to prefer implementing delays until resolution.
Some cases (e.g. 406/409/415) should however trigger a resolution requirement instead of retries.
General data read operations should self resolve over time (quotas, availability), while write operations should be stopped after a reasonnable amount of retries and considered failed.
Pagination
To efficiently handle large datasets and improve performance, our API implements pagination on endpoints that return lists of resources. Depending on the endpoint, pagination is handled using either:
-
Page-based pagination (with
pageIndexandpageSizein the query parameters) -
Cursor-based pagination (with cursor tokens provided in the
Linkheader)
This section explains how each method works and how to properly implement them in your integration.
Page-Based Pagination
This method uses pageIndex (starting from 1) and pageSize to navigate through a dataset.
Example Request
GET /brands?pageIndex=1&pageSize=100
Query Parameters
|
Parameter |
Description |
|---|---|
|
|
The index of the page you want to retrieve (starting at 1). |
|
|
The number of items per page. |
Note
-
This method is simple and predictable.
-
It is suitable for datasets that don’t change often.
-
Be cautious of data inconsistency if the underlying data changes while paginating.
Cursor-Based Pagination
Cursor-based pagination is more efficient and reliable for large or dynamic datasets. The client uses a cursor token provided in the response to retrieve pages.
How It Works
-
The API returns pagination links in the
Linkheader. -
Each link has a
relattribute:first,prev,next, etc. -
Use the
cursorparameter from the link to fetch pages.
Example Header
Link: ; rel="first", ; rel="prev", ; rel="next"
Example Request (Next Page)
GET /products?cursor=NjdjN2Y2YzUwNDI2ZTBlMjBiOWNhM2UyfG5leHQ=&limit=12&fields=*
Notes
-
Ideal for real-time or frequently updated datasets.
-
Prevents missing/duplicate data during navigation.
-
The cursor is opaque: do not parse or modify it.
Best Practices
-
Always check for
nextorprevlinks before requesting a new page. -
Don’t mix pagination types for the same endpoint.
-
Use retry logic and backoff if handling large result sets.
-
Use filtering and ordering when available to ensure data consistency through page reads
Listing retrieval
Since our API does not currently support webhooks, your integration must poll listing endpoints (e.g. orders, returns, stock) regularly to fetch new or updated resources.
To ensure you don’t miss data, and don’t overload the API, please follow these guidelines:
1. Use pagination and filters
-
Never try to retrieve everything in one call.
-
Always use
limitandcursorparameters (or equivalent) to navigate through paginated results. -
When available, use
updatedAtMinto fetch only what changed since your last poll.
2. Poll at reasonable intervals
-
Adjust polling frequency based on how fast data changes (e.g. every 5–10 minutes for orders).
-
Don’t call multiple endpoints simultaneously — stagger your polls.
-
Avoid polling too frequently to prevent reaching rate limits.
3. Ensure reliable processing
-
Always log the
cursororlastUpdatedAtof the last processed page. -
Retry failed calls with exponential backoff (on 5xx errors or timeouts).
-
Use unique resource IDs (e.g.
orderId) to prevent duplicate processing.
4. Combine snapshot & incremental strategies
For critical flows like order ingestion:
-
Run regular full snapshots (e.g. once a day).
-
Between snapshots, use incremental polling with
updatedAtMin. -
This helps detect missed updates (e.g. status changes, late orders).
Common Pitfalls
|
Problem |
Recommendation |
|---|---|
|
Missing items |
Use |
|
Duplicates |
Deduplicate by ID before processing |
|
API overload / rate limit |
Use intervals, staggered calls, backoff on 429/403 |
|
Missed deletions |
Run periodic full sync and compare stored data |
|
No results |
Ensure there are not too restrictive filters |
Example (JS-like pseudocode)
let lastFetchedAt = '2024-10-01T00:00:00Z';
function pollOrders() {
let cursor = null;
do {
const res = fetch(`/outbound-shipments?limit=100&cursor=${cursor}&updatedAtMin=${lastFetchedAt}`);
process(res.items);
cursor = res.nextCursor;
} while (cursor);
lastFetchedAt = now();
}
setInterval(pollOrders, 300000); // every 5 minutes
Rate Limiting / Quotas
Why we apply rate limits
To ensure stability, fair usage, and optimal performance for all partners, Octopia APIs enforce rate limits on certain endpoints. These limits prevent abuse, ensure equitable access, and protect our systems during high-load periods.
How it works
-
Rate limits are enforced per endpoint, per seller ID, and per client application (client_id).
-
The limits are evaluated over a rolling one-hour window.
-
If a client exceeds the allowed threshold for a given route, a 403 Forbidden error is returned with the message:
{
"status": 403,
"title": "Quota exceeded",
"detail": "You have exceeded the hourly quota for this endpoint."
}
Each API call is counted against both the client_id and the sellerId used in the request.
If you manage multiple seller accounts under a single integration:
-
You can call the same endpoint multiple times for different sellers without exceeding the quota, as each
sellerIdhas an independent limit. -
For example, calling a route 500 times for
sellerId=10001does not block your next call to the same route withsellerId=10002.
Although we do not expose the exact quota values per route (for security reasons), we recommend the following:
-
Avoid unnecessary polling: Use updatedAtMin/Max filters and pagination to fetch only what’s needed.
-
Distribute your calls: Spread API calls evenly over time rather than batching all at once at the top of the hour.
-
Use sellerId-aware logic: If your system handles multiple sellers, treat their usage independently — don’t artificially throttle all traffic based on one seller’s activity.
-
Implement exponential backoff: On receiving a 403 quota error, pause for a short time and retry progressively less frequently (e.g., wait 60s → 120s → 300s).
-
Log and monitor quota errors: Capture 403 errors in your logs to detect patterns or misbehaving loops.
What happens when the quota is exceeded?
-
A 403 response is immediately returned.
-
No partial processing is done — the call is fully rejected.
-
You should not retry immediately. Doing so may result in further denials or temporary blocks.
What is the exact quota/rate for endpoint X ?
Quotas are implemented as a security measure, they are tailored to suit most usecases and are high enough to avoid being reached. Exact values are not communicated.
Asynchronous quota errors
Offer and Product submission is subjected to ressource quantity quotas.
Those quotas are not API related and are configured at the seller account level, are set to low values for new accounts and automatically upgraded based on data submission quality.
Quota depletion is stated in integration reports. Replenishment is hourly.
Data Formats
Date / Time Formats
All dates and times in the API follow the ISO 8601 standard in UTC timezone unless stated otherwise.
Format
YYYY-MM-DDTHH:MM:SS.sssZ
Examples
"2025-10-20T14:30:00Z" "2023-03-30T15:28:58.9275688+00:00"
Notes
-
Always include the timezone offset (
Zor+00:00) to avoid ambiguity. -
Dates must be parsed/stored in UTC for consistency.
-
Common date filter fields include
createdAt,updatedAt,statusUpdatedAt,receptionDate, etc.
IDs / GTINs / SKUs
UUIDs
Many identifiers follow the UUID v4 format (e.g. outboundShipmentId, returnId, productId, parcelId, etc.)
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
GTINs
GTIN (Global Trade Item Number) must be numeric and between 8 and 14 digits.
^\d{8,14}$
Example:
"gtin": "1234567890123"
Notes:
-
No letters, spaces, or dashes.
-
If invalid, supply orders or product referencing will be rejected.
-
Validated with check digit logic
-
It is then advised to only submit correct GTINs (checksum) to avoid rejections.
-
SellerProductReference
This is your internal product reference. It must be:
-
Unique per seller per product-condition combination
-
Between 1 and 40 characters
-
Alphanumeric, with optional underscores or dashes
-
Case-sensitive
Examples:
"sellerProductReference": "SKU-12345-BLUE" "sellerProductReference": "IPHONEX_NEW"
Character Sets & Encoding
All payloads (request and response bodies) use UTF-8 encoding.
Rules
-
All characters should be properly escaped (e.g. in JSON, XML).
-
Avoid sending HTML-encoded entities (e.g.
&,<) unless expected. -
Ensure systems reading/writing data enforce UTF-8 when serializing/deserializing.
XML payloads (for Offers zip packages)
-
Your
offers.xmlorproducts.xmlshould declare:
xml version="1.0" encoding="utf-8"
-
Special characters in text nodes (e.g.
&,<,") must be escaped using standard XML escaping.
Validation Hints
|
Field Type |
Constraint |
|---|---|
|
|
Must be a valid UUID v4 |
|
|
Must be 8–14 digits, numeric only |
|
|
ISO 8601, with timezone info |
|
|
1–40 characters, unique, alphanumeric |
|
|
Positive decimal values, Note that some numeric properties can be integer only, or accept 2 or 3 decimal points. |
|
|
ISO 3166-1 alpha-2 (e.g., |
Delivery / Logistics
Octopia provides a base set of delivery modes as follows :
Small parcels
|
Code |
Label |
|---|---|
|
THD |
TrackedHomeDelivery |
|
SHD |
SignedHomeDelivery |
|
EHD |
ExpressHomeDelivery |
Large parcels
|
Code |
Label |
|---|---|
|
FDHD |
FixedDateHomeDelivery |
|
SRHD |
SpecificRoomHomeDelivery |
|
WSHD |
WithSetupHomeDelivery |
Extended Delivery Modes and Legacy matching
Based on your activities on our platform and your active subscriptions other deliverymodes can be returned or submitted.
Please see below the table for additional details.
|
Mode |
Code |
Label |
Legacy(1) Mode |
XML OfferPackage |
SalesChannel availability(2) |
|---|---|---|---|---|---|
|
M30 (<30kg) |
|
|
|
|
Cdiscount |
|
M30 (<30kg) |
|
|
|
|
All (mandatory) |
|
M30 (<30kg) |
|
|
|
|
When active* |
|
M30 (<30kg) |
|
|
|
|
When active* |
|
P30 |
|
|
|
|
When active* |
|
P30 |
|
|
|
|
When active* |
|
P30 |
|
|
|
|
When active* |
|
ShopPickup |
– |
|
|
|
Cdiscount |
|
ShopPickup |
– |
|
|
|
Cdiscount |
|
PickupPoint |
|
|
|
|
Cdiscount |
|
PickupPoint |
|
|
|
|
Cdiscount |
|
PickupPoint |
|
|
|
|
Cdiscount |
|
PickupPoint |
|
|
|
N/A |
Cdiscount Fulfillment Only |
|
PickupPoint |
|
|
|
N/A |
Cdiscount Fulfillment Only |
|
PickupPoint |
|
|
|
N/A |
Cdiscount Fulfillment Only |
|
PickupPoint |
|
|
|
N/A |
Cdiscount Fulfillment Only |
|
PickupPoint |
|
|
|
N/A |
Cdiscount Fulfillment Only |
|
PickupPoint |
|
|
|
N/A |
Cdiscount Fulfillment Only |
|
PickupPoint |
|
|
|
N/A |
Cdiscount Fulfillment Only |
Footnotes :
* : depends on SalesChannel choice for enabled delivery modes
(1) : These delivery codes are used in the legacy SOAP API
(2) : Delivery modes marked as “Cdiscount” are only available on the CDISFR salesChannel, offers with such delivery modes will not be published on other salesChannels
All values are case sensitive
Depending on your activity within the Octopia network and the complexity of your fulfillment management with our services, other delivery modes can be read from the GET /orders endpoint.
Previously available modes, which are currently considered obsolete are not given in this mapping table.
Columns explanations
Octopia – Code
Octopia Code is the delivery mode short code range, available through APIs exposing the “code” or “mode” attribute
Offer Endpoint
/* items[].deliveryOffers[] */
"deliveryModes": [
{
/* other information */
"code": "THD"
}
]
Fulfillment Endpoint
/* items[] */
"delivery": [
{
"mode": "THD"
/* other information */
}
]
It is also the required value when submitting data through
-
POST /offer-requests (please note that submitting offers with this endpoint does not publish towards Cdiscount)
Octopia – Label
The delivery mode attribute “label” or “mode” is available through the following APIs :
Orders Endpoint
/* items[].lines[] */
"delivery": [
{
"mode": "TrackedHomeDelivery"
/* other information */
}
]
Please note that PickupPoint delivery modes also expose pickupIp and pickupName within shippingAddresses nodes.
LegacyMode
The delivery mode attribute “ModLiv” was available through the following APIs :
-
SOAP – GetOrderList
It is provided here as a reference mapper for legacy integrations and should not be used anymore. See also SOAP API Deprecation
XMLOfferPackage
These values are to be used in XML offer publication packages under the OfferShippingInformationList node as an “DeliveryMode” attribute to ShippingInformation.
XML Offers Endpoint
SalesChannel Availability
Some delivery modes are currently required whichever the targetted publication channel or offer publication method
Others can only be submitted to specific sales channels.
All sales channels can accept or not your offers based on which delivery methods you provide.
OSP Name (language code)
This is how it is currently displayed within your seller portal.