Skip to main content

SOM API: booking with customs declarations

SOM API: Booking with Customs Declarations defines how to include customs declaration data in cross-border shipments booked via the Ingrid SOM API.

J
Written by Jakub Talarek

What is it?

SOM API: Booking with Customs Declarations defines how to include customs declaration data in cross-border shipments booked via the Ingrid SOM API. It covers three supported integration paths depending on how your fulfillment systems are structured, plus a complete field reference for GeneralCustomsDeclaration and GeneralCustomsDeclarationItem.

Any shipment that crosses a customs border requires a customs_declaration object in the booking call. Ingrid does not derive customs data automatically — it must come from your systems.


Which path to use

Your setup

Recommended path

You use Ingrid Delivery Checkout and have a tos_id

Path 1: TOS ID + inline customs declaration

You provide all shipment data directly (no Delivery Checkout)

Path 2: Full API booking + inline customs declaration

Customs data comes from a separate system or pipeline step

Path 3: Create shipment → upsert customs → book


Path 1: TOS ID booking + inline customs declaration

Use when you book shipments using a tos_id from a completed Ingrid Delivery Checkout session. Ingrid resolves addresses, shipping method, and line items from the checkout session — but customs data must still be included in every booking call.

POST /v1/som/shipments.createAndBook
{
  "tos_id": "{{tos_id}}",
  "customs_declaration": {
    "general_customs_declaration": {
      "contents_type": "SALE_OF_GOODS",
      "contents_explanation": "Clothing",
      "invoice_number": "INV-2024-001",
      "invoice_date": "2024-01-15",
      "incoterms": "DDP",
      "currency": "SEK",
      "seller_identification_numbers": {
        "vat_number": "SE123456789001",
        "eori_number": "SE123456789"
      },
      "items": [
        {
          "description": "Cotton T-shirt",
          "hs_tariff_number": "6109100010",
          "country_of_origin": "CN",
          "quantity": 2,
          "unit_value": 29900,
          "unit_net_weight": 200,
          "unit_gross_weight": 250
        }
      ]
    }
  }
}

Path 2: Full API booking + inline customs declaration

Use when you provide the full shipment payload directly — no Delivery Checkout involved. The customs_declaration block is identical to Path 1.

POST /v1/som/shipments.createAndBook
{
  "shipment": {
    "address_from": { ... },
    "address_to": { ... },
    "parcels": [ ... ]
  },
  "customs_declaration": {
    "general_customs_declaration": {
      "contents_type": "SALE_OF_GOODS",
      "contents_explanation": "Clothing",
      "incoterms": "DDP",
      "currency": "SEK",
      "seller_identification_numbers": {
        "vat_number": "SE123456789001",
        "eori_number": "SE123456789"
      },
      "items": [
        {
          "description": "Cotton T-shirt",
          "hs_tariff_number": "6109100010",
          "country_of_origin": "CN",
          "quantity": 2,
          "unit_value": 29900,
          "unit_net_weight": 200,
          "unit_gross_weight": 250
        }
      ]
    }
  }
}

Path 3: Create shipment → upsert customs declaration → book

Use when customs data is produced by a separate system or pipeline step after shipment creation.

Step 1: Create the shipment

POST /v1/som/shipments.create
{
  "shipment": {
    "address_from": { ... },
    "address_to": { ... },
    "parcels": [ ... ]
  }
}

Response includes the shipment_id needed for the next steps.

Step 2: Upsert the customs declaration

POST /v1/som/shipments.upsertCustomsDeclaration
{
  "shipment_id": "{{shipment_id}}",
  "general_customs_declaration": {
    "contents_type": "SALE_OF_GOODS",
    "contents_explanation": "Clothing",
    "incoterms": "DDP",
    "currency": "SEK",
    "seller_identification_numbers": {
      "vat_number": "SE123456789001",
      "eori_number": "SE123456789"
    },
    "items": [
      {
        "description": "Cotton T-shirt",
        "hs_tariff_number": "6109100010",
        "country_of_origin": "CN",
        "quantity": 2,
        "unit_value": 29900,
        "unit_net_weight": 200,
        "unit_gross_weight": 250
      }
    ]
  }
}

Calling upsertCustomsDeclaration again on the same shipment will replace the existing customs declaration.

Step 3: Book the shipment

POST /v1/som/shipments.bookParcels
{
  "shipment_id": "{{shipment_id}}"
}

Ensure Step 2 completes successfully before calling bookParcels.


Reducing payload with booking rules

Many customs declaration fields are the same for every order on a given route — seller tax IDs, incoterms, currency, importer address. With booking rules, Ingrid can populate these static fields automatically at booking time based on conditions like origin country.

