Vector
API Method

BOL Ingestion API

Submit a bill of lading — the document plus its key fields — and Vector files it against the right shipment. You send business identifiers; we resolve the rest.

POST
/1.0/entities/actions/ingestion/bol/ingest?ingestion_config_id=<uuid>

Bearer token

Plus an ingestion config ID

multipart/form-data

One metadata part + files

Asynchronous

Returns 202 Accepted

When to use this endpoint

Use BOL ingestion when you have a bill of lading to file and you know it by its business identifiers — BOL number, shipment number, SCAC or carrier name, PO number. Post the document and those identifiers together, and Vector resolves the carrier, customer, origin and destination on its side, then creates or updates the matching shipment document with your files attached.

The general-purpose entity API (POST /1.0/entities/records) expects a fully built entity graph: platform mixin UUIDs, file IDs that match part names, and every relationship already resolved to an internal entity ID. If you are holding a BOL number and a PDF, this endpoint is the right door.

Base URL: your Vector API host, provided with your credentials.

Authentication

Every request carries a bearer token in the Authorization header:

Header
Authorization: Bearer <your API token>

Ingestion config

The request also requires an ingestion_config_id query parameter. The ingestion config is the per-account setup that tells Vector how to handle your BOLs — which document type to file them as, and who to notify if one fails to process.

Your Vector implementation contact provisions the config and gives you its UUID during onboarding; there is no self-serve path for creating one today. The config is owned by a single firm, and requests are rejected if the token and the config belong to different firms — so treat the ID as account configuration, not as a secret you rotate.

Confirm with your implementation contact

Which document type your BOLs are filed as, and which email addresses receive failure alerts. Both are set on the config and both affect what you see downstream.

Request format

The body is multipart/form-data with exactly two kinds of part:

  • Exactly one metadata part — the shipment metadata envelope, sent as application/json. Sending zero or more than one is an error.
  • One or more document file parts — the BOL itself and any companion documents. At least one file part is required.

How files are matched to document roles

Vector matches each uploaded file by filename against the name values you declare in attachments.files[]. Declaring attachments is how you say "this PDF is the bill of lading and that one is the packing list."

If you declare no attachments, matching falls back to substrings in the filename — a file whose name contains bol is treated as the bill of lading, and one containing packing as the packing list. Declaring attachments explicitly is more predictable and is what we recommend.

File requirements

  • PDF only. Send native (digitally generated) PDFs rather than scanned images saved as PDF.
  • There is no enforced limit on file count or file size today. If you plan to send unusually large batches, let your implementation contact know.

Metadata reference

The metadata part is a JSON object with a single key, shipmentMetadata, holding an array of shipment objects. It uses the same shape as the SFTP index.json.

Envelope
{ "shipmentMetadata": [ { /* fields below */ } ] }

Reference number arrays use plural names only — deliveryNumbers, orderNumbers, poNumbers. The singular forms are no longer accepted.

Matching keys

Send at least one of bolNumber or shipmentNumber. Sending both gives the best match rate.

FieldTypeRequiredWhat it does
bolNumberstring
One of
The BOL identifier. Primary key for deduplication and for matching an appointment.
shipmentNumberstring
One of
Shipment identifier. Secondary dedupe key, and a candidate for appointment matching.

Parties

FieldTypeRequiredWhat it does
carrierIdstring
Required
Links the shipment to a carrier. Accepts a SCAC (e.g. FDXT).
carrierNamestring
Optional
Carrier display name. Used as a fallback when resolving the carrier.
shipperIdstring
Required
Links the shipment to the origin facility.
shipperstring
Optional
Shipper name or address.
customerIdstring
Optional
Unique identifier for the customer.
customerNamestring
Optional
Customer name. Used as a fallback when resolving the customer.
receiverIdstring
Optional
Unique identifier for the destination location.
receiverstring
Optional
Receiver name and location.

Identification numbers

FieldTypeRequiredWhat it does
deliveryNumbersstring[]
Optional
Delivery reference numbers. Values must be unique.
orderNumbersstring[]
Optional
Order reference numbers. Values must be unique.
poNumbersstring[]
Optional
Purchase order numbers. Values must be unique.
proNumberstring
Optional
Carrier PRO number. Written to shipment identification.
sealNumberstring
Optional
Seal number. Written to shipment identification.

Equipment

FieldTypeRequiredWhat it does
shipmentTrailerNumberstring
Optional
Trailer number. Triggers a trailer lookup once the carrier resolves.
podStatusstring
Optional
Proof of delivery status: "Not Applicable", "Pending", "Signed", or "Rejected".

