POST /v2/batches with a body containing 'shipments' as an array of objects; you can pass existing purchased shipment IDs using {'id': '<shipment_id>'} or include full shipment creation parameters to create-and-add in one call.
Poll GET /v2/batches/{batch_id} until 'status' is 'purchased' (if buying rates) or 'created' for pre-purchased shipments; the 'shipment_counts' sub-object shows how many are in each state.
To buy labels for all shipments in the batch, POST /v2/batches/{batch_id}/buy with body {'rate': {'carrier': '<carrier>', 'service': '<service>'}} specifying the carrier/service to use across the batch.
After all shipments are purchased, generate a ScanForm by POSTing /v2/batches/{batch_id}/scan_form; poll the batch until 'scan_form' is populated with a 'form_url'.
Download the ScanForm PDF from 'form_url' and present it to the carrier at induction to register all parcels in a single scan.
Known gotchas
ScanForms can only be generated when all shipments in the batch are purchased and use the same carrier; mixing carriers in one batch prevents ScanForm generation for that batch.
Batch operations are asynchronous; buying rates or generating a ScanForm returns immediately but completion requires polling.
There is a limit on how many shipments can be included in a single batch — check current API documentation for the per-batch shipment maximum.
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp