Payload schema

The exact JSON shapes Paperless expects for orders (Pattern A) and receipts (Pattern B). Every field with type, required/optional status, example, and mapping to the Paperless data model.

Conventions

Pattern A: Order object

This is the body Paperless expects from GET /v1/orders/{id} on your side.

Full example

{
  "id":          "ord_ABC123XYZ",
  "merchant_id": "MERCHANT_12345",
  "location_id": "LOC_001",
  "state":       "COMPLETED",
  "created_at":  "2026-05-15T17:21:14Z",
  "closed_at":   "2026-05-15T17:21:19Z",
  "currency":    "CAD",

  "total_money":     { "amount": 1357, "currency": "CAD" },
  "total_tax_money": { "amount":  157, "currency": "CAD" },

  "line_items": [
    {
      "uid":              "li_1",
      "name":             "Latte",
      "quantity":         "1",
      "base_price_money": { "amount": 600, "currency": "CAD" },
      "total_money":      { "amount": 600, "currency": "CAD" },
      "applied_taxes": [
        { "tax_uid": "tax_1", "applied_money": { "amount": 78, "currency": "CAD" } }
      ]
    },
    {
      "uid":              "li_2",
      "name":             "Croissant",
      "quantity":         "1",
      "base_price_money": { "amount": 600, "currency": "CAD" },
      "total_money":      { "amount": 600, "currency": "CAD" },
      "applied_taxes": [
        { "tax_uid": "tax_1", "applied_money": { "amount": 79, "currency": "CAD" } }
      ]
    }
  ],

  "taxes": [
    {
      "uid":           "tax_1",
      "name":          "HST",
      "percentage":    "13.0",
      "type":          "ADDITIVE",
      "applied_money": { "amount": 157, "currency": "CAD" }
    }
  ],

  "tenders": [
    {
      "id":           "tnd_1",
      "type":         "CARD",
      "amount_money": { "amount": 1357, "currency": "CAD" },
      "card_details": {
        "card": {
          "brand":  "VISA",
          "last_4": "4242"
        }
      }
    }
  ],

  "custom_attributes": {
    "paperless_customer_id": {
      "value": "PL-3f0e2c1a-7d33-4f0a-9b9b-ac3b5b1c2f88"
    }
  }
}

Top-level fields

FieldTypeRequiredMaps toNotes
idstringRequiredReceipt.external_idGlobally unique. Idempotency key.
merchant_idstringRequiredReceipt.merchant_idYour merchant ID.
location_idstringRequiredMust match a location from /locations.
statestringOptionalInformational. Paperless only ingests COMPLETED orders regardless.
created_atISO 8601 UTCRequiredWhen the order opened.
closed_atISO 8601 UTCRequiredReceipt.purchased_atWhen payment completed.
currencystring (ISO 4217)RequiredReceipt.currency
total_moneyMoneyRequiredReceipt.total_centsGrand total.
total_tax_moneyMoneyRequiredReceipt.tax_centsTotal tax. Subtotal = total - tax.
line_itemsarrayRequiredReceiptItem[]Empty array is invalid. Must have ≥ 1.
taxesarrayOptionalReceiptTax[]Empty when there is no tax.
tendersarrayRequiredReceiptPayment[]≥ 1 entry.
custom_attributesobjectOptionalHolds paperless_customer_id when present.

LineItem

FieldTypeRequiredMaps toNotes
uidstringOptionalReference for applied_taxes.tax_uid.
namestringRequiredReceiptItem.name
quantitystring (numeric)RequiredReceiptItem.quantitySent as a string for decimal support (e.g. "1.5"); rounded to integer by Paperless.
base_price_moneyMoneyRequiredReceiptItem.unit_pricePre-tax unit price.
total_moneyMoneyRequiredReceiptItem.total_pricePre-tax line total.
applied_taxesarrayOptionalReceiptItem.tax_centsSum of applied_money across entries.

Tax

FieldTypeRequiredMaps toNotes
uidstringOptionalReferenced by line_items.applied_taxes.tax_uid.
namestringRequiredReceiptTax.nameE.g. HST, GST, VAT.
percentagestringOptionalReceiptTax.rateDecimal string, e.g. "13.0".
typeenumRequiredReceiptTax.typeADDITIVE or INCLUSIVE.
applied_moneyMoneyRequiredReceiptTax.amount_centsTotal tax collected under this rule.
GST / HST recognition

