Connecting Custom Carrier API
Last updated
ChannelDock offers a wide range of pre-built carrier integrations that sellers and fulfillment centers can use out of the box. Because we cannot build a connection with every carrier platform, we also offer a Custom Carrier API. With it, you as a carrier (or shipping platform) can add your own shipment methods to the ChannelDock account of a seller or fulfillment center, and create the shipping labels yourself.
How it works
- You register your shipment methods in the ChannelDock account of the seller or fulfillment center, using the ChannelDock REST API.
- The user selects your shipment method when creating a shipping label in ChannelDock.
- ChannelDock calls your API with the order data and the selected shipment method.
- Your API returns the label as a PDF, together with the tracking number.
- ChannelDock prints the label and sends the tracking number to the sales channel (for example bol or Amazon), so the order is marked as shipped.
You build two things: a script that registers your shipment methods (step 1) and an endpoint on your side that creates labels (steps 3 and 4).
Step 1: Get API credentials
The shipment methods are created in the account of the seller or fulfillment center that will use them. That account generates the API credentials and shares them with you:
- Seller: Settings → API & Webhooks
- Fulfillment center: Settings → API & Webhooks
If endpoint permissions are limited on the API key, make sure the key has access to the shipment methods endpoint. See ChannelDock REST API Documentation for more about API keys.
Step 2: Register your shipment methods
Send your shipment methods to the endpoint that matches the account type:
| Account | Method | Endpoint |
|---|---|---|
| Seller | POST | https://channeldock.com/portal/api/v2/seller/shipmentmethods |
| Fulfillment center | POST | https://channeldock.com/portal/api/v2/center/shipmentmethods |
Authenticate with the api-key and api-secret headers.
Finding this endpoint in the API documentation
Open docs.channeldock.com and go to ChannelDock Seller (or ChannelDock Fulfillment Center) → Shipment methods → Create / Update custom shipment method. You can also search for “custom shipment method”. We do not link directly to the section, because those links change whenever the API documentation is republished.
Example request
{
"name": "MyCarrier - Package large express",
"remote_carrier_id": "my_carrier_large_express",
"carrier_code": "mycarrier",
"logo_url": "https://example.com/logo-700x300.png",
"min_weight": 0,
"max_weight": 23,
"max_x": 150,
"max_y": 150,
"max_z": 150,
"mailbox_size": 0,
"callback_request": {
"method": "POST",
"url": "https://yourdomain.com/api/channeldock/labels",
"headers": {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_CARRIER_API_TOKEN"
}
},
"shipment_method_countries": [
{ "country_code_from": "NL", "country_code_to": "NL", "price": 3.20 },
{ "country_code_from": "NL", "country_code_to": "BE", "price": 4.80 },
{ "country_code_from": "NL", "country_code_to": "DE", "price": 5.60 }
]
}
| Field | Required | Description |
|---|---|---|
| name | Yes | Name of the shipment method, shown to the user. Also used to recognise an existing method (see below). |
| remote_carrier_id | Yes | Your own ID for this shipment method. We send it back with every label request. |
| carrier_code | Yes | Lowercase code of your platform or carrier, for example mycarrier or dhl. |
| logo_url | Yes | Public URL of a PNG logo of 700 x 300 pixels. |
| min_weight, max_weight | Yes | Weight limits in kg. |
| max_x, max_y, max_z | Yes | Maximum dimensions in cm. |
| mailbox_size | Yes | 1 if the method is for mailbox parcels, otherwise 0. With 1, the method is only shown when the parcel fits through the mailbox. |
| callback_request | Yes | How ChannelDock calls your label endpoint: url, method (we recommend POST) and headers (an object, for example with your own authentication token). |
| shipment_method_countries | Yes | At least one route with country_code_from, country_code_to (2-letter ISO codes) and price. The method is only offered for these routes. |
Good to know
- Create or update: ChannelDock looks for an existing shipment method with the same
namein the account. If it exists, it is updated (includingremote_carrier_idandcallback_request). If not, a new one is created. Changing thenametherefore creates a second shipment method; the old one remains. - Routes are added or updated, never removed: a route that you leave out of the request stays active with its previous price.
- Several methods at once: send an array of shipment method objects instead of a single object. The response then shows the result per method.
- Fulfillment centers can retrieve their shipment methods with
GET https://channeldock.com/portal/api/v2/center/shipmentmethods.
Response
{
"response": "success",
"message": "Shipment method MyCarrier - Package large express created successfully"
}
Step 3: Receive the label request
As soon as a ChannelDock user creates a shipping label with one of your shipment methods, ChannelDock calls the url from callback_request, using the method and headers you provided. With POST (recommended), the order data is sent as a JSON body. With GET, the same fields are sent as query parameters.
Example request from ChannelDock
{
"order_id": 774,
"remote_order_id": "ORD-2025-4055",
"seller_id": 1223,
"center_id": 0,
"api_id": 456,
"api_description": "Bol.com - Main shop",
"channel_name": "Bol.com",
"order_date": "2025-05-13 08:49:28",
"ship_on_date": "2025-05-14",
"remote_carrier_id": "my_carrier_large_express",
"carrier_code": "mycarrier",
"number_of_labels": 1,
"sender_details": {
"name": "John Doe",
"company_name": "Doe Logistics BV",
"street": "Keizersgracht",
"house_number": "241",
"address_line_2": "Suite 301",
"zipcode": "1016 EA",
"city": "Amsterdam",
"state_province_code": "",
"country": "NL",
"phone_number": "+31 20 123 4567",
"email": "[email protected]",
"signature_full_name": "John Doe",
"signature_initials": "JD",
"vat_number": "NL123456789B01",
"eori_number": "NL123456789000"
},
"shipping_first_name": "Emma",
"shipping_middle_name": null,
"shipping_last_name": "van Dijk",
"shipping_company": "KiteGear BV",
"shipping_street": "Keizersgracht",
"shipping_house_number": "123",
"shipping_house_number_ext": "B",
"shipping_address1": "Keizersgracht 123",
"shipping_address2": "2nd floor",
"shipping_address_supplement": "Entrance via side door",
"shipping_zip_code": "1015 CJ",
"shipping_city": "Amsterdam",
"shipping_region": "Noord-Holland",
"shipping_country_code": "NL",
"shipping_email": "[email protected]",
"shipping_phone_number": "+31 6 12345678",
"shipping_address_accurate": 1,
"shipping_service": "",
"billing_first_name": "Emma",
"billing_middle_name": null,
"billing_last_name": "van Dijk",
"billing_company": "KiteGear BV",
"billing_street": "Keizersgracht",
"billing_house_number": "123",
"billing_house_number_ext": "B",
"billing_address1": "Keizersgracht 123",
"billing_address2": "2nd floor",
"billing_address_supplement": "Finance dept.",
"billing_zip_code": "1015 CJ",
"billing_city": "Amsterdam",
"billing_region": "Noord-Holland",
"billing_country_code": "NL",
"billing_email": "[email protected]",
"total_weight": 8.0,
"total_length": 80,
"total_width": 25,
"total_height": 25,
"total_order_price": 749.95,
"total_order_currency": "EUR",
"order_products": [
{
"order_product_id": 868,
"remote_order_product_id": "NL-PROD-001",
"ean": "8719326583655",
"sku": null,
"quantity": 1,
"product_title": "North Orbit Kite 2025 - 12m",
"order_product_price": 699.95,
"order_product_price_currency": "EUR",
"product_weight": "5.00",
"product_length": 80,
"product_width": 25,
"product_height": 15,
"product_hs_code": "95062900",
"product_origin_country_code": "NL"
},
{
"order_product_id": 869,
"remote_order_product_id": "NL-PROD-002",
"ean": "8719326583617",
"sku": "PUMP-PRO",
"quantity": 1,
"product_title": "Mystic Kite Pump Pro",
"order_product_price": 50.0,
"order_product_price_currency": "EUR",
"product_weight": "3.00",
"product_length": 40,
"product_width": 10,
"product_height": 10,
"product_hs_code": "84142080",
"product_origin_country_code": "DE"
}
]
}
| Field | Description |
|---|---|
| order_id | The order ID in ChannelDock. |
| remote_order_id | The order number in the sales channel (for example the bol or Amazon order number). |
| seller_id, center_id | The seller the order belongs to. center_id is filled when a fulfillment center creates the label, otherwise it is 0. |
| api_id, api_description, channel_name | The sales channel connection the order came from. |
| remote_carrier_id | Your own ID of the selected shipment method, as registered in step 2. Use it to decide which service to book. |
| carrier_code | The carrier_code of the selected shipment method. |
| number_of_labels | The number of labels (parcels) the user requested. |
| sender_details | The sender address, including VAT and EORI number when available. |
| shipping_* | The delivery address. Use shipping_street, shipping_house_number and shipping_house_number_ext if your system needs separate fields; shipping_address1 and shipping_address2 contain the full address lines. |
| billing_* | The billing address. |
| total_weight | Total weight of the parcel in kg. |
| total_length, total_width, total_height | Parcel dimensions in cm. |
| total_order_price, total_order_currency | Total value of the order products, for example for customs and insurance. |
| order_products | The products in the order, including EAN, SKU, quantity, price, weight (kg), dimensions (cm), HS code and country of origin. |
Fields can be null or empty when the data is not available in ChannelDock, so do not treat every field as mandatory. For shipments outside the EU, ChannelDock only sends the request when every product has a weight.
Step 4: Return the label
Create the label in your system and respond with HTTP status 200 and the following JSON:
{
"label_id": "99999",
"carrier_code": "dhl",
"tracking_number": "JVGL0123456789",
"tracking_number_url": "https://www.dhl.com/nl-en/home/tracking.html?tracking-id=JVGL0123456789",
"pdf_content_base64": "JVBERi0xLjQKJeLjzgo8PC9UeXBlL0NhdGFsb2cvUG..."
}
| Field | Required | Description |
|---|---|---|
| label_id | Yes | The label ID in your system. |
| carrier_code | Yes | The carrier that actually delivers the parcel (for example dhl, postnl, ups). ChannelDock passes this to the sales channel, so it must match the tracking number. |
| tracking_number | Recommended | The tracking number from that same carrier. Without it, the label is still created, but the sales channel does not receive a tracking number. |
| tracking_number_url | Recommended | The link to follow the shipment on the carrier’s website. |
| pdf_content_base64 | Yes | The label as a PDF file, Base64-encoded, in A6 format. When number_of_labels is higher than 1, return all labels in one PDF. |
If label_id, carrier_code or pdf_content_base64 is missing, the user sees the error “Missing field in JSON response” and no label is created.
ChannelDock then saves the label, makes it available for printing and sends the tracking number to the sales channel.
Error handling
If you cannot create the label (for example because the address is invalid), respond with an HTTP status code in the 400 range and a message:
{
"error": {
"message": "House number is missing in the delivery address"
}
}
The user then sees the following error in ChannelDock:
Please contact the owner of this shipment method (integration) for support assistance. Shipping error 400 from mycarrier: House number is missing in the delivery address.
Write the message so that the user knows what to fix. The user is waiting for the label, so respond within a few seconds.
Testing and troubleshooting
- Create a test order in the seller or fulfillment center account, and create a label with your shipment method.
- ChannelDock logs the request sent to your API and your response (without the PDF content) in the log of the order. Open the order in ChannelDock to see exactly what was sent and received.
- Does your shipment method not appear when creating a label? Check the weight and dimension limits,
mailbox_size, and whether a route exists for the order’s sending and destination country.
Was this helpful?