Partner Order API
The Partner Order API accepts dropship orders and stock queries over signed HTTPS. Each order is validated, priced from the catalog, and submitted into the merchant's fulfilment flow.
Endpoints
POST /v1/partner-orders
POST /v1/stock
GET /v1/catalog
Base URL and your credentials are provided to you on onboarding.
Authentication
Every request carries three headers:
| Header | Value |
|---|---|
X-Vivid-Key | Your key id |
X-Vivid-Timestamp | Current Unix time in seconds, generated on each request |
X-Vivid-Signature | Hex HMAC-SHA256, see below |
signingString = timestamp + "." + rawBody
signature = hex( HMAC_SHA256( secret, signingString ) )
- Sign the exact raw body bytes you send. Do not re serialize after signing.
- The timestamp is part of the signed string.
- Requests must arrive within 5 minutes of their timestamp.
Order request body
{
"partner_code": "your_partner_code",
"external_order_number": "YOUR-ORDER-123",
"order_date": "2026-07-27T10:15:00Z",
"line_items": [
{ "sku": "MERCHANT-SKU", "quantity": 2, "product_ref": "your-ref" }
],
"delivery_address": {
"first_name": "Jan",
"last_name": "Jansen",
"company": "Example B.V.",
"street": "Voorbeeldstraat",
"house_number": "12",
"postal_code": "1011 AB",
"city": "Amsterdam",
"country": "NL",
"email": "jan@example.com",
"phone": "+31612345678"
},
"requested_delivery_date": "2026-08-05",
"delivery_instructions": "Ring twice"
}
Fields
| Field | Required | Notes |
|---|---|---|
partner_code | yes | Your partner code. |
external_order_number | yes | Your order reference. Used for duplicate protection. |
line_items[].sku / quantity | yes | The sku must match the merchant's SKU exactly, since that is how the product is identified. An unknown SKU is rejected and the order is not processed. Prices are never sent; they resolve from your catalog. |
delivery_address | yes | Recipient name (first_name+last_name, or a single name), address, country (ISO-2), email, phone. |
delivery_address.company | no | Recipient company, when ordering on behalf of a business. |
order_date | no | ISO timestamp. |
line_items[].product_ref | no | Your own line reference, for your records. |
branch_identifier | multi-branch partners only | Identifies the branch the order is for. Required when your account covers several branches (these partners must also send requested_delivery_date); ignored otherwise. An unknown identifier is rejected with BRANCH_UNKNOWN. |
requested_delivery_date | no | YYYY-MM-DD. See the delivery date rules below. |
delivery_instructions | no | Free text, carried on the order reference. |
Shipping is applied automatically per destination country. You do not send prices or shipping costs, both are determined by the merchant configuration.
Delivery date rules
When you send requested_delivery_date, it must satisfy all of:
- Minimum lead time of 2 business days from the order date.
- Cut-off at 12:00 (Europe/Amsterdam). Orders placed after 12:00 need one extra business day.
- No weekends. Saturdays and Sundays are not valid delivery dates.
- No national holidays.
A date that breaks any of these is rejected with INVALID_DELIVERY_DATE. Omit the field to use the earliest valid date.
Responses
| HTTP | Meaning |
|---|---|
| 201 | Accepted. Body has order_number. In test mode this is #TEST-… with a price preview. |
| 409 | DUPLICATE_ORDER, already received; original returned, treat as success. ORDER_IN_PROGRESS, retry shortly. |
| 422 | Rejected. See code: SKU_UNKNOWN, SKU_NOT_ALLOWED, SKU_UNAVAILABLE, SKU_NO_PRICE, INVALID_QUANTITY, INVALID_ADDRESS, UNSUPPORTED_COUNTRY, INVALID_DELIVERY_DATE. Multi-branch partners can also get BRANCH_REQUIRED, BRANCH_UNKNOWN, BRANCH_NOT_CONFIGURED, DELIVERY_DATE_REQUIRED. |
| 429 | RATE_LIMITED, back off and retry. |
| 502 / 500 | Retry safe. |
Duplicate protection
Orders dedupe on your external_order_number. Resend the same one and you get the original back with 409, so retrying after a timeout is always safe.
Stock
{ "skus": ["MERCHANT-SKU-1", "MERCHANT-SKU-2"] }
Returns a simple in_stock true/false per SKU. No quantities.
Catalog
GET /v1/catalog returns the products available in the catalog assigned to your partner account. Signed the same way as other requests, with an empty body.
GET /v1/catalog?cursor=OPTIONAL_CURSOR
| Field | Notes |
|---|---|
sku | Leading identifier. May be null on a small number of products. |
title, vendor | Product title and brand. |
ean | EAN/GTIN barcode. Not set on every product — null when missing. |
manufacturerArticleNumber | The manufacturer's own part number, where known. |
description, specifications | specifications is a plain array of strings. |
weight | { value, unit }, or null. |
imageUrls | Array of image URLs, may be empty. |
documentationUrl | Manual/datasheet link, or null. |
warranty | Free text, or null. |
status | Shopify's own product status (e.g. ACTIVE, DRAFT) — use this to identify inactive products. |
price | { amount, currencyCode }, excl. VAT. |
Results are paginated, 50 products per page:
{
"products": [ ... ],
"pagination": { "has_next_page": true, "next_cursor": "..." }
}
Pass next_cursor back as the cursor query parameter to fetch the next page. When has_next_page is false, you've reached the end.
Partner Order API
De Partner Order API verwerkt dropshiporders en voorraadaanvragen via beveiligde, ondertekende HTTPS-verzoeken. Elke order wordt gevalideerd, geprijsd op basis van de gekoppelde catalogus en doorgezet naar het fulfilmentproces van Apex.
Endpoints
POST /v1/partner-orders
POST /v1/stock
GET /v1/catalog
Je ontvangt de basis-URL en inloggegevens tijdens de onboarding.
Authenticatie
Elk verzoek bevat drie headers:
| Header | Waarde |
|---|---|
X-Vivid-Key | Jouw key-id |
X-Vivid-Timestamp | Huidige Unix-tijd in seconden, per verzoek gegenereerd |
X-Vivid-Signature | Hex HMAC-SHA256, zie hieronder |
signingString = timestamp + "." + rawBody
signature = hex( HMAC_SHA256( secret, signingString ) )
- Onderteken exact de onbewerkte request body die je verstuurt. Serialiseer de body niet opnieuw na het ondertekenen.
- De timestamp maakt deel uit van de ondertekende string.
- Verzoeken moeten binnen 5 minuten na de timestamp bij ons binnenkomen.
Request body van de order
{
"partner_code": "your_partner_code",
"external_order_number": "YOUR-ORDER-123",
"order_date": "2026-07-27T10:15:00Z",
"line_items": [
{ "sku": "APEX-SKU", "quantity": 2, "product_ref": "your-ref" }
],
"delivery_address": {
"first_name": "Jan",
"last_name": "Jansen",
"company": "Example B.V.",
"street": "Voorbeeldstraat",
"house_number": "12",
"postal_code": "1011 AB",
"city": "Amsterdam",
"country": "NL",
"email": "jan@example.com",
"phone": "+31612345678"
},
"requested_delivery_date": "2026-08-05",
"delivery_instructions": "Twee keer aanbellen"
}
Velden
| Veld | Verplicht | Toelichting |
|---|---|---|
partner_code | ja | Jouw partnercode. |
external_order_number | ja | Jouw orderreferentie. Wordt gebruikt voor bescherming tegen dubbele orders. |
line_items[].sku / quantity | ja | De SKU moet exact overeenkomen met de Apex SKU. Hiermee wordt het juiste product herkend. Een onbekende SKU wordt geweigerd en de order wordt niet verwerkt. Prijzen mogen niet worden meegestuurd; deze worden bepaald op basis van jouw gekoppelde catalogus. |
delivery_address | ja | Naam ontvanger (first_name+last_name, of een enkele name), adres, country (ISO-2), email, phone. |
delivery_address.company | nee | Bedrijfsnaam van de ontvanger, wanneer er namens een bedrijf wordt besteld. |
order_date | nee | ISO-timestamp. |
line_items[].product_ref | nee | Jouw eigen regelreferentie voor interne administratie. |
branch_identifier | alleen bij meerdere vestigingen | Geeft aan voor welke vestiging de order is. Verplicht wanneer jouw account meerdere vestigingen omvat (dan is ook requested_delivery_date verplicht); anders wordt het genegeerd. Een onbekende identifier wordt geweigerd met BRANCH_UNKNOWN. |
requested_delivery_date | nee | YYYY-MM-DD. Zie de leverdatumregels hieronder. |
delivery_instructions | nee | Vrije tekst voor bezorginstructies; wordt meegegeven op de order. |
Verzendkosten worden automatisch toegepast op basis van het land van bestemming. Je stuurt geen prijzen of verzendkosten mee; beide worden bepaald vanuit de partnerconfiguratie in Apex.
Leverdatumregels
Als je requested_delivery_date meestuurt, moet deze aan de volgende regels voldoen:
- Minimale doorlooptijd van 2 werkdagen vanaf de orderdatum.
- Cut-offtijd om 12:00 uur (Europe/Amsterdam). Orders die na 12:00 uur worden geplaatst, hebben een extra werkdag nodig.
- Weekenden zijn geen geldige leverdagen.
- Nationale feestdagen zijn geen geldige leverdagen.
Een datum die niet aan deze regels voldoet, wordt geweigerd met INVALID_DELIVERY_DATE. Laat het veld leeg om de eerst mogelijke geldige leverdatum te gebruiken.
Antwoorden
| HTTP | Betekenis |
|---|---|
| 201 | Geaccepteerd. De response body bevat order_number. In testmodus is dit #TEST-…, inclusief prijsvoorbeeld. |
| 409 | DUPLICATE_ORDER: de order is al ontvangen. De originele order wordt teruggegeven; behandel dit als succesvol. ORDER_IN_PROGRESS: de order wordt nog verwerkt. Probeer het later opnieuw. |
| 422 | Geweigerd. Zie code: SKU_UNKNOWN, SKU_NOT_ALLOWED, SKU_UNAVAILABLE, SKU_NO_PRICE, INVALID_QUANTITY, INVALID_ADDRESS, UNSUPPORTED_COUNTRY, INVALID_DELIVERY_DATE. Bij meerdere vestigingen zijn ook mogelijk: BRANCH_REQUIRED, BRANCH_UNKNOWN, BRANCH_NOT_CONFIGURED, DELIVERY_DATE_REQUIRED. |
| 429 | RATE_LIMITED: wacht even en probeer het opnieuw. |
| 502 / 500 | Veilig om opnieuw te proberen. |
Bescherming tegen dubbele orders
Orders worden ontdubbeld op basis van external_order_number. Stuur je dezelfde order opnieuw, dan krijg je de originele order terug met 409. Opnieuw proberen na een time-out is dus veilig.
Voorraad
{ "skus": ["APEX-SKU-1", "APEX-SKU-2"] }
Geeft per SKU een eenvoudige in_stock true/false terug. Er worden geen aantallen gedeeld.
Catalogus
GET /v1/catalog geeft de producten terug die beschikbaar zijn in de catalogus die aan jouw partneraccount is gekoppeld. Ondertekend op dezelfde manier als andere verzoeken, met een lege body.
GET /v1/catalog?cursor=OPTIONELE_CURSOR
| Veld | Toelichting |
|---|---|
sku | Leidende identifier. Kan null zijn bij een klein aantal producten. |
title, vendor | Producttitel en merk. |
ean | EAN/GTIN-barcode. Niet bij elk product ingevuld — null indien ontbrekend. |
manufacturerArticleNumber | Het eigen artikelnummer van de fabrikant, indien bekend. |
description, specifications | specifications is een platte array van tekstregels. |
weight | { value, unit }, of null. |
imageUrls | Array van afbeeldings-URL's, kan leeg zijn. |
documentationUrl | Link naar handleiding/datasheet, of null. |
warranty | Vrije tekst, of null. |
status | De productstatus zoals Shopify die hanteert (bijv. ACTIVE, DRAFT) — hiermee herken je inactieve producten. |
price | { amount, currencyCode }, excl. btw. |
Resultaten worden gepagineerd, 50 producten per pagina:
{
"products": [ ... ],
"pagination": { "has_next_page": true, "next_cursor": "..." }
}
Geef next_cursor terug als de cursor query-parameter om de volgende pagina op te halen. Wanneer has_next_page op false staat, heb je het einde bereikt.