LLM Integration Guide
This guide takes an AI agent, or a developer, through a whole integration with the Stream API: signing in, pricing a shipment, booking it, getting it collected and following it to delivery. Every call is linked to its reference page, which has the fields, real examples and code in six languages.
Read these first
/llms.txtlists every page./llms-full.txtholds every page in one file.- Every page has a Markdown version: add
.mdto its address, such as/reference/create-a-quote.md. - The OpenAPI file describes every call, field and answer.
Before you start
- Two environments. Build and test against the sandbox,
https://sandbox-api.vatit-stream.com/client_api/v2, then switch to production,https://orders-production.vatit-stream.com/client_api/v2. The sandbox's carriers are stand-ins, so nothing is shipped or charged. - The client's own logins. We send each client a sandbox login when they're ready to connect, and a production login when they go live. Ask the client for them. Never put them in code; read them from the environment.
- JSON in, JSON out. Send
Content-Type: application/jsonwith a body, except when the order carries files (see step 4). - Call from a server. Keep the login and token out of browsers and mobile apps.
The integration, step by step
1. Sign in
Sign in with the login's email and password. Send the token from the answer on every other call as Authorization: Bearer <token>. A token lasts a week. When a call answers 401, sign in again and repeat the call. See Authentication.
2. Look up the ids you need
Many fields take an id from another call, and ids differ between the sandbox and production. Look them up in the environment you are calling, and keep them per environment.
| You need | Look it up with |
|---|---|
| A country, for addresses and items | List countries ?q=South Africa |
An incoterm (purpose_of_shipment_id) | List purposes of shipment ?code=DDP. It lists only the incoterms the client may use. |
| A reason for shipment | List reasons for shipment ?q=commercial |
| A currency | List currencies. Currencies go by their three-letter code, such as ZAR. |
| A nature of transaction for an item | List natures of transaction ?code=11 |
3. Price the shipment
Create a quote with the addresses, packages, items (hs_codes) and value. The answer's estimates hold one price for each carrier that can take the shipment. Keep the quote's id and the estimate_id you choose.
- Set
estimate_taxes_and_dutiestotrueto include the import duties and taxes we estimate. See Taxes and duties. - Set
hub_transittotrueto route through one of our hubs. See Hub shipments.
4. Book the shipment
Create an order from the chosen estimate_id. Send a customer_reference that is unique to this order, such as the client's purchase order number. It is how you find the order again if the call times out (see Retrying safely).
To send a commercial invoice, packing list or safety data sheet, include them in this request as a multipart/form-data upload. The API can't add them later. See Sending documents. Without a commercial invoice, we make one from the shipment's items.
Keep the order's id. It starts as order_received.
5. Get the waybill
Call Create a waybill yourself. An order made through the API waits in order_received until you do.
-
A success answers with the order, and its
waybillholds the carrier's tracking number. -
When it can't be made yet, the answer says why, and the order moves to one of these:
awaiting_additional_documentation: a document is missing;awaiting_prepayment: a pro forma invoice needs paying;awaiting_waybill_generation: our team is checking it.
Order statuses says what to do in each.
-
Never send it twice without checking. A second call books the carrier again. After a timeout, read the order with Get an order, and call again only if it has no
waybill. On a hub order check everyshipments[].waybill: the order's ownwaybillis its last shipment's, but the call books every leg.
6. Book the collection
List pickup slots gives the days and times the carrier collects. Book a pickup in one of them. The order moves to awaiting_pickup, then to in_transit once the carrier has the goods.
Booking again cancels the earlier pickup. To check what's booked, use List pickups.
7. Follow it to delivery
- Webhooks tell you about some status changes and every waybill change; Receiving webhooks says which. Set one up with Create a webhook, and read Receiving webhooks for what we send and how to check it.
- Poll as well. Webhooks say nothing for the other statuses, and events can be lost if your server is down. Check open orders with List orders, filtered with
?status=, or Get an order. - Tracking: List tracking events gives the carrier's scans, newest first. The order's
tracking_linkopens the carrier's own tracking page.
8. Cancel if needed
Cancel an order works while every shipment is still before pickup.
What each status asks of you
Order statuses says what each status means and what to do in it.
Errors
Every error answers { "success": false, "error": "...", "errors": [...] }. Errors says what each status means and what to retry, and Retrying safely covers timeouts.
Before going live
- Test the whole flow on the sandbox with the client's sandbox login.
- Send a unique
customer_referencewith every order. - Never retry Create a waybill without reading the order first.
- Check the
tokenon every webhook event, answer2xxquickly, and ignore repeats. - Poll open orders as well as receiving webhooks.
- Keep ids, logins and tokens per environment. Switch the base URL and the login together.