Shipping guides · 4 min read
How to Handle Shipments Outside of the EU?
Ship outside the EU with the customs data carriers need.
This guide explains how to process shipments that are destined for countries outside the European Union (EU) and therefore require customs documentation. It assumes you have followed our Getting Started guide and are familiar with the core flow of the Sendify API.
All example requests use the sandbox URL https://app.dev.sendify.se/ and will require a sandbox API key.
Prerequisites
- Complete the Getting Started guide – you need a valid
x-api-key. - Have a
shipment_idfor which you want to handle customs. - Know the destination country is outside the EU.
- Either attach customs_information in the create shipment request (recommended for non-EU shipments), or have the necessary customs document files (e.g., commercial invoice, ABD) ready for upload.
Creating Shipment
For non-EU shipments, you can include a customs_information object directly in the POST /shipments request. If you do this, Sendify will automatically generate the customs invoice from your data and you do not need to upload a customs invoice document later.
Example request
curl --location 'https://app.dev.sendify.se/external/v1/shipments' \
--header 'x-api-key: $YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"enable_bookable_validation": true,
"from": {
"name": "Sendify AB",
"address": {
"address_line_1": "Östra Larmgatan 16",
"country_code": "SE",
"postal_code": "41107",
"city": "Göteborg"
},
"contact": {
"name": "Support Agent",
"phone": "0103303091",
"email": "contact@sendify.se"
}
},
"to": {
"name": "Sendify Norway",
"address": {
"address_line_1": " Vulkan 1",
"country_code": "NO",
"postal_code": "0178",
"city": "Oslo"
},
"contact": {
"name": "Support Agent",
"phone": "030814088588",
"email": "kontact@sendify.de"
},
"is_private_individual": false
},
"reference_id": "Sendify Shipment",
"packages": [
{
"depth_cm": 20,
"height_cm": 20,
"width_cm": 20,
"weight_kg": 2,
"quantity": 1,
"description": "Swedish Fika",
"type": "PACKAGE",
"stackable": true
}
],
"customs_information": {
"invoice_type": "commercial",
"reason_for_export": "sale",
"currency": "SEK",
"sender_eori_number": "SE123456789012",
"sender_vat_number": "SE556941164101",
"sender_voec_number": "2012345",
"receiver_eori_number": "NO123456789",
"receiver_vat_number": "NO999999999MVA",
"items": [
{
"description": "Coffee gift box",
"material": "assorted",
"quantity": 1,
"unit_type": "pieces",
"unit_weight": 2.0,
"unit_value": 300,
"hs_code": "090121",
"country_of_origin": "SE"
}
],
"additional_information": "Non-EU shipment. No batteries, liquids or hazardous materials.",
"insurance_costs": 0,
"shipping_costs": 0,
"other_costs": 0,
"discount": 0,
"signature": "Support Agent"
},
"system": "Sendify"
}'Example response
{
"id": "YOUR_SHIPMENT_ID",
"reference_id": "Sendify Shipment"
}1. Requesting Rates for Non-EU Shipments
For shipments to or from countries outside the European Union (EU), you must include included_non_eu_rates: true in your POST /shipments/rates request. This applies to both:
- Exports from the EU to non-EU countries
- Imports from non-EU countries into the EU
Without this flag, the API will not return rates and will redirect you to the Sendify website. We recommend always setting this flag to true for all shipments, as it was added for backward compatibility.
This ensures that you receive rates that are applicable for customs processing.
Example: Rate Request for a non-EU shipment (import or export):
curl --location --request POST 'https://app.dev.sendify.se/external/v1/shipments/rates' \
--header 'x-api-key: $YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"shipment_id": "YOUR_SHIPMENT_ID",
"requested_pickup_time": "2025-07-10T10:00:00+02:00",
"included_non_eu_rates": true
}'2. Identifying Required Documents
If a rate is for a non-EU shipment and requires customs documents, its response object in the /shipments/rates call will contain a required_documents array. This array lists the document_type strings for documents you must provide.
Possible values for document_type include:
customsinvoice(Commercial or Proforma Invoice)abd(Ausfuhrbegleitdokument - German export declaration)salesinvoice(Sales Invoice, if different from customs invoice)
Example Rate Response Snippet for a Non-EU Shipment:
{
"rates": [
{
"price_rank": 1,
"shipment_id": "YOUR_SHIPMENT_ID",
"booking_token": "BOOKING_TOKEN",
"carrier_name": "Example Carrier",
"product_name": "Global Express",
"price": "350",
"currency": "SEK",
"required_documents": ["customsinvoice", "salesinvoice"]
}
],
"warnings": []
}In this example, both a customsinvoice and an salesinvoice document are required. You would save the booking_token for later.
3. Uploading Customs Documents
If you included customs_information when creating the shipment, a customs invoice will be generated automatically from that data and you do not need to upload a customsinvoice document. In that case, proceed directly to booking.
For each document_type listed in the required_documents array, you must upload the corresponding file. Use the POST /shipments/{shipment_id}/{document_type} endpoint. The request must be multipart/form-data.
A separate API call is needed for each document.
Placeholders:
{shipment_id}: Your shipment ID.{document_type}: The document type (e.g.,customsinvoice).
Make sure to replace "/path/to/your/..." with the actual path to your document file, don't remove the @.
Example: Uploading a Customs Invoice (customsinvoice)
curl --location --request POST \
'https://app.dev.sendify.se/external/v1/shipments/{YOUR_SHIPMENT_ID}/customsinvoice' \
--header 'x-api-key: $YOUR_API_KEY' \
--form 'file=@/PATH/TO/YOUR/FILE.pdf' \
-w "HTTP Status: %{http_code}\n"Upon successful upload, the API returns a 204 No Content status.
Example Response:
HTTP Status: 2044. Booking the Shipment
Once all documents specified in the required_documents array have been successfully uploaded, you can book the shipment using the booking_token obtained from the rate response (Step 2).
Example Booking Request:
curl --location --request POST 'https://app.dev.sendify.se/external/v1/shipments/book' \
--header 'x-api-key: $YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"booking_token": "BOOKING_TOKEN"
}'Example Booking Response:
{
"shipment_id": "YOUR_SHIPMENT_ID",
"main_tracking_id": "CARRIER_TRACKING_ID_EXAMPLE"
}This confirms the booking. Sendify will forward the uploaded documents to the carrier.
5. Quick Recap
- Ensure your shipment (to or from a non-EU country) is created.
- Call
POST /shipments/ratesfor theshipment_id, ensuringincluded_non_eu_rates: trueis included in the JSON request body.- Check the response for rates with a
required_documentsarray. - Save the
booking_tokenfor the desired rate.
- Check the response for rates with a
- For each item in
required_documents:- Call
PUT /shipments/{shipment_id}/{document_type}with the file.
- Call
- Call
POST /shipments/bookwith thebooking_token. - Your non-EU shipment is booked with customs documents handled!
Need help? Contact api@sendify.com and include the X-Sendify-Request-ID header from the relevant request if available.