DOCS

Create a single shipment

Create a single shipment

The CreateDeclarationShipment GraphQL workflow takes a Japan Post shipment from raw inputs to a printable label in one round trip.

CreateDeclarationShipment chains together seven *Workflow mutations into a single GraphQL request. Each step builds on the data the previous steps provided, and all of them are submitted together so a complete shipment can be created in one round trip:

partyCreateWorkflow            → describe origin + destination parties
itemCreateWorkflow             → describe the line items
cartonsCreateWorkflow          → describe the physical packaging
shipmentRatingCreateWorkflow   → record the carrier rate quote
landedCostCalculateWorkflow    → calculate duties / taxes / fees
declarationCreateWorkflow      → create the customs declaration
shipmentCreateWorkflow         → create the shipment + label

The Workflow mutations are designed to be chained: you don't need to thread IDs from one step into the next, and you don't need to send a separate request per step. Submit the whole document, get the final Shipment back.

When the serviceLevel on the final step is a Japan Post service level (japan_post.*), Zonos calls the Japan Post Label API (code 52) on your behalf using your Verified Account's Later Pay Numbers, generates the label and tracking number, creates the Declaration ID, and links them — all inside that final shipmentCreateWorkflow step.

Why one mutation? Each step depends on the previous one (landed cost needs the items + parties; the declaration needs the landed cost; the label needs everything). Bundling them into a single GraphQL document keeps the data consistent and avoids six extra round trips.

Endpoint 

URL:

https://api.zonos.com/graphql

Headers:

credentialToken: {{YOUR_API_TOKEN}}
accountKey:      {{SHIPPER_API_TOKEN}}

Example request 

A complete CreateDeclarationShipment request you can copy and adapt — the mutation, its variables, and the response — for a single Japan Post parcel shipped DDP to the U.S. Each input is broken down in the step-by-step section below.

1mutation CreateDeclarationShipment(
2$partyInput: [PartyCreateWorkflowInput!]!
3$itemInput: [ItemCreateWorkflowInput!]!
4$cartonInput: [CartonCreateWorkflowInput!]!
5$shipmentRatingInput: ShipmentRatingCreateWorkflowInput!
6$landedCostInput: LandedCostWorkFlowInput!
7$declarationInput: DeclarationCreateWorkflowInput!
8$shipmentInput: ShipmentCreateWorkflowInput!
9) {
10 partyCreateWorkflow(input: $partyInput) {
11 id
12 type
13 location {
14 line1
15 locality
16 postalCode
17 countryCode
18 }
19 }
20 itemCreateWorkflow(input: $itemInput) {
21 id
22 name
23 sku
24 amount
25 currencyCode
26 hsCode
27 }
28 cartonsCreateWorkflow(input: $cartonInput) {
29 id
30 length
31 width
32 height
33 dimensionalUnit
34 weight
35 weightUnit
36 }
37 shipmentRatingCreateWorkflow(input: $shipmentRatingInput) {
38 id
39 amount
40 }
41 landedCostCalculateWorkflow(input: $landedCostInput) {
42 id
43 method
44 currencyCode
45 amountSubtotals {
46 duties
47 taxes
48 fees
49 shipping
50 landedCostTotal
51 }
52 }
53 declarationCreateWorkflow(input: $declarationInput) {
54 declaration {
55 id
56 source
57 status
58 }
59 errors {
60 code
61 message
62 }
63 }
64 shipmentCreateWorkflow(input: $shipmentInput) {
65 id
66 trackingDetails {
67 number
68 }
69 shipmentCartons {
70 label {
71 url
72 }
73 }
74 }
75}

Step-by-step 

The Status column on each table below uses these terms:

  • Required — the request fails without it.
  • Required for label — optional in the GraphQL schema, but needed to produce a valid Japan Post U.S. label.
  • Conditional — required depending on another field (noted inline).
  • Recommended — optional, but drives accurate duties and taxes.
  • Optional — not needed.