Attachments

FieldTypeRequiredWhat it does
attachments.files[]object[]
Required
Each entry is { name, type }, mapping an uploaded filename to a document role: "bill of lading", "packing list", or "proof of shipment".

What blocks ingestion

Only four things are required: at least one attachment, one of bolNumber / shipmentNumber, shipperId (to link the facility), and carrierId (to link the carrier). Every other field is optional and will not block ingestion, but the more you send, the richer the shipment record.

Worked example

One BOL PDF with its metadata. Note that the PDF's filename matches a name in attachments.files[] — that is what assigns it the bill-of-lading role.

metadata.json
{
  "shipmentMetadata": [
    {
      "bolNumber": "BOL-4471902",
      "shipmentNumber": "SHP-88213",
      "carrierId": "RDWY",
      "carrierName": "YRC Freight",
      "shipperId": "PDX-DC-01",
      "shipper": "Portland DC",
      "customerName": "Northwind Foods",
      "receiver": "Reno Cross-dock",
      "deliveryNumbers": ["DL-30918"],
      "orderNumbers": ["SO-77410"],
      "poNumbers": ["PO-55120", "PO-55121"],
      "proNumber": "770114592",
      "sealNumber": "SL-0099",
      "shipmentTrailerNumber": "TRL-2210",
      "podStatus": "Not Applicable",
      "attachments": {
        "files": [
          { "name": "mybol.pdf", "type": "bill of lading" }
        ]
      }
    }
  ]
}
Request (cURL)
# metadata.json holds the shipmentMetadata envelope; the PDF filename
# must match a name in attachments.files[]
curl -X POST \
  "https://<your-vector-host>/1.0/entities/actions/ingestion/bol/ingest?ingestion_config_id=$CONFIG" \
  -H "Authorization: Bearer $TOKEN" \
  -F "metadata=@metadata.json;type=application/json" \
  -F "file=@mybol.pdf"
202 Accepted
Queued, not yet filed
Response
{
  "message": "BOL queued for ingestion",
  "ingestionConfigId": "a1b2c3d4-..."
}

The 202 body is an acknowledgement, not the created record. It confirms the submission was validated, bundled and queued — it does not tell you the shipment document was written. See After the 202.

Errors

These are returned synchronously, before anything is queued. A rejected submission has had no effect — fix the cause and resubmit.

StatusCauseFix
400
No ingestion_config_id on the query string, or no config exists with that ID.Check the parameter is present and the UUID matches the config you were given.
400
The metadata part is missing, sent more than once, or is not valid JSON.Send exactly one metadata part with content type application/json and valid JSON.
400
No document file parts in the request.Attach at least one file part alongside the metadata.
403
The ingestion config is owned by a different firm than the caller.Use the config provisioned for your account, and a token issued to the same firm.

After the 202

Processing is asynchronous. Once accepted, the request parts are bundled and handed to Vector's ingestion pipeline:

  1. 1

    Bundled and queued

    Your metadata and files are packaged together and published to the BOL ingestion queue.

  2. 2

    Entities resolved

    The pipeline resolves carrier, customer, shipper and receiver from the business identifiers you sent.

  3. 3

    Deduplicated

    Submissions are deduplicated by BOL number, then shipment number.

  4. 4

    Filed

    A shipment document is created, or an existing one updated, with your files attached.

Resubmitting the same BOL

Because deduplication is keyed on BOL and shipment number, resubmitting the same BOL updates the existing shipment document rather than creating a second one. Retrying after a network failure is therefore safe.

Attachments are replaced on resubmit

A repeat submission overwrites the attachments already on the shipment document — files are not appended. If you resubmit, include every file that should remain attached, not just the new or changed ones.

How you learn about failures

If a queued BOL fails to process, an email notice goes to the alert recipients configured on your ingestion config. Being explicit about the current limits:

  • There is no API-visible processing status — a 202 is the last thing the API tells you about a submission.
  • The response does not return the created shipment document ID, and there is no lookup endpoint for it today.
  • Make sure the alert recipient list on your config is a monitored address, not an individual's inbox.

On the roadmap, not available today

A confirmation or status path — either a synchronous variant that returns the created document ID or a status endpoint you can poll. If your integration depends on programmatic confirmation, raise it with your implementation contact so it can be weighed.

If you submitted a BOL and nothing appeared, contact Vector support with the BOL number and the approximate submission time.

Fields, status codes and behaviour on this page describe the BOL ingestion endpoint as currently implemented. If something you need isn't covered here, confirm it with your Vector implementation contact rather than inferring it from testing.