Logistra Cargonizer is used by thousands of companies and is one of the leading providers for freight related EDI solutions in Norway. The Cargonizer API allows you to programmatically interact with the Cargonizer services, which in turn can estimate freight costs, generate shipments and print labels etc. for hundreds of carriers. It is an HTTP REST interface divided into distinct resources, each documented separately.
The business of shipping is a complicated one, but we try to make it less complicated for you. A common use case goes something like this: You want to send parcels from point A to point B. Often, A is you and B is your customer. You may want to know what it's going to cost you and maybe present that price to your customer. You put this into our system, which takes care of the nitty gritty of it, and you deliver or someone picks up the parcels for you.
For a minimal, simple workflow like this, these are the steps you would have to take:
These definitions are used throughout the documentation and are entities you will be coming across as you implement an application using the API.
Your user account. Everything you do in Cargonizer you do as a user, and you authenticate your access to it using a password or an API key.
Also referred to as Sender. Most likely the same as your company. It is a basic entity, like your user account; your user account can be associated with more than one sender , and most actions you take in Cargonizer happen in the context of a sender. You create a consignment for a sender, and that sender becomes the consignor for that consignment.
A shipment containing all information about the nature of the cargo, detailed parcel information, transport services and addresses of different parties involved in the shipment. A shipment can have many individual parcels, referred to as parcels, items of pieces in Cargonizer (yes, we know it can be confusing, we're working on it).
A company or person with a role in the consignment/shipment. Examples are consignor, consignee, third-party freight payer, delivery part, pick up address.
The party that receives the consignment. The name and address of the receiving part.
A carrier is the party responsible for actually moving your consignment from its origin to its destination. Exmples of carriers are Bring and Postnord.
Each carrier offers different products. They can have different priorities, freight prices and methods for delivery. Examples are Home Delivery, Service Parcels, Express, Road Groupage.
Each Consignor (sender) needs to have an agreement with the chosen carrier before shipping. The Consignor has at least one agreement number with each of the carriers they will use for transport of goods. The information about the shipment will be sent electronically to the carrier. The receiving systems at the carriers side needs to know who is sending this information. The transport agreement number is often used for this purpose
To access most resources, you must be authenticated. Authentication is done using an API key associated with your user account; additionally, many resources require that you tell them which sender you represent. Both the API key and sender ID are passed as custom HTTP headers.
To authenticate your request, you must supply your API key, a long string of numbers and letters (hexadecimal representation of an integer) that you can find by going to the Preferences pane when you're logged into the Cargonizer web interface. This key is associated with your user account and is a secret (treat it like a password).
You need an Cargonizer Account to get access to you API key. Please choose a plan and register first, if that's not the case. If you are a developer you can get a test account in our test enviroment (sandbox) by registering for one here.
The HTTP header containing your API key must be named X-Cargonizer-Key, as in the examples below.
Example: Requesting your user profile as an XML document.
cURL:
curl -g -XGET -H'X-Cargonizer-Key: 12345' 'https://cargonizer.no/profile.xml'
HTTP:
GET /profile.xml HTTP/1.1
Host: cargonizer.no
X-Cargonizer-Key: 12345
Pseudocode:
http = new HTTPRequest();
http.method = 'GET';
http.url = 'https://cargonizer.no/profile.xml';
http.headers.add('X-Cargonizer-Key', '12345');
response = http.execute();
In a lot of cases, Cargonizer needs to know which sender you're operating as, as it's possible for one user to have access to more than one sender. When using the API, you supply the sender's ID using an HTTP header just like you supply your API key. You can find a list of sender IDs for your user in the web interface under Preferences, just like your API key.
Note: While we refer to it as a sender ID in this and other documents, the ID you must supply actually represents the relationship between your user and a sender. Thus, the "sender ID" for a sender is different for each of that sender's associated users.
The HTTP header containing the sender ID must be named X-Cargonizer-Sender.
Example: Requesting a list of transport agreements for a sender.
cURL:
curl -g -XGET -H'X-Cargonizer-Key: 12345' -H'X-Cargonizer-Sender: 678' 'https://cargonizer.no/transport_agreements.xml'
HTTP:
GET /profile.xml HTTP/1.1
Host: cargonizer.no
X-Cargonizer-Key: 12345
Pseudocode:
http = new HTTPRequest();
http.method = 'GET';
http.url = 'https://cargonizer.no/profile.xml';
http.headers.add('X-Cargonizer-Key', '12345');
response = http.execute();
Note: For a resource that requires a sender ID, you will also have to supply an API key. All requests that happen in the scope of a sender must be authenticated by a user allowed to act as that sender.
The API works over plain HTTP following REST conventions. You can list, get, create, update and delete resources using standard HTTP. The following table uses the customer resource as an example:
Action | HTTP method | Path |
---|---|---|
List customers | GET | /customers.xml |
Get customer with ID 1 | GET | /customer/1.xml |
Create a customer | POST | /customers.xml |
Update customer with ID 1 | PUT | /customers/1.xml |
Delete customer with ID 1 | DELETE | /customers/1.xml |
All programming environments have tools for making HTTP requests. In the examples below I'll use pseudocode and in addition show how to make the same request using the command-line tool cURL. We'll continue using the customer example.
To run these examples, you need to be authenticated and to provide a sender ID. You may also want to use the sandbox to play around without putting your real data at risk. I will be using the sandbox URL in the examples.
All programming environments have tools for making HTTP requests. In the examples below I'll use pseudocode and in addition show how to make the same request using the command-line tool cURL. We'll continue using the customer example.
To run these examples, you need to be authenticated and to provide a sender ID. You may also want to use the sandbox to play around without putting your real data at risk. I will be using the sandbox URL in the examples.
All data to and from the Cargonizer API must use UTF-8. You should include the charset in your content type header:
Content-Type: application/xml;charset=utf-8
If you're sending XML you should also specify that it's UTF-8 in the declaration:
<?xml version="1.0" encoding="UTF-8" ?>
cURL is a widespread command-line tool for performing HTTP requests. Basic usage takes the form curl [arguments] [url] and here are some of the arguments you will run into throughout these documents:
cURL is very handy when getting to know a webservice; you see exactly what is going on between you and the server and you have complete control over what's getting sent.
cURL
curl -g -XGET -H'X-Cargonizer-Key: 12345' -H'X-Cargonizer-Sender: 678' 'https://sandbox.cargonizer.no/customers.xml'
HTTP:
GET /customers.xml HTTP/1.1
Host: sandbox.cargonizer.no
X-Cargonizer-Key: 12345
X-Cargonizer-Sender: 678
Pseudocode
http = new HTTPRequest();
http.method = 'GET';
http.url = 'https://sandbox.cargonizer.no/customers.xml';
http.headers.add('X-Cargonizer-Key', '12345');
http.headers.add('X-Cargonizer-Sender', '678');
response = http.execute();
cURL
curl -g -XGET -H'X-Cargonizer-Key: 12345' -H'X-Cargonizer-Sender: 678' 'https://sandbox.cargonizer.no/customers/1.xml'
HTTP
GET /customers/1.xml HTTP/1.1
Host: sandbox.cargonizer.no
X-Cargonizer-Key: 12345
X-Cargonizer-Sender: 678
Pseudocode
http = new HTTPRequest();
http.method = 'GET';
http.url = 'https://sandbox.cargonizer.no/customers/1.xml';
http.headers.add('X-Cargonizer-Key', '12345');
http.headers.add('X-Cargonizer-Sender', '678');
response = http.execute();
cURL
curl -g -XPOST -d@customer.xml -H'X-Cargonizer-Key: 12345' -H'X-Cargonizer-Sender: 678' 'https://sandbox.cargonizer.no/customers.xml'
HTTP
POST /customers.xml HTTP/1.1
Host: sandbox.cargonizer.no
X-Cargonizer-Key: 12345
X-Cargonizer-Sender: 678
<contents of file "customer.xml">
Pseudocode
http = new HTTPRequest();
http.method = 'POST';
http.url = 'https://sandbox.cargonizer.no/customers.xml';
http.headers.add('X-Cargonizer-Key', '12345');
http.headers.add('X-Cargonizer-Sender', '678');
http.body = new File('customer.xml').read();
response = http.execute();
cURL
curl -g -XPUT -d@customer.xml -H'X-Cargonizer-Key: 12345' -H'X-Cargonizer-Sender: 678' 'https://sandbox.cargonizer.no/customers/1.xml'
HTTP
PUT /customers/1.xml HTTP/1.1
Host: sandbox.cargonizer.no
X-Cargonizer-Key: 12345
X-Cargonizer-Sender: 678
<contents of file "customer.xml">
Pseudocode
http = new HTTPRequest();
http.method = 'PUT';
http.url = 'https://sandbox.cargonizer.no/customers/1.xml';
http.headers.add('X-Cargonizer-Key', '12345');
http.headers.add('X-Cargonizer-Sender', '678');
http.body = new File('customer.xml').read();
response = http.execute();
cURL
curl -g -XDELETE -H'X-Cargonizer-Key: 12345' -H'X-Cargonizer-Sender: 678' 'https://sandbox.cargonizer.no/customers/1.xml'
HTTP
DELETE /customers/1.xml HTTP/1.1
Host: sandbox.cargonizer.no
X-Cargonizer-Key: 12345
X-Cargonizer-Sender: 678
Pseudocode
http = new HTTPRequest();
http.method = 'DELETE';
http.url = 'https://sandbox.cargonizer.no/customers/1.xml';
http.headers.add('X-Cargonizer-Key', '12345');
http.headers.add('X-Cargonizer-Sender', '678');
response = http.execute();
Errors can occur at different levels. Sometimes it's an authentication error, sometimes the request parameters are missing some required information and sometimes there's a bug. Interacting with an API, you're going to have to handle errors; this document outlines how Cargonizer behaves when an error occurs.
The first thing to check is the HTTP status code. If it's not in the 200 range (or a 302 redirect), you've got an unexpected result to deal with. Here are some of the status codes we use:
In addition to the status code, there will be an error message. If you've requested to be informed with XML (url ends with ".xml"), the error messages will follow a common structure:
<errors>
<info> ... </info>
<error>Error 1</error>
<error>Error 2</error>
</errors>
That is, an <errors> element with one or more <error> elements containing an error description. In addition, an <info> element will be present with information to help debugging what's wrong. It can look something like this:
<errors>
<info>
<request-id>92bd1c0fb905197d165a515cf82f2a0f</request-id>
<user>
<id>5432</id>
<username>apiuser@company.com</username>
</user>
<managership>
<id>4567</id>
<sender>
<id>7890</id>
<name>Joe's Garage</name>
</sender>
</managership>
</info>
<error>Missing transport agreement</error>
</errors>
Fjern denne sub page
<!--Alway begin with a <consignments> element. It is required.-->
<consignments>
<consignment transport_agreement="1433" print="false" estimate="false">
<!--
transport_agreement: Required. Unique per consignor.
You can use the transport_agreement resource to get a valid
list of agreements or contact Logistra if this is out of your reach.
print: Deprecated. It is recommended to implement and use our printing API
and keep this set to "false". Using our printing API will give you a
better control and it is imperative to use the printing api if the
sender has more than one DirectPrint.
estimate: Optional. If set to “true” Cargonizer will try to calculate the freight costs.
-->
<product>mypack</product>
<!--
Required. An identifier that specifies the transport product you want to use.
This resource will give you a list to choose from.
For more details, see this list of valid identifiers
-->
<parts>
<!--
Every party on the consignment comes under this element. Possible parties are:
<consignee> Required. The party that will receive the packages.
<service_partner> Optional. Required if using Postnord MyPack Collect,
Return Dropoff or Mypack Home Small product.
The pick-up point that this consignment will be delivered to.
Consignee will pick up the parcels at this address.
Use the service_partners.xml to get a correct servicepartner.
<return_addres> Optional. A xml received without a return address will null the
return-to data that is registered back-end. In most cases
this carrier then will use the consignor part as return address,
but not always. Adding a specific return address will then
make sure all returns are returned correctly.
<freight_payer_address> Optional. Only to be used when an external party pays freight.
-->
<consignee>
<name>Ola Nordmann</name>
<address1>Gata 24</address1>
<postcode>0256</postcode>
<city>Oslo</city>
<country>NO</country>
<email>asfd@asfd.no</email>
<mobile>99999999</mobile>
</consignee>
<service_partner>
<number>3265576</number>
<name>Extra Brandbu</name>
<address1>Torgvegen 3</address1>
<postcode>2760</postcode>
<city>BRANDBU</city>
<country>NO</country>
</service_partner>
</parts>
<items>
<item type="Package" amount="1" weight="1" volume="15" description="Varer"/>
</items>
<services>
<service id="schenker_privatlevering"\>
</services>
<references>
<consignor>183032</consignor>
<consignee>183032</consignee>
</references>
</consignment>
</consignments>
The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.
A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!
Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.
A transport agreement represents an agreement between you and a carrier to transport your goods. To create a consignment you must supply the ID of a valid transport agreement for the carrier and product you want to use.
cURL
curl -g -XGET -H'X-Cargonizer-Key: 12345' -H'X-Cargonizer-Sender: 678' 'https://cargonizer.no/transport_agreements.xml'
HTTP
GET /transport_agreements.xml HTTP/1.1
Host: cargonizer.no
X-Cargonizer-Key: 12345
X-Cargonizer-Sender: 678
Pseudocode
http = new HTTPRequest();
http.method = 'GET';
http.url = 'https://cargonizer.no/transport_agreements.xml';
http.headers.add('X-Cargonizer-Key', '12345');
http.headers.add('X-Cargonizer-Sender', '678');
response = http.execute();
<transport-agreements>
<transport-agreement>
<id>1</id>
<description>Standard</description>
<number>12345</number>
<carrier>
<identifier>bring</identifier>
<name>Bring</name>
</carrier>
<products>
<product>
<identifier>bring_bedriftspakke</identifier>
<name>Bedriftspakke</name>
<services>
<service>
<identifier>bring_oppkrav</identifier>
<name>Postoppkrav</name>
<attributes>
<attribute>
<identifier>amount</identifier>
<type>float</type>
<required>true</required>
<min>50</min>
<!-- Minimum value for this attribute -->
<max>5000</max>
<!-- Maximum value for this attribute -->
</attribute>
<attribute>
<identifier>currency</identifier>
<type>string</type>
<required>true</required>
<!-- Allowed values for this attribute -->
<values>
<value description="Norway NOK">nok</value>
<value description="Sweden SEK">sek</value>
<value description="Denmark DKK">dkk</value>
</values>
</attribute>
</attributes>
</service>
</services>
</product>
</products>
</transport-agreement>
</transport-agreements>
You can filter the returned list of transport agreements by supplying a carrier or product identifier.
cURL
curl -g -XGET -H'X-Cargonizer-Key: 12345' -H'X-Cargonizer-Sender: 678' 'https://cargonizer.no/transport_agreements.xml?carrier_id=bring'
HTTP
GET /transport_agreements.xml?carrier_id=bring HTTP/1.1
Host: cargonizer.no
X-Cargonizer-Key: 12345
X-Cargonizer-Sender: 678
Pseudocode
http = new HTTPRequest();
http.method = 'GET';
http.url = 'https://cargonizer.no/transport_agreements.xml?carrier_id=bring';
http.queryStringParameters.set('carrier_id', 'bring');
http.headers.add('X-Cargonizer-Key', '12345');
http.headers.add('X-Cargonizer-Sender', '678');
response = http.execute();
cURL
curl -g -XGET -H'X-Cargonizer-Key: 12345' -H'X-Cargonizer-Sender: 678' 'https://cargonizer.no/transport_agreements.xml?product_id=bring_servicepakke'
HTTP
GET /transport_agreements.xml?product_id=bring_servicepakke HTTP/1.1
Host: cargonizer.no
X-Cargonizer-Key: 12345
X-Cargonizer-Sender: 678
Pseudocode
http = new HTTPRequest();
http.method = 'GET';
http.url = 'https://cargonizer.no/transport_agreements.xml?product_id=bring_servicepakke';
http.queryStringParameters.set('product_id', 'bring_servicepakke');
http.headers.add('X-Cargonizer-Key', '12345');
http.headers.add('X-Cargonizer-Sender', '678');
response = http.execute();
To estimate the cost of shipping your goods, you can use this resource.
Requesting a cost estimation for a consignment
cURL
curl -g -XPOST -d@consignment.xml -H'X-Cargonizer-Key: 12345' -H'X-Cargonizer-Sender: 678' 'https://cargonizer.no/consignment_costs.xml'
HTTP
POST /consignment_costs.xml HTTP/1.1
Host: cargonizer.no
X-Cargonizer-Key: 12345
X-Cargonizer-Sender: 678
<contents of file "consignment.xml">
Pseudocode
http = new HTTPRequest();
http.method = 'POST';
http.url = 'https://cargonizer.no/consignment_costs.xml';
http.headers.add('X-Cargonizer-Key', '12345');
http.headers.add('X-Cargonizer-Sender', '678');
http.body = new File('consignment.xml').read();
response = http.execute();
The contents of consignment_costs.xml are the same as those for creating a consignment.
<consignments>
<consignment transport_agreement="12345">
<product>bring2_business_parcel</product>
<parts>
<consignee>
<name>Juan Ponce De Leon</name>
<country>NO</country>
<postcode>1337</postcode>
</consignee>
</parts>
<items>
<item type="package" amount="1" weight="12" volume="27"/>
</items>
</consignment>
</consignments>
Note: Weight in kg. Volume in dm3.
Gross amount is the freight price without your transport agreement and net amount is the freight price calculated by using your transport agreement.
<consignment-cost>
<gross-amount type="float">96.25</gross-amount>
<!-- Gross price -->
<net-amount type="float">55.30</net-amount>
<!-- Net price -->
</consignment-cost>
These parameters tell us which carrier's service points to query. The carrier parameter is required. product and transport_agreement_id are recommended and will provide more accurate results in some cases.
Find service points close to this address. country and postcode are always required; the rest are recommended to provide more accurate results.
Some carriers accept custom parameters. These are provided using the custom top-level parameter, and nested parameters are encoded using custom[sub1][sub2]=value.
In particular, some custom parameters are passed through to the carrier's API using custom[params]. These parameters will override any dynamically derived parameters, e.g. given address=123 Some street, the derived streetNumber API parameter "123" can be overridden using custom[params][streetNumber]=321 (assuming that the carrier's API uses that parameter).
The API does not require authentication, but it is strongly recommended to both authenticate and provide a Sender ID for more functionality and accuracy.
GET https://cargonizer.no/service_partners.xml?carrier=bring&country=NO&postcode=1337
GET https://cargonizer.no/service_partners.xml?carrier=bring&product=bring_servicepakke&transport_agreement_id=000&country=NO&postcode=1337
The carrier parameter can be omitted when transport_agreement_id is given, as the carrier can be derived from it.
GET https://cargonizer.no/service_partners.xml?transport_agreement_id=000&product=bring_servicepakke&country=NO&postcode=1337
Authentication required
Using transport_agreement_id requires authentication and a Sender ID.
GET /service_partners.json?transport_agreement_id=000&product=bring_servicepakke&country=NO&postcode=1337
X-Cargonizer-Key: 1234567890
X-Cargonizer-Sender: 1234
GET https://cargonizer.no/service_partners.xml?transport_agreement_id=000&product=bring_servicepakke&country=NO&postcode=1337&custom[params][pickupPointType]=locker
GET https://cargonizer.no/service_partners.xml?transport_agreement_id=000&product=postnord_mypack&country=NO&postcode=1337&custom[params][typeId]=2
GET https://cargonizer.no/service_partners.xml?transport_agreement_id=000&product=helthjem_mypack&country=NO&postcode=1337&custom[params][transportSolutionId]=3&custom[params][shopId]=1234
You may send a POST request to the endpoint with a Content-Type: applicaiton/json header and the parameters encoded in a JSON body.
curl \
-XPOST \
-H'Content-Type: application/json' \
https://cargonizer.no/service_partners.json \
-d @- <<'EOF'
{
"carrier": "bring",
"country": "NO",
"postcode": "1337",
"custom": {
"params": {
"pickupPointType": "manned"
}
}
}
EOF
Some consignments require that Terms of Delivery (TOD) be specified. Only cod is required.
<consignment>
<tod code="EXW" country="SE" postcode="100 05" city="Stockholm"/>
</consignment>
List of valid TOD codes
Code | Description |
---|---|
EXW | Ex Works |
FCA | Free Carrier seller's premises |
CPT | Carriage Paid To buyer's premises |
CIP | Carriage and Insurance Paid to buyer's premises |
DAT | Delivered At Terminal |
DAP | Delivered At Place |
DDP | Delivered buyer's premises Duty Paid |
FAS | Free alongside ship |
FOB | Free on board |
CFR | Cost and freight |
CIF | Cost insurance and freight |
The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.
A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!
Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.
The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.
A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!
Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.
The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.
A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!
Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.
The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.
A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!
Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.
The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.
A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!
Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.
Please follow the link below and ask for a test account. After a short while we will have created your account and you will have received your username and password.
Our sandbox environment is the place to safely explore, learn, demo, develop, and test the service without the risk of affecting the data and settings of your production environment. The sandbox environment includes all carriers with dummy freight agreements.
Postman is a third party app which can be used for easy validating your API requests and resources. We have created a collection which covers most parts of our API here and this tool might be useful in your initial development.
This Postman Collection run towards our live environment (https://cargonizer.no). Make sure to change your endpoint to https://sandbox.cargonizer.no if your account is located in our test environment (Sandbox) when testing your own requests.
Logistra AS is not affiliated with Postman in any way. Please contact Postman directly if you encounter any issues using this application.