What booking rules can auto-populate:

  • seller_identification_numbers — VAT, EORI per origin country

  • incoterms and place_of_incoterms

  • currency

  • sold_to — importer or customs broker address. Note: The region field (state/province) is required for: United States, Canada, Australia, China, Brazil, Mexico, Malaysia, New Zealand.

  • Carrier-specific metadata

What you must always send per order:

  • items[] — HS tariff number, country of origin, value, net and gross weight per line item

  • contents_type and contents_explanation (unless configured as a static rule)

  • invoice_number and invoice_date (if required by your carrier)

Booking rules are configured by the Ingrid team. Contact your integration manager or ask Iris, Ingrid's AI assistant, in the chat on the Ingrid Help Center, and share your route setup and which fields are static per origin country or warehouse. Iris can hand your request over to the Ingrid team or create a ticket for you. If you can't reach Iris, email [email protected].


Field reference

GeneralCustomsDeclaration

Field

Type

Required

Description

currency

string

Yes

ISO 4217 currency code (e.g. SEK, EUR, USD)

contents_type

enum

Yes

SALE_OF_GOODS, GIFT, RETURN, COMMERCIAL_SAMPLE, DOCUMENTS, OTHER, DANGEROUS_GOODS, HUMANITARIAN_DONATIONS

contents_explanation

string

Yes

Short description of contents (e.g. "Clothing")

incoterms

enum

Carrier-dependent

DDP, DAP, DDU, EXW, FCA, etc.

invoice_number

string

Carrier-dependent

Unique invoice identifier

invoice_date

string

Carrier-dependent

RFC-3339 date when invoice was issued

total_gross_weight

integer

Carrier-dependent

Total parcel weight in grams including packaging

seller_address

Address

Carrier-dependent

Exporter address

seller_identification_numbers

TaxIdentificationNumbers

Carrier-dependent

Seller EORI, VAT, VOEC, IOSS, etc.

sold_to

Address

Carrier-dependent

Buyer/importer address.
​Note: The region field (state/province) is required for: United States, Canada, Australia, China, Brazil, Mexico, Malaysia, New Zealand.

buyer_identification_numbers

TaxIdentificationNumbers

Carrier-dependent

Buyer EORI, VOEC, PCCC, etc.

duties_payer

Payer

No

Who pays import duties. Defaults to sender

declaration_statement

string

Carrier-dependent

Legal statement for customs processing

items

GeneralCustomsDeclarationItem[]

Yes

Line items in the declaration

GeneralCustomsDeclarationItem

Field

Type

Required

Description

name

string

Yes

Item name

sku

string

Yes

Product SKU

description

string

Recommended

Composition or material

hs_tariff_number

string

Yes

Harmonized System tariff code (6–10 digits)

country_of_origin

string

Yes

ISO Alpha-2 country code where item was manufactured

quantity

integer

Yes

Number of units

unit_value

integer (uint32)

Yes

Value per single unit in smallest currency unit (cents/öre). E.g., €128.25 = 12825. Do not send decimal values — they will be rejected

unit_net_weight

integer

Yes

Net weight per unit in grams

unit_gross_weight

integer

Recommended

Gross weight per unit in grams

brand

string

No

Item brand

category

string

No

Commodity category


FAQ

  • Do I need to send customs_declaration if I book with a TOS ID?
    Yes. A TOS ID reduces the shipment data you need to send, but cross-border shipments still require customs_declaration in every booking call.

  • What is the difference between Path 1 and Path 2?
    The customs_declaration block is identical in both. The only difference is whether shipment data is resolved from a TOS order (Path 1) or provided directly in the request (Path 2).

  • Does upsertCustomsDeclaration overwrite existing customs data?
    Yes — it is an upsert. Calling it again on the same shipment replaces the existing customs declaration.

  • Can I update the customs declaration after booking?
    No. Once bookParcels has been called, the customs declaration cannot be changed. If corrections are needed, contact your carrier directly.

  • Can booking rules fully replace my customs data?
    No. Booking rules auto-fill static per-route fields, but item-level data (HS codes, values, weights, country of origin) must always come from your systems per order.

  • I'm getting a validation error on unit_value — what format should I use?
    ​unit_value is a uint32 field and must be an integer in the smallest currency unit (cents, öre, pence). For example, €128.25 should be sent as 12825. Sending a decimal value like 128.25 will be rejected with an invalid value for uint32 field unitValue error.

  • Who do I contact to set up booking rules?
    Contact your Ingrid integration manager or ask Iris, Ingrid's AI assistant, in the chat on the Ingrid Help Center, and share your route setup and which fields are static per origin country, destination, or carrier product. Iris can hand your request over to the Ingrid team or create a ticket for you. If you can't reach Iris, email [email protected].


Related documentation

Did this answer your question?