Newsletter
Best Practices
  • Home
  • Best Practices

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 Accept header. Ensure that the Accept header is properly set (e.g., application/json).

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 Content-Type (e.g., application/json).

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 pageIndex and pageSize in the query parameters)

  • Cursor-based pagination (with cursor tokens provided in the Link header)

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

pageIndex

The index of the page you want to retrieve (starting at 1).

pageSize

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 Link header.

  • Each link has a rel attribute: first, prev, next, etc.

  • Use the cursor parameter 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 next or prev links 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 limit and cursor parameters (or equivalent) to navigate through paginated results.

  • When available, use updatedAtMin to 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 cursor or lastUpdatedAt of 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 updatedAtMin and paginate fully

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 sellerId has an independent limit.

  • For example, calling a route 500 times for sellerId=10001 does not block your next call to the same route with sellerId=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 (Z or +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.xml or products.xml should 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

UUID

Must be a valid UUID v4

GTIN

Must be 8–14 digits, numeric only

DateTime

ISO 8601, with timezone info

sellerProductReference

1–40 characters, unique, alphanumeric

price / weight

Positive decimal values, . as decimal sep, no leading or trailing 0

Note that some numeric properties can be integer only, or accept 2 or 3 decimal points.

countryCode

ISO 3166-1 alpha-2 (e.g., FR, ES)

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)

NTHD

NotTrackedHomeDelivery

STD

Standard

Cdiscount

M30 (<30kg)

THD

TrackedHomeDelivery

TRK

Tracked

All (mandatory)

M30 (<30kg)

SHD

SignedHomeDelivery

REG

Registered

When active*

M30 (<30kg)

EHD

ExpressHomeDelivery

EXP

Express

When active*

P30

FDHD

FixedDateHomeDelivery

LV1

BigParcelEco

When active*

P30

SRHD

SpecificRoomHomeDelivery

LV2

BigParcelStandard

When active*

P30

WSHD

WithSetupHomeDelivery

LV3

BigParcelComfort

When active*

ShopPickup

ImmediateVendorPickup

RIM

Rim

Cdiscount

ShopPickup

VendorPickup

MAG

Relay

Cdiscount

PickupPoint

PPMR

PickupPointMondialRelay

REL

MondialRelay

Cdiscount

PickupPoint

PPRC

PickupPointRelaisColis

RCO

RelaisColis

Cdiscount

PickupPoint

PPLP

PickupPointLaPoste

SO1

SoColissimo

Cdiscount

PickupPoint

ExpressPickupPointMondialRelay

N/A

Cdiscount Fulfillment Only

PickupPoint

ExpressLockerMondialRelay

N/A

Cdiscount Fulfillment Only

PickupPoint

ExpressPickupPointRelaisColis

N/A

Cdiscount Fulfillment Only

PickupPoint

PickupPointChronopostLock

N/A

Cdiscount Fulfillment Only

PickupPoint

ExpressPickupPointCdiscount

N/A

Cdiscount Fulfillment Only

PickupPoint

StandardPickupPointLaPoste

N/A

Cdiscount Fulfillment Only

PickupPoint

ExpressPickupPointLaPoste

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

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.