1. partyCreateWorkflow

Creates the parties involved in the shipment — at minimum an ORIGIN (where the shipment ships from) and a DESTINATION (the buyer / consignee).

FieldStatusNotes
typeRequiredORIGIN, DESTINATION, RETURN, etc.
location.countryCodeRequiredISO-2 country code.
location.line1, locality, administrativeAreaCode, postalCodeRequired for labelAddress fields needed for a valid label.
person.firstName, lastName, phoneRequired for labelContact details needed for a valid label.
person.companyName, emailOptional

Example payload:

[
  { "type": "DESTINATION", "location": { "countryCode": "US" }, "person": {} },
  { "type": "ORIGIN", "location": { "countryCode": "JP" }, "person": {} }
]

The response returns the created Party IDs and resolved address fields.

2. itemCreateWorkflow

Creates the line items that make up the shipment. These are the SKUs that will appear on the commercial invoice and drive the landed-cost calculation.

FieldStatusNotes
currencyCodeRequiredCurrency of the unit price.
quantityRequiredNumber of units of this item.
amountConditionalUnit price (not total). Required unless totalAmount is provided.
totalAmountOptionalAlternative to amount; amount is derived from totalAmount / quantity.
hsCodeRecommendedHarmonized System tariff code. Drives duty rates.
countryOfOriginRecommendedISO-2 code where the item was made. Drives duty / FTA.
name, descriptionRecommendedCustomer-facing product name + description.
customsDescriptionOptionalCustoms description override.
sku, productIdOptionalYour internal identifiers.
measurementsOptionalPer-unit weight / dimensions.

The HS code, country of origin, and amount are the three fields that most influence the duty/tax outcome in step 5.

3. cartonsCreateWorkflow

Creates the physical packages — the boxes, polybags, or letters that will hold the items.

FieldStatusNotes
dimensionalUnitRequiredINCH or CENTIMETER.
weight, weightUnitRequired for labelJapan Post requires package weight.
length, width, heightOptionalOuter dimensions.
typeOptionalPackaging style (box, polybag, letter). Defaults to PACKAGE.

Each carton becomes one parcel on the carrier label in step 7. Multiple cartons → multi-piece shipment with one tracking number per carton.

4. shipmentRatingCreateWorkflow

Records the rate quote the merchant is charging the buyer for shipping.

FieldStatusNotes
amountRequiredWhat the buyer is paying for shipping. Pass 0 if free.
currencyCodeRequiredCurrency of amount.
serviceLevelCodeRequiredCarrier service code (e.g. japan_post.air.parcel).
displayNameOptionalPretty name for the receipt / invoice.

This is the rate the buyer was quoted at checkout. It feeds into the landed-cost calculation as the "shipping" subtotal so duties and taxes are computed against the correct CIF value.

5. landedCostCalculateWorkflow

Runs the duties, taxes, and fees calculation for the destination country. Uses the items, parties, and shipping cost from the prior steps.

FieldStatusNotes
endUseRequiredNOT_FOR_RESALE or FOR_RESALE. Some destinations apply different rates for commercial vs personal end use.
tariffRateRequiredDefaults to ZONOS_PREFERRED if omitted. Tells Zonos which tariff source/methodology to apply.
calculationMethodRecommendedDDP (buyer prepays) or DDU (buyer pays at the door). Use DDP for prepaid. Drives whether LandedCost.amountSubtotals includes duty/tax.
currencyCodeOptionalCurrency the landed-cost subtotals are returned in.
arrivalDateOptionalFX rates and tariff schedules are pinned to this date if provided.

The response includes amountSubtotals (duties, taxes, fees, shipping, landedCostTotal) — these are the numbers you display to the buyer at checkout and that get printed on the commercial invoice.

6. declarationCreateWorkflow

Creates a Declaration — an identifier required to clear the package into the destination country under current customs regulations.

