Courier Manifest

The Courier Manifest API enables courier partners to submit manifest data for customs processing. Supports single uploads, chunked uploads for large files (25MB+), and complete pipeline monitoring with 4-stage processing.

All endpoints require authentication via Bearer token. For JSON webhook API, always use default as the courier slug.

Base Path: /api/v1/couriers

Courier codes

The {courier} slug in the webhook URL selects the field mapping applied to your payload. For the JSON webhook API always use default — Excel slugs expect human-readable column headers ("Consignee Name"), not JSON fields (consigneeName). Using an Excel slug for a JSON request is the most common cause of failed imports.

CodeUse ForDescription
defaultJSON APIStandard JSON webhook (recommended)
bfeExcel onlyBFE Excel file conversion
goluckyExcel onlyGoLucky Excel file conversion
360lionExcel only360Lion Excel file conversion
n24Excel onlyN24 Excel file conversion
nohsExcel onlyNoHS Excel file conversion
mercadolibreExcel onlyMercadoLibre Excel file conversion
mailamericasExcel onlyMailAmericas Excel file conversion

POST/v1/couriers/{courier}/manifests/webhook

Submit manifest

Submit a courier manifest for customs processing. Supports both single and chunked uploads.

Path parameters

  • Name
    courier
    Type
    string
    Description

    Courier code. Use default for JSON API.

Headers

  • Name
    Idempotency-Key
    Type
    string
    Description

    UUID to prevent duplicate processing.

  • Name
    X-Signature
    Type
    string
    Description

    HMAC SHA256 signature: sha256={hex_signature}.

Required attributes

  • Name
    mawbNumber
    Type
    string
    Description

    Master Air Waybill number. Max 50 characters.

  • Name
    items
    Type
    array
    Description

    Array of manifest items (min 1 item).

Optional attributes (manifest)

  • Name
    manifestNumber
    Type
    string
    Description

    Manifest identifier. Defaults to mawbNumber. Max 100 characters.

  • Name
    batchId
    Type
    string
    Description

    Opt-in for Update Mode. When provided, updates the existing batch in place instead of creating a new one. Max 100 characters.

  • Name
    airline
    Type
    string
    Description

    Airline code or name (e.g., "AA", "LATAM"). Max 100 characters.

  • Name
    flightNumber
    Type
    string
    Description

    Flight number. Max 50 characters.

  • Name
    aircraftRegistration
    Type
    string
    Description

    Aircraft registration. Max 50 characters.

  • Name
    originAirport
    Type
    string
    Description

    Origin airport IATA code. Max 5 characters.

  • Name
    customsBrokerCode
    Type
    string
    Description

    Customs broker code. Max 50 characters.

  • Name
    batchId
    Type
    string
    Description

    Opt-in for Update Mode (idempotent re-imports). When provided, the webhook updates the existing batch in place instead of creating a new one. The batch must belong to the authenticated partner — otherwise the request returns 422 unknown_batch, and a batch closed by the broker returns 423 Locked. Max 100 characters. See Update Mode below.

Required item attributes

Each entry in items must include a tracking identifier plus the origin country and consignee name.

  • Name
    trackingNumber
    Type
    string
    Description

    Package tracking number. Required if awbNumber is not provided. Max 100 characters.

  • Name
    awbNumber
    Type
    string
    Description

    House Air Waybill number. Required if trackingNumber is not provided. If both are sent, awbNumber takes precedence. Max 100 characters.

  • Name
    itemIdempotencyKey
    Type
    string
    Description

    Optional but recommended for Update Mode. Stable per-line identifier from your system. Required to detect a true UPDATE (a line whose price/weight/etc. changed). Max 128 characters.

  • Name
    originCountry
    Type
    string
    Description

    Country of origin of the shipment (not the destination — courier manifests always clear into Argentina). 2-letter ISO 3166-1 alpha-2 code.

  • Name
    consigneeName
    Type
    string
    Description

    Full name of the person or company receiving the shipment (consignatario). Max 200 characters.

Consignee address — send each part in its own field

consigneeAddress is the street line only. City, province and postal code each have their own field — do NOT pack them into consigneeAddress. Only the first 30 characters of consigneeAddress reach the AFIP F3003 customs declaration (destinatarioDomicilio); if the full address is crammed into one field it gets truncated and the manifest declares an incomplete address. consigneeCity, consigneeProvince and consigneePostalCode are strongly recommended and effectively required for customs clearance.

  • Name
    consigneeAddress
    Type
    string
    Description

    Street line only: street name + number + floor/apartment. Correct: "Oro 2185 1B". Incorrect: "Oro 2185 1B, CP 1425, Buenos Aires, Argentina". Max 255 characters (first 30 reach AFIP F3003).

  • Name
    consigneeCity
    Type
    string
    Description

    Destination city/locality — send it in THIS field, NOT inside consigneeAddress. Strongly recommended: required for AFIP customs clearance. Max 100 characters.

  • Name
    consigneeProvince
    Type
    string
    Description

    Destination province/state — send it in THIS field, NOT inside consigneeAddress. Strongly recommended: required for AFIP customs clearance. Defaults to "Buenos Aires" if omitted. Max 100 characters.

  • Name
    consigneePostalCode
    Type
    string
    Description

    Destination postal code — send it in THIS field, NOT inside consigneeAddress. Strongly recommended for delivery and AFIP clearance. Max 20 characters.

Consignee contact & ID

  • Name
    consigneeIdType
    Type
    string
    Description

    Consignee tax/ID document type. For Argentina use "CUIT" (companies) or "CUIL" / "DNI" (individuals). Max 50 characters.

  • Name
    consigneeIdNumber
    Type
    string
    Description

    Consignee tax/ID number, digits only. Argentina CUIT/CUIL is 11 digits. Max 50 characters.

  • Name
    consigneePhoneNumber
    Type
    string
    Description

    Consignee contact phone number. Max 50 characters.

  • Name
    consigneeEmail
    Type
    string
    Description

    Consignee email address. Max 150 characters.

Product & customs attributes

  • Name
    itemName
    Type
    string
    Description

    Product name/title. Max 255 characters.

  • Name
    itemDescription
    Type
    string
    Description

    Longer product description. Max 1000 characters.

  • Name
    hsCode
    Type
    string
    Description

    HS / NCM tariff code. Max 20 characters.

  • Name
    fobValueUsd
    Type
    number
    Description

    FOB value in USD.

  • Name
    totalWeightKg
    Type
    number
    Description

    Net weight in kilograms.

  • Name
    totalVolumetricWeightKg
    Type
    number
    Description

    Volumetric (dimensional) weight in kilograms.

  • Name
    amountOfItems
    Type
    integer
    Description

    Number of items in the shipment.

  • Name
    amountOfPackages
    Type
    integer
    Description

    Number of physical packages.

  • Name
    boxNumber
    Type
    string
    Description

    Box / package identifier. Max 50 characters.

  • Name
    productLink
    Type
    string
    Description

    URL to the product listing. Max 500 characters.

  • Name
    imageLink
    Type
    string
    Description

    URL to a product image. Max 500 characters.

  • Name
    Category
    Type
    string
    Description

    Product category. Max 100 characters.

  • Name
    customerName
    Type
    string
    Description

    Customer name (when different from the consignee). Max 200 characters.

  • Name
    shipperName
    Type
    string
    Description

    Shipper / sender name. Max 200 characters.

  • Name
    shipperEmail
    Type
    string
    Description

    Shipper / sender email address. Max 150 characters.

Update Mode attributes (opt-in, v1.1.0)

Send batchId at the manifest root to re-import into an existing batch instead of creating a new one. Add a stable itemIdempotencyKey per item so the resolver can tell a real UPDATE apart from a new line.

  • Name
    itemIdempotencyKey
    Type
    string
    Description

    Optional but recommended for Update Mode. Stable per-line identifier from your system. Required to detect a true UPDATE (a line whose price/weight/etc changed). When omitted, the server derives a key from (team, manifest, batch, awb, payload_hash) — that auto-key changes whenever any client-authored field changes, so a real UPDATE looks like a CREATE of a new line. Max 128 characters.

Response codes

CodeMeaning
202Manifest accepted and queued for processing.
422Validation failed, or batchId does not belong to your account (unknown_batch).
423Target batch was closed by the broker — contact them to reopen it before retrying.

Request

POST
/v1/couriers/default/manifests/webhook
curl -X POST https://app.price2b.com/api/v1/couriers/default/manifests/webhook \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "mawbNumber": "MAWB-123456",
    "manifestNumber": "057-200001115",
    "airline": "LATAM",
    "flightNumber": "LA8005",
    "originAirport": "MIA",
    "items": [
      {
        "trackingNumber": "XMP2355400900999",
        "originCountry": "US",
        "consigneeName": "Juan Pérez",
        "consigneeIdType": "CUIT",
        "consigneeIdNumber": "20123456789",
        "consigneeAddress": "Oro 2185 1B",
        "consigneeCity": "La Plata",
        "consigneeProvince": "Buenos Aires",
        "consigneePostalCode": "1425",
        "consigneePhoneNumber": "+54 11 4444-5555",
        "consigneeEmail": "juan.perez@example.com",
        "itemName": "Nike Air Max 270",
        "hsCode": "6404.11.00",
        "fobValueUsd": 100.03,
        "totalWeightKg": 0.85
      }
    ]
  }'

Responses

{
  "success": true,
  "status": "queued",
  "message": "Manifest queued for processing",
  "idempotency_key": "7b2a58e4-8c1c-46d9-9f28-b5f1b1c4a7aa",
  "manifest_number": "057-200001115",
  "batch_id": null,
  "mode": "create",
  "tracking": {
    "manifest_number": "057-200001115",
    "batch_id": null,
    "mawb_number": "MAWB-123456",
    "items_count": 1,
    "timestamp": "2026-05-19T12:00:00Z"
  }
}

GET/v1/couriers/{courier}/webhook/{idempotencyKey}/status

Get webhook status

Check the processing status of a webhook request using its idempotency key.

Path parameters

  • Name
    courier
    Type
    string
    Description

    Courier code.

  • Name
    idempotencyKey
    Type
    string
    Description

    The idempotency key from webhook submission.

Request

GET
/v1/couriers/default/webhook/{key}/status
curl https://app.price2b.com/api/v1/couriers/default/webhook/7b2a58e4-8c1c-46d9-9f28-b5f1b1c4a7aa/status \
  -H "Authorization: Bearer {token}"

Response

{
  "success": true,
  "status": "queued",
  "idempotency_key": "7b2a58e4-8c1c-46d9-9f28-b5f1b1c4a7aa",
  "created_at": "2026-01-24T10:30:00",
  "updated_at": "2026-01-24T10:30:05"
}

GET/v1/couriers/manifests

List manifests

Get a paginated list of all manifests for the authenticated user with processing progress.

Query parameters

  • Name
    per_page
    Type
    integer
    Description

    Items per page (default: 15).

  • Name
    status
    Type
    string
    Description

    Filter by status: pending, processing, completed.

  • Name
    date_from
    Type
    date
    Description

    Filter by date from (Y-m-d).

  • Name
    date_to
    Type
    date
    Description

    Filter by date to (Y-m-d).

Request

GET
/v1/couriers/manifests
curl -G https://app.price2b.com/api/v1/couriers/manifests \
  -H "Authorization: Bearer {token}" \
  -d per_page=20 \
  -d status=completed

Response

{
  "success": true,
  "data": [
    {
      "manifest_id": "071-57898304",
      "batch_id": "BATCH-20260506-aBcDeFgHiJ",
      "status": "completed",
      "progress": 100,
      "summary": {
        "total_awbs": 10,
        "total_articles": 25,
        "personal_items": 15,
        "commercial_items": 8,
        "prohibited_items": 2,
        "amount_to_pay": 1250.50,
        "currency": "USD"
      }
    }
  ],
  "meta": {
    "current_page": 1,
    "total": 95,
    "per_page": 20
  }
}

The same manifest_id can appear multiple times — every historical import is its own batch. Save batch_id client-side to address that specific batch via Update Mode.


GET/v1/couriers/manifests/{manifest}/pipeline-status

Get pipeline status

Get detailed 4-stage pipeline processing status for a manifest.

Pipeline stages

StageWeightDescription
Classification25%Regime determination (Personal/Commercial/Prohibited)
Web Services25%CUIT validation, quota checks
OpenAI (NCM)25%AI-powered NCM code classification
Calculations25%Customs duties and taxes calculation

Request

GET
/v1/couriers/manifests/{manifest}/pipeline-status
curl https://app.price2b.com/api/v1/couriers/manifests/071-57898304/pipeline-status \
  -H "Authorization: Bearer {token}"

Response

{
  "success": true,
  "data": {
    "manifest_id": "071-57898304",
    "batch_id": "BATCH-20260506-aBcDeFgHiJ",
    "status": "processing",
    "overall_progress": 75,
    "pipeline_steps": {
      "classification": {
        "status": "completed",
        "progress": 100
      },
      "webservices": {
        "status": "completed",
        "progress": 100
      },
      "openai": {
        "status": "completed",
        "progress": 100
      },
      "calculations": {
        "status": "processing",
        "progress": 50
      }
    },
    "summary": {
      "total_products": 25,
      "regime_breakdown": {
        "personal": 15,
        "commercial": 8,
        "prohibited": 2
      },
      "amount_to_pay": 625.25
    }
  }
}

GET/v1/couriers/manifests/{manifest}/download

Download results

Download processed manifest results. Only available when processing is 100% complete.

Query parameters

  • Name
    format
    Type
    string
    Description

    Output format: json (default), csv, excel, xlsx.

Request

GET
/v1/couriers/manifests/{manifest}/download
curl https://app.price2b.com/api/v1/couriers/manifests/071-57898304/download \
  -H "Authorization: Bearer {token}" \
  -o results.json

Response (JSON)

{
  "success": true,
  "data": {
    "manifest": "071-57898304",
    "total_products": 25,
    "products": [
      {
        "awb_number": "AWB-001",
        "tracking_number": "071-57898304-001",
        "ncm_code": "8518.30.00",
        "regime": "P",
        "cif_value": 59.99,
        "ddp_value": 79.99,
        "customs_duty": 12.00,
        "customs_channel": "V"
      }
    ]
  }
}

POST/v1/couriers/manifests/batch-status

Batch status check

Check the processing status of multiple manifests in a single request (max 50).

Required attributes

  • Name
    manifests
    Type
    array
    Description

    Array of manifest IDs to check (1-50 items).

Request

POST
/v1/couriers/manifests/batch-status
curl -X POST https://app.price2b.com/api/v1/couriers/manifests/batch-status \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "manifests": ["071-57898304", "071-57898305", "071-57898306"]
  }'

Response

{
  "success": true,
  "data": [
    {
      "manifest_id": "071-57898304",
      "status": "completed",
      "progress": 100,
      "can_download": true
    },
    {
      "manifest_id": "071-57898305",
      "status": "processing",
      "progress": 75,
      "can_download": false
    }
  ]
}

POST/v1/couriers/{courier}/manifests/webhook

Chunked upload - Submit

Submit a manifest chunk for large files (25MB+). Include _chunk_metadata to enable chunked upload mode.

Chunk metadata

  • Name
    chunk_number
    Type
    integer
    Description

    Current chunk number (1-indexed).

  • Name
    total_chunks
    Type
    integer
    Description

    Total number of chunks (max: 50).

  • Name
    base_idempotency_key
    Type
    string
    Description

    UUID to group chunks from same manifest.

  • Name
    total_items
    Type
    integer
    Description

    Total items across all chunks.

Request

POST
/v1/couriers/default/manifests/webhook
curl -X POST https://app.price2b.com/api/v1/couriers/default/manifests/webhook \
  -H "Authorization: Bearer {token}" \
  -H "Idempotency-Key: 550e8400-chunk-1-of-25" \
  -d '{
    "mawbNumber": "071-57898304",
    "items": [...],
    "_chunk_metadata": {
      "chunk_number": 1,
      "total_chunks": 25,
      "total_items": 2500,
      "base_idempotency_key": "550e8400-e29b-41d4-a716-446655440000"
    }
  }'

Response

{
  "success": true,
  "status": "receiving",
  "message": "Chunk received successfully",
  "chunk_number": 1,
  "total_chunks": 25,
  "progress": {
    "received_chunks": 1,
    "missing_chunks": [2, 3, 4, 5],
    "percentage": 4,
    "is_complete": false
  }
}

GET/v1/couriers/manifests/chunks/{baseIdempotencyKey}/status

Chunked upload - Status

Check the status of a chunked upload, including received and missing chunks.

Request

GET
/v1/couriers/manifests/chunks/{key}/status
curl https://app.price2b.com/api/v1/couriers/manifests/chunks/550e8400-e29b-41d4-a716-446655440000/status \
  -H "Authorization: Bearer {token}"

Response

{
  "success": true,
  "data": {
    "manifest_number": "071-57898304",
    "status": "receiving",
    "progress": {
      "total_chunks": 25,
      "received_chunks": 20,
      "missing_chunks": [3, 15, 18, 22, 24],
      "percentage": 80
    }
  }
}

POST/v1/couriers/manifests/chunks/{baseIdempotencyKey}/retry-missing

Chunked upload - Retry

Get a list of missing chunks to retry.

Request

POST
/v1/couriers/manifests/chunks/{key}/retry-missing
curl -X POST https://app.price2b.com/api/v1/couriers/manifests/chunks/550e8400-e29b-41d4-a716-446655440000/retry-missing \
  -H "Authorization: Bearer {token}"

Response

{
  "success": true,
  "message": "Please resend the following chunks",
  "data": {
    "manifest_number": "071-57898304",
    "missing_chunks": [3, 15, 18, 22, 24],
    "missing_count": 5
  }
}

Manifest Update Mode

Update an already-imported batch in place instead of creating a new one. The system deduplicates per item via cryptographic hash and only re-runs the pipeline on items that actually changed.

This feature is opt-in. If you do not send batchId, your existing flow keeps creating new batches and is unaffected.

Default behavior

The webhook has always worked this way: each call creates a fresh batch_id, even when you re-send the same manifestNumber. Multiple batches per manifest are a normal, supported pattern.

Opt-in to update an existing batch

Send the existing batch_id together with the regular payload. The server then:

  1. Looks up the batch and verifies it belongs to your partner account.
  2. Returns HTTP 423 Locked if the broker has closed it.
  3. Resolves each item against the existing rows in that batch — see decision matrix.

If the batchId does not exist for your account: HTTP 422 with { "error": "unknown_batch", ... }.

Decision matrix (per item)

DecisionWhenCost
CREATENo existing record matches the item identityFull pipeline runs
UPDATEExisting record matches identity, payload differsPipeline re-runs only on the changed record
SKIPExisting record matches identity, payload identicalZero — no DB write, no pipeline dispatch
REJECTCross-team conflict, missing AWB, missing/duplicate idempotency keyLogged, never persisted

The cost saving comes from SKIP. In a recurring manifest where you re-send 1.500 items and only 20 changed, ~1.480 are skipped and only ~20 enter the pipeline (which is what gets billed for AI classification).

Update request

POST
/v1/couriers/default/manifests/webhook
curl -X POST https://app.price2b.com/api/v1/couriers/default/manifests/webhook \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "manifestNumber": "U1-071-57898304",
    "mawbNumber": "071-57898304",
    "batchId": "BATCH-20260506-aBcDeFgHiJ",
    "items": [
      {
        "trackingNumber": "TRK-1",
        "itemIdempotencyKey": "your-stable-line-id-1",
        "originCountry": "CN",
        "consigneeName": "Juan Pérez",
        "fobValueUsd": 49.99
      }
    ]
  }'

Response (202 update mode)

{
  "success": true,
  "status": "queued",
  "manifest_number": "U1-071-57898304",
  "batch_id": "BATCH-20260506-aBcDeFgHiJ",
  "mode": "update",
  "tracking": {
    "manifest_number": "U1-071-57898304",
    "batch_id": "BATCH-20260506-aBcDeFgHiJ",
    "mawb_number": "071-57898304",
    "items_count": 1,
    "timestamp": "2026-05-06T12:00:00Z"
  }
}

Item identity

A single MAWB can carry many line items (Temu consolidated shipments, Andreani internal MAWBs where every package shares an AWB). Identity is therefore NOT based on the AWB alone.

Recommended — send itemIdempotencyKey per item

A stable per-line key from your system. The server uses it as the matching key for SKIP/UPDATE detection across re-imports.

This is the only way to detect a true UPDATE (a line whose price/weight/etc. actually changed).

Default — auto-derived key from payload contents

If you omit itemIdempotencyKey, the server derives one from (team, manifest, batch, awb, payload_hash). The payload_hash is computed over your client-authored fields, so:

  • Re-send the same line byte-identically → same auto-key → SKIP.
  • Change anything in that line → new auto-key → treated as CREATE (a new line), not UPDATE.

Without itemIdempotencyKey, an UPDATE looks like a CREATE plus a stale leftover SKIP. Use itemIdempotencyKey whenever you can.


Hashed fields — what counts as byte-identical

The server hashes these client-authored fields after normalization (trim strings, lowercase emails, uppercase country codes, decimal precision to 4 places, HTS digits-only):

awb_number, box_number, sender, consignee, tax_id, consignee_address1, consignee_city, consignee_province, consignee_zip, consignee_phone, consignee_email, product_description, notes, article_url, category_id, country_of_manufacture, weight, quantity, packages, unit_value, total_value, hts_code.

Fields outside this list (regime classification, customs channel, calculation results) are owned by the broker post-import and never affect the SKIP / UPDATE decision.

Items absent from the update

Items that exist in the batch but are NOT in the new payload are left untouched. The update is additive/corrective. To remove an item, contact the broker — there is no public endpoint for that.


HTTP 423 — Manifest closed by broker

The broker can mark a batch as closed from their internal UI. Once closed, any write attempt against that batchId returns 423 Locked.

Response (423 Locked)

{
  "error": "manifest_closed",
  "message": "El manifiesto fue cerrado por el broker. Contactalo para reabrirlo si necesitás hacer modificaciones.",
  "closed_at": "2026-05-04T18:32:00Z",
  "manifest_number": "U1-071-57898304",
  "batch_id": "BATCH-20260506-aBcDeFgHiJ"
}

What to do:

  1. Contact the broker and ask them to reopen the batch.
  2. If you have new shipments unrelated to the closed batch, submit them without batchId to create a new batch under the same manifestNumber.

HTTP 422 — Unknown batch

Returned when the partner provides a batchId that does not belong to their account.

Response (422 unknown_batch)

{
  "success": false,
  "error": "unknown_batch",
  "message": "The provided batch_id does not exist for this partner.",
  "batch_id": "DOES-NOT-EXIST-12345"
}

1. POST .../webhook (no batchId)              → 202 mode=create, batch_id=null
2. GET  .../manifests/{manifest}/pipeline-status → batch_id in response (after a few seconds)
   or
   GET  .../manifests                         → list with batch_id per row
3. Persist (manifest_number, batch_id) client-side
4. POST .../webhook (with batchId)            → 202 mode=update + per-item resolution
   If the broker closed the batch:            → 423 manifest_closed
   If batch_id does not belong to partner:    → 422 unknown_batch

Best practices

  • Send the full manifest each time you update a batch. Do not pre-diff client-side — the server deduplicates.
  • Save the batch_id from the first import response. You need it to address the same batch later.
  • Provide itemIdempotencyKey per item when your internal system has stable per-line identifiers.
  • Use a fresh Idempotency-Key HTTP header per request. That header dedupes network retries, not real updates.
  • Coordinate with the broker before they close the batch.

Alternative Manifest API

An alternative REST API for manifest management, suitable for simpler integrations.

Base Path: /api/v1/manifests


GET/v1/manifests

List manifests (alt)

Get a paginated list of manifests using the alternative API.

Request

GET
/v1/manifests
curl -G https://app.price2b.com/api/v1/manifests \
  -H "Authorization: Bearer {token}" \
  -d per_page=20

Response

{
  "success": true,
  "data": [
    {
      "manifest_id": "MAN-20260124-001",
      "total_products": 25,
      "processing_status": "completed"
    }
  ],
  "meta": {
    "current_page": 1,
    "total": 45
  }
}

POST/v1/manifests

Upload manifest (alt)

Upload a manifest with up to 1000 products.

Product attributes

  • Name
    awb_number
    Type
    string
    Description

    Air Waybill number.

  • Name
    consignee
    Type
    string
    Description

    Consignee full name.

  • Name
    tax_id
    Type
    string
    Description

    Tax ID (CUIT).

  • Name
    product_description
    Type
    string
    Description

    Product description.

  • Name
    quantity
    Type
    integer
    Description

    Quantity.

  • Name
    unit_value
    Type
    number
    Description

    Unit value in currency.

  • Name
    country_of_manufacture
    Type
    string
    Description

    2-letter ISO country code.

Request

POST
/v1/manifests
curl -X POST https://app.price2b.com/api/v1/manifests \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "manifest": "MAN-20260124-001",
    "products": [
      {
        "awb_number": "AWB123456",
        "consignee": "Juan Pérez",
        "tax_id": "20-12345678-9",
        "product_description": "Wireless Headphones",
        "quantity": 2,
        "unit_value": 49.99,
        "country_of_manufacture": "CN"
      }
    ]
  }'

Response (201)

{
  "success": true,
  "message": "Manifest uploaded successfully",
  "data": {
    "manifest_id": "MAN-20260124-001",
    "total_products": 1,
    "processing_status": "pending"
  }
}

GET/v1/manifests/{manifest}

Get manifest details (alt)

Get complete manifest details including all products with NCM codes and customs calculations.

Request

GET
/v1/manifests/MAN-20260124-001
curl https://app.price2b.com/api/v1/manifests/MAN-20260124-001 \
  -H "Authorization: Bearer {token}"

Response

{
  "success": true,
  "data": {
    "manifest": "MAN-20260124-001",
    "products": [
      {
        "awb_number": "AWB123456",
        "ncm_code": "8518.30.00",
        "cif_value": 105.48,
        "ddp_value": 186.12,
        "customs_duty": 35.50,
        "quota": {
          "tax_id": "20-12345678-9",
          "quota": 3
        }
      }
    ]
  }
}

Tax ID / CUIT Quota API

Check and manage tax ID (CUIT) quota for customs imports.


POST/v1/couriers/quota/check

Check CUIT quota

Check the current quota status for a tax ID (CUIT). Returns remaining purchases allowed (0-5).

Required attributes

  • Name
    tax_id
    Type
    string
    Description

    Tax ID (CUIT). Accepts: 20-12345678-9 or 20123456789.

Optional attributes

  • Name
    awb_number
    Type
    string
    Description

    AWB number to check specific record quota.

Request

POST
/v1/couriers/quota/check
curl -X POST https://app.price2b.com/api/v1/couriers/quota/check \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{"tax_id": "20-12345678-9"}'

Response

{
  "success": true,
  "data": {
    "tax_id": "20123456789",
    "tax_id_formatted": "20-12345678-9",
    "current_quota": {
      "quota": 3,
      "status": 200,
      "domicilio": "S"
    },
    "historical_records_count": 2
  }
}

PUT/v1/couriers/client-info

Update client info

Update the tax ID (CUIT) for a consignee record.

