Commercial Invoices API Tutorial
Table of contents
The Commercial Invoices API provides you with the ability to create and update an invoice, retrieve a list of your invoices, and even retrieve the details of an individual invoice.
Note that the endpoint has to be enabled on a per client basis, and requires discussion between you, the client, and your assigned broker to be enabled.
Endpoints
GET /commercial_invoices
POST /commercial_invoices
PATCH /commercial_invoices
GET /commercial_invoices/id
The Commercial Invoices JSON object is used in every HTTP request. Take a look at its elements before you go on.
You’ll need to request specific permission to access both the create and update APIs. Once you’ve received permission, you’ll create the invoice by making an HTTP POST request:
curl -X "POST" "https://api.flexport.com/commercial_invoices" \
-H "Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Flexport-Version: 3" \
-H "Content-Type: application/json" \
-d $'{
"shipment_id": 652551,
"invoice_number":"CA994444",
"currency_code": "USD",
"is_related_parties": "true",
"involved_parties": [
{
"type": "seller",
"company_entity_ref": "id-12345"
}
],
"proration_amount":
{
"amount": "4430.95",
"currency_code": "USD"
},
"line_items": [
{
"document_line_number": 1,
"purchase_order_number": "61901",
"country_of_origin": "CN",
"product_sku": "ACME-33x3d3",
"quantity": {
"value": 0,
"unit": "pcs"
},
"value": {
"amount": "12.34",
"currency_code": "USD"
},
"price_per_unit": {
"amount": "12.34",
"currency_code": "USD"
},
"gross_weight": {
"value": 2300.4,
"unit": "kg"
},
"volume": {
"value": 472.62,
"unit": "cbm"
}
}
],
"metadata": [
{
"name": "newKey",
"value": ["newValue"]
}
]
}'
The following elements are required:
- invoice_number
- currency_code
- proration_amount
- line_items
The following elements are optional:
- is_related_parties
- metadata
- involved_parties
Either shipment_id
or shipment_ref_name
(a string) can be passed along so long as only one or the other is included.
involved_parties
is composed of a type and a company_entity_ref
, which are both required within the parent object. company_entity_ref
can be used in other requests you may make later on.
type
must be one of the following:
- origin_agent
- buyer
- seller
- consignee
- shipper
- import_customs_agent
- export_customs_agent
- importer_of_record
- forwarding_agent
- destination_agent
- trucking_broker
- origin_warehouse
- destination_warehouse
"involved_parties": [
{
"type": "seller",
"company_entity_ref": "id-12345"
}
]
Since a monetary amount is an inherent element of an invoice, currency_code
is naturally required. Valid values follow standard ISO currency codes (https://en.wikipedia.org/wiki/ISO_4217).
While required, a line_items
object contains quite a few elements. It is covered here, so we’re not going to review it here.
Finally, though not required, the metadata element is an object which is a set of custom key-values (keys are strings, values are arrays of strings) which is always the consignee's list of keys. Note that the metadata keys must be configured in the Flexport UI prior to being used.
After a succesful request, you’ll recieve a response similar to this one:
{
"_object": "/api/response",
"self": "https://api.flexport.com/commercial_invoices",
"version": 3,
"data": {
"metadata": {
"newKey": "newValue"
},
"_object": "/commercial_invoice",
"id": "zpr5KZKXLOxX85z3scOKIA",
"invoice_number": "CA994444",
"digitization_status": null,
"involved_parties": [
{
"_object": "/customs/involved_party",
"address": {
"_object": "/address",
"street_address": "1234 Business Street",
"street_address2": "Suite 2",
"city": "City",
"state": "State",
"country": "Germany",
"country_code": "DE",
"zip": "65432",
"unlocode": null,
"timezone": "Europe/Berlin",
"ref": null
},
"name": "Warehouse",
"type": "seller",
"company_entity": null
}
],
"is_related_parties": true,
"line_items": [
{
"metadata": {},
"_object": "/commercial_invoice_line_item",
"document_line_number": 1,
"price_per_unit": {
"_object": "/money",
"amount": "12.34",
"currency_code": "USD"
},
"first_sale_value": null,
"value": {
"_object": "/money",
"amount": "12.34",
"currency_code": "USD"
},
"net_value": {
"_object": "/money",
"amount": "0",
"currency_code": "USD"
},
"total_units": "0.0",
"container_number": null,
"purchase_order_number": "61901",
"po_line_item_number": "",
"weight": {
"value": 2300.4,
"unit": "kg",
"_object": "/quantity/weight"
},
"volume": {
"value": 472.62,
"unit": "cbm",
"_object": "/quantity/volume"
},
"net_weight": {
"value": 0,
"unit": "kg",
"_object": "/quantity/weight"
},
"net_net_weight": {
"value": 0,
"unit": "kg",
"_object": "/quantity/weight"
},
"manufacturer_address": null,
"manufacturer_name": null,
"product": {
"_object": "/api/refs/object",
"ref_type": "/product",
"link": "https://api.flexport.com/products/9678705",
"id": 9678705
}
}
],
"manufacturer_addresses": [
{
"_object": "/address",
"street_address": "1641 Settlers Lane",
"street_address2": "STE 2918",
"city": "Albany",
"state": "MN",
"country": "United States",
"country_code": "US",
"zip": "56307",
"unlocode": "USAL2",
"timezone": "America/Chicago",
"ref": "id-312836"
}
],
"shipment": {
"_object": "/api/refs/object",
"ref_type": "/shipment",
"link": "https://api.flexport.com/shipments/652551",
"id": 652551
},
"total_unit_count": "0.0",
"total_value": {
"_object": "/money",
"amount": "12.34",
"currency_code": "USD"
},
"total_volume": {
"value": 472.62,
"unit": "cbm",
"_object": "/quantity/volume"
},
"total_weight": {
"value": 2300.4,
"unit": "kg",
"_object": "/quantity/weight"
}
},
"error": null
}
which includes summary items such as invoice_number
, total_value
, total_unit_count
, total_value
and total_weight
, as well as details including manufacturer_addresses
and line_items
, from which you’ll be able to create your invoice.
The Commercial Invoices API allows you to update your invoice should you need to. In this case, you’re sending an HTTP PATCH request whose data includes the invoice_id element to specify the desired invoice:
curl -X "PATCH" "https://api.flexport.com/commercial_invoices" \
-H "Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Flexport-Version: 3" \
-H "Content-Type: application/json" \
-d $'{
"invoice_number":"CA994444",
"currency_code":"USD",
"is_related_parties":"true",
"proration_amount":[
{
"amount":"5043.32",
"currency_code":"USD"
}
]
}'
This request shows the elements which can be updated. Other than the invoice_number, all other elements are optional. It goes without saying that you’ll want to include some changed element in addition to an invoice_number in the data section of the request, otherwise, why bother?
The response will be similar to the one received in the create example above:
{
"_object": "/api/response",
"self": "https://api.flexport.com/commercial_invoices?page=2&per=10",
"version": 2,
"data": {
"_object": "/api/collections/paginated",
"prev": "https://api.flexport.com/commercial_invoices?page=1&per=10",
"next": null,
"data": [
{
"_object": "/commercial_invoices",
"id": "abcxyz-23456-def",
"invoice_number": "ABCDEFGHIJKLMNOP",
"digitization_status": "complete",
"manufacturer_addresses": [...],
"total_value": {...},
"total_unit_count": "12345",
"total_weight": {...},
"total_volume": {...},
"line_items": [...],
"shipment": {...}
}
]
}
}
(some elements are abbreviated for brevity)
Do you need to retrieve your complete set of invoices? Make an HTTP GET request to the List commercial invoices endpoint:
curl -X "GET" "https://api.flexport.com/commercial_invoices?page=1&per=20" \
-H 'Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' \
-H 'Flexport-Version: 3' \
-H 'Accept: application/json' \
with the optional URL arguments page
and per
(the page you are requesting, and the number of items per page, respectively) to receive your list.
You'll receive the following response:
{
"_object": "/api/response",
"self": "https://api.flexport.com/commercial_invoices?page=2&per=10",
"version": 2,
"data": {
"_object": "/api/collections/paginated",
"prev": "https://api.flexport.com/commercial_invoices?page=1&per=10",
"next": null,
"data": [
{
"_object": "/commercial_invoices",
"id": "abcxyz-23456-def",
"invoice_number": "CA994444",
"digitization_status": "complete",
"manufacturer_addresses": [...],
"total_value": {...},
"total_unit_count": "12345",
"total_weight": {...},
"total_volume": {...},
"line_items": [...],
"shipment": {...}
}
]
}
}
You can filter your results using any of the following elements:
- f.shipment.id
- f.invoice_number
- f.involved_party_seller_id
- f.involved_party_seller_name
It’s quite easy to obtain the details of an invoice: append the invoice id to the URL, and make an HTTP GET request
curl -X "GET" "https://api.flexport.com/commercial_invoices/abcxyz-23456-def" \
-H 'Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' \
-H 'Flexport-Version: 3' \
-H 'Accept: application/json' \
Using it, we get back
{
"_object": "/api/response",
"self": "https://api.flexport.com/commercial_invoices/abcxyz-23456-def",
"version": 2,
"data": {
"_object": "/commercial_invoice",
"id": "abcxyz-23456-def",
"invoice_number": "CA994444",
"digitization_status": "complete",
"manufacturer_addresses": [...],
"total_value": {...},
"total_unit_count": "12345",
"total_weight": {...},
"total_volume": {...},
"line_items": [...],
"shipment": {...}
}
}
which are the details corresponding to that invoice id (again, abbreviated for clarity).
HTTP error codes, along with a description message within the JSON response, help you build your exception handling routines.
An example of an error response is shown below.
{
"_object": "/api/error",
"status": 400,
"code": "invalid_pagination",
"message": "Invalid Sort Direction. allowed values: desc, asc"
}
You’ll want to use the status
and message
fields to handle exceptions.