FieldStatusNotes
sourceRequiredPOST, PREPAY, ZONOS, or DIRECT. In this flow, use DIRECT.
landedCostIdsOptionalUsually omitted here because the previous step already produced a landed cost.

The response returns a Declaration with an id, source, and status, or a list of errors. The id is what's needed for the shipment to be accepted; nothing else from this step is consumed by the caller in this flow.

7. shipmentCreateWorkflow

The terminal step — creates the Shipment entity, generates the carrier label, and (optionally) the commercial invoice / packing slip.

For Japan Post Verified Accounts, this is also where Zonos calls the Japan Post Label API (code 52) on your behalf, injects your Later Pay Numbers, creates the Declaration ID, and links the Declaration ID to the tracking number returned by Japan Post.

Key fields:

FieldStatusNotes
serviceLevelRequired for labelThe Japan Post service to ship with (e.g. japan_post.air.ems_merchandise). Must be a japan_post.* service level.
generateLabelOptionalDefaults to true; must be true to return a label.
contentsTypeRecommendedSALE_OF_GOODS, GIFT, DOCUMENTS, SAMPLE, etc. Drives customs treatment.
nonDeliveryOptionalWhat the carrier should do if delivery fails: RETURN, ABANDON, FORWARD.
referencesOptionalMerchant-supplied reference numbers printed on the label and commercial invoice. See below.
declaredValue / isDeclaredValueOptionalInsurance value for the shipment.
shipmentConsolidationIdOptionalUsed when this shipment is part of a batch dispatch.

references sub-input

These fields print on the carrier label and/or commercial invoice. Use them to surface PO numbers, license numbers, and free-text remarks the consignee or customs authority needs to see.

FieldStatusNotesLength
invoiceNumberOptionalMerchant invoice number.
purchaseOrderNumberOptionalMerchant PO number.
licenseNumberOptionalExport/import license number.
certificateNumberOptionalCustoms certificate number.
paymentConditionsOptionalFree-text terms-of-payment shown on the commercial invoice.Limit to 200 characters — longer values overflow on the printed invoice.
customsRemarksOptionalFree-text customs remarks.
taxCodeOptionalCustom tax code printed on the label.

Response

The interesting fields on the returned Shipment are:

{
  id
  trackingDetails {
    number
  }
  shipmentCartons {
    label {
      url
      labelImage
    }
  }
}

trackingDetails.number is the Japan Post tracking number.

The label object can return the label two ways — request whichever fits your workflow (or both):

FieldReturnsUse when
urlA hosted link to the rendered label file (PDF), ready to download or print.You want to hand off a link — open it, email it, or fetch the file later without holding it in the payload.
labelImageThe base64-encoded label image (PNG/PDF/ZPL) inline in the response.You want the label bytes directly in the response to attach to a fulfillment workflow or save to your WMS.

Select only the fields you need. Requesting url keeps the response small; requesting labelImage returns the full label inline so you don't need a second round trip to fetch it. The example above requests url.

Error handling 

  • Validation errors (missing required fields, invalid country codes, etc.) come back in the standard GraphQL errors array and abort the rest of the chain.
  • Declaration errors (e.g. unsupported source) surface inside declarationCreateWorkflow.errors rather than the top-level errors array, so always check both.
  • Japan Post errors (label generation failure, invalid address, etc.) surface as GraphQL errors on shipmentCreateWorkflow. If a retry is needed, contact support — the recommended path is to resubmit the full mutation with corrected input.

Permissions 

Each step is independently secured. Your API key must hold the write scope for each entity in the chain (ITEM_WRITE, CARTON_WRITE, SHIPMENT_RATING_WRITE, LANDED_COST_WRITE, DECLARATION_WRITE, SHIPMENT_WRITE). The standard merchant role on a Verified Account grants all of these.

Next steps 

Book a demo

Was this page helpful?