Required attributes

  • Name
    awb_number
    Type
    string
    Description

    AWB number to update.

  • Name
    tax_id
    Type
    string
    Description

    New tax ID (CUIT).

Request

PUT
/v1/couriers/client-info
curl -X PUT https://app.price2b.com/api/v1/couriers/client-info \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{"awb_number": "AWB123456", "tax_id": "20-98765432-1"}'

Response

{
  "success": true,
  "message": "Client info updated successfully",
  "data": {
    "awb_number": "AWB123456",
    "tax_id_formatted": "20-98765432-1"
  }
}

POST/v1/couriers/client-info/can-edit

Check editability

Check if a record's tax ID can be modified.

Request

POST
/v1/couriers/client-info/can-edit
curl -X POST https://app.price2b.com/api/v1/couriers/client-info/can-edit \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{"awb_number": "AWB123456"}'

Response

{
  "success": true,
  "data": {
    "awb_number": "AWB123456",
    "can_edit": true,
    "current_tax_id": "20-12345678-9",
    "status": "pending"
  }
}

S3 Storage API

Direct file upload to S3 for large manifest files (up to 40MB).


POST/v1/manifests/storage/upload

Upload to S3

Upload manifest files (JSON or Excel) directly to S3 storage.

Required attributes

  • Name
    file
    Type
    file
    Description

    Manifest file. Max 40MB. Allowed: json, xlsx, xls, xlsm.

  • Name
    courier_code
    Type
    string
    Description

    Carrier code: OCA, DHL, FEDEX, UPS, etc.

Optional attributes

  • Name
    manifest_name
    Type
    string
    Description

    Custom name for the manifest.

  • Name
    description
    Type
    string
    Description

    Description or notes.

Request

POST
/v1/manifests/storage/upload
curl -X POST https://app.price2b.com/api/v1/manifests/storage/upload \
  -H "Authorization: Bearer {token}" \
  -F "file=@daily-manifest.xlsx" \
  -F "courier_code=DHL" \
  -F "manifest_name=Daily-Shipments-2026-01-24"

Response (201)

{
  "success": true,
  "message": "Manifest uploaded successfully",
  "data": {
    "file_name": "DHL_daily-shipments_2026-01-24.xlsx",
    "file_url": "https://storage.price2b.com/manifests/DHL/...",
    "file_size": {
      "bytes": 2458624,
      "human": "2.34 MB"
    },
    "courier_code": "DHL"
  }
}

GET/v1/manifests/storage/list

List S3 manifests

List all manifest files uploaded to S3 storage.

Query parameters

  • Name
    courier_code
    Type
    string
    Description

    Filter by carrier code.

  • Name
    per_page
    Type
    integer
    Description

    Items per page (default: 15).

Request

GET
/v1/manifests/storage/list
curl -G https://app.price2b.com/api/v1/manifests/storage/list \
  -H "Authorization: Bearer {token}" \
  -d courier_code=DHL

Response

{
  "success": true,
  "data": [
    {
      "file_name": "DHL_daily-shipments_2026-01-24.xlsx",
      "file_url": "https://storage.price2b.com/...",
      "file_size": {
        "bytes": 2458624,
        "human": "2.34 MB"
      },
      "courier_code": "DHL",
      "uploaded_at": "2026-01-24T15:45:30+00:00"
    }
  ]
}

Status values

StatusProgressDescription
pending0%Uploaded, not started
processing1-99%Pipeline running
completed100%All processing complete

Customs channels

CodeNameDescription
VVerdeGreen - automatic clearance
AAzulBlue - document review
RORojoRed - physical inspection

Rate limits

EndpointLimit
Webhook submissions60/min
Status checks120/min
Downloads30/min

HTTP status codes

HTTPMeaning
200Idempotent replay (same Idempotency-Key + same payload hash)
202Manifest queued for processing (first import or update)
401Missing/invalid Sanctum token
422Validation error — including unknown_batch (when the provided batchId does not belong to your account)
423Batch closed by broker (manifest_closed)
429Rate limit exceeded
500Server error

Was this page helpful?