Receipt Out API v1

Deliver a receipt in one request.

Receipt Out gives retailers and POS platforms a small, authenticated API for sending an itemized digital receipt directly to a customer's Receipt Out account after checkout.

Production endpointPOST https://receiptout.com/api/v1/receipts
JSONBearer authIdempotent

Quickstart

A retailer integration needs an API key, an activated Receipt Out customer email, and a unique transaction identifier from the retailer's POS system.

1Get a Test API key from Receipt Out.
2Send one JSON receipt to the v1 endpoint.
3Verify the DEMO receipt appears in the customer's inbox.
4Move to a Live key when the integration is ready for real receipts.
cURL
curl https://receiptout.com/api/v1/receipts \
  -X POST \
  -H "Authorization: Bearer ro_test_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: sale-12345" \
  --data @receipt.json

Authentication

Every API request uses a retailer-specific Bearer key in the Authorization header.

Authorization: Bearer ro_test_...

Keys are shown only once when created. Receipt Out stores a cryptographic hash of the key rather than the full credential. A revoked key immediately stops authenticating.

Keep API keys server-side. Never place a Receipt Out API key in browser JavaScript, a public mobile app, source control, or client-visible configuration.

Test and Live modes

TEST

Test keys

Keys beginning with ro_test_ exercise the real receipt pipeline but mark every resulting receipt DEMO.

LIVE

Live keys

Keys beginning with ro_live_ create normal customer receipts. Live keys should only be issued for an approved production integration.

Receipt request

The API accepts a JSON object with a customer and receipt. The customer must already have an activated Receipt Out account matching the submitted email address.

receipt.json
{
  "customer": {
    "email": "customer@example.com"
  },
  "receipt": {
    "transaction_id": "SALE-12345",
    "purchased_at": "2026-09-27T13:45:00-05:00",
    "store": {
      "location": "Jackson, Missouri"
    },
    "currency": "USD",
    "payment": {
      "label": "Visa ending 4242"
    },
    "items": [
      {
        "description": "Milk",
        "quantity": 1,
        "unit_price_cents": 348,
        "line_total_cents": 348
      },
      {
        "description": "Laundry detergent",
        "quantity": 1,
        "unit_price_cents": 1297,
        "line_total_cents": 1297
      }
    ],
    "subtotal_cents": 1645,
    "discount_cents": 100,
    "tax_cents": 124,
    "total_cents": 1669
  }
}
FieldTypeRequiredNotes
customer.emailstringYesMust match an activated Receipt Out account.
receipt.transaction_idstringYesRetailer's unique transaction ID, max 120 characters.
receipt.purchased_atISO-8601YesPurchase time; cannot be more than 24 hours in the future.
receipt.store.locationstringNoStore/location description, max 160 characters.
receipt.currencystringNoThree-letter ISO code. Defaults to USD.
receipt.payment.labelstringNoDisplay-only payment description. Do not send full card numbers.
receipt.itemsarrayYes1–200 line items.
items[].descriptionstringYesItem description, max 140 characters.
items[].quantitynumberNoDefaults to 1. Greater than 0, up to 9999.
items[].unit_price_centsintegerYesNon-negative integer cents.
items[].line_total_centsintegerYesNon-negative integer cents.
receipt.subtotal_centsintegerYesMust equal the sum of all line totals.
receipt.discount_centsintegerNoDefaults to 0 and cannot exceed subtotal.
receipt.tax_centsintegerYesNon-negative integer cents.
receipt.total_centsintegerYesMust equal subtotal − discounts + tax.

Money and totals

All monetary values are integer minor units—cents for USD. Do not send floating-point dollar values.

$12.991299
$3.48348
$0.000

Receipt Out validates both equations before accepting a receipt:

subtotal_cents = Σ line_total_centstotal_cents = subtotal_cents − discount_cents + tax_cents

Idempotency and retries

Every delivery requires an Idempotency-Key header. Use a value tied to the retailer transaction or delivery attempt, such as store-104-sale-882741.

  • If the exact same request is retried with the same key, Receipt Out returns the original delivery with idempotent_replay: true.
  • If the same idempotency key is reused with different JSON, the API returns 409 idempotency_conflict.
  • If the same retailer transaction_id is sent again under a different idempotency key, the API returns 409 transaction_exists.

This lets POS software safely retry after network timeouts without creating duplicate customer receipts.

Successful responses

201 Created
{
  "object": "receipt_delivery",
  "status": "delivered",
  "receipt_id": 42,
  "transaction_id": "SALE-12345",
  "customer": {
    "email": "c******@example.com"
  },
  "mode": "test",
  "demo": true,
  "idempotent_replay": false,
  "request_id": "req_..."
}

A successful replay returns HTTP 200 with the original receipt_id and idempotent_replay: true.

Error responses

Errors are JSON and include a stable error code plus a request ID that can be used during integration support.

HTTPCodeMeaning
400invalid_idempotency_keyMissing or malformed Idempotency-Key.
400invalid_jsonMissing or malformed JSON.
401invalid_api_keyMissing, invalid, revoked, or inactive API key.
404customer_not_foundNo activated Receipt Out account matches the email.
409idempotency_conflictSame idempotency key, different request body.
409transaction_existsThat retailer transaction ID was already delivered.
413payload_too_largeRequest body exceeded 512 KB.
415unsupported_media_typeContent-Type is not application/json.
422validation_errorOne or more receipt fields failed validation.
429rate_limitedCurrent delivery rate limit exceeded.
500internal_errorReceipt Out could not complete the delivery.

Current v1 limits

512 KBMaximum JSON request body
200Maximum line items per receipt
120/minAccepted deliveries per API client
1 accountReceipt delivered to one matched customer

These are initial pilot limits and can evolve as Receipt Out moves into larger retailer integrations.

OpenAPI specification

The machine-readable OpenAPI 3.1 document describes the current v1 endpoint, schemas, authentication, and response models.

View openapi.json