Paperless rolls up taxes whose name matches GST, HST, Goods and Services Tax, or Harmonized Sales Tax (case-insensitive) into a separate gst_hst_cents field used for Canadian tax reporting. Naming consistency matters.

Tender

FieldTypeRequiredMaps toNotes
idstringOptionalYour tender ID.
typeenumRequiredReceiptPayment.methodCARD, CASH, GIFT_CARD, WALLET, OTHER.
amount_moneyMoneyRequiredReceiptPayment.amount_cents
card_details.card.last_4stringOptionalReceiptPayment.last4Card tenders only. Never send full PAN.
card_details.card.brandstringOptionalInformational.

Money

{
  "amount":   1357,      // integer minor units
  "currency": "CAD"      // ISO 4217
}

Pattern B: Receipt object

This is the body Paperless expects from POST /ingest/{provider}/receipts. It is a flattened, fully self-contained shape — no callbacks required.

Full example

{
  "external_id":       "ord_ABC123XYZ",
  "external_event_id": "evt_acme_8f3e1c9a",
  "merchant_id":       "MERCHANT_12345",

  "location": {
    "location_id": "LOC_001",
    "name":        "Acme Coffee — King St",
    "address":     "123 King St W",
    "city":        "Toronto",
    "region":      "ON",
    "country":     "CA",
    "postal_code": "M5H 1A1",
    "timezone":    "America/Toronto"
  },

  "merchant": {
    "business_name": "Acme Coffee",
    "tax_number":    "123456789RT0001"
  },

  "purchased_at":   "2026-05-15T17:21:19Z",
  "currency":       "CAD",
  "subtotal_cents": 1200,
  "tax_cents":       157,
  "total_cents":    1357,

  "line_items": [
    { "name": "Latte",     "quantity": 1, "unit_price": 600, "total_price": 600, "tax_cents": 78 },
    { "name": "Croissant", "quantity": 1, "unit_price": 600, "total_price": 600, "tax_cents": 79 }
  ],

  "taxes": [
    { "name": "HST", "rate": "13.0", "type": "ADDITIVE", "amount_cents": 157 }
  ],

  "payments": [
    { "method": "CARD", "last4": "4242", "amount_cents": 1357 }
  ],

  "customer": {
    "paperless_customer_id": "3f0e2c1a-7d33-4f0a-9b9b-ac3b5b1c2f88",
    "email": null,
    "phone": null
  }
}

Required vs optional

FieldTypeRequiredNotes
external_idstringRequiredIdempotency key. Globally unique per merchant.
external_event_idstringRequiredUnique per push. Differs from external_id if you re-push the same receipt.
merchant_idstringRequiredYour merchant ID.
locationobjectRequiredInlined location snapshot.
merchant.business_namestringRequiredDisplay name on the receipt.
merchant.tax_numberstringOptionalRequired in jurisdictions that need it on receipts (CA, EU, etc.).
purchased_atISO 8601 UTCRequired
currencyISO 4217Required
subtotal_cents, tax_cents, total_centsintRequiredsubtotal + tax = total must hold.
line_itemsarrayRequired≥ 1.
taxesarrayOptionalEmpty when there is no tax.
paymentsarrayRequired≥ 1. Sum of amount_cents must equal total_cents.
customer.paperless_customer_idUUIDOptionalStrongest match signal. Bare UUID, no PL- prefix.
customer.emailstringOptionalUsed for fallback match.
customer.phoneE.164 stringOptionalUsed for fallback match.

Refund / void payloads (both patterns)

To record a refund or void after the original receipt has been written, post a webhook event with one of:

{
  "external_event_id": "evt_acme_refund_001",
  "event_type":        "order.refunded",
  "created_at":        "2026-05-16T11:02:00Z",
  "merchant_id":       "MERCHANT_12345",
  "location_id":       "LOC_001",
  "data": {
    "order_id":     "ord_ABC123XYZ",
    "refund_id":    "rf_acme_001",
    "amount_cents":  600,
    "reason":       "customer_request"
  }
}
{
  "external_event_id": "evt_acme_void_001",
  "event_type":        "order.voided",
  "created_at":        "2026-05-15T17:22:00Z",
  "merchant_id":       "MERCHANT_12345",
  "location_id":       "LOC_001",
  "data": {
    "order_id": "ord_ABC123XYZ",
    "reason":   "cashier_correction"
  }
}

Validation rules Paperless enforces