Skip to documentation content

Invoices

Look up imported QuickBooks invoices and prepare Stripe fields from a fresh, supported invoice with an immutable snapshot.

On this page

Linked-source access

Use a Stripe-integration Carden API key with explicitly granted invoices:read to read invoices from that integration's linked QuickBooks source. Preparation also requires enrichment:write; reporting requires payments:write. QuickBooks supplies accounting facts and Stripe is the payment destination within the same merchant and environment.

The source link and invoice-read grant require authority over both the QuickBooks source and Stripe destination. Existing keys receive no automatic grants. An invoice ID, company ID, or arbitrary caller-supplied organization cannot broaden access. New preparation requires a fresh, active linked source; the API does not silently create provider accounts or initiate a Stripe OAuth flow.

List or find invoices

List invoices · invoices:read
GET /api/v1/invoices?quickbooksInvoiceId=1042&limit=20
GET /api/v1/invoices?invoiceNumber=INV-1042&limit=20

Query fieldMeaning
quickbooksInvoiceIdOptional exact QuickBooks Invoice ID; this is not the Carden invoice UUID.
invoiceNumberOptional exact source invoice number. Resolve ambiguous results instead of choosing the first invoice.
cursorOptional opaque pagination cursor returned as nextCursor by the preceding page.
limitOptional integer page size from 1 to 100; defaults to 25. The examples request 20 records.

Use an exact source ID or invoice-number filter for a known invoice, or omit lookup filters to list available invoices. Follow nextCursor with the same filters until it is null. An empty invoices array means there is no matching visible record in this context, not proof that the invoice never existed in QuickBooks.

200 OK · data is InvoiceList
{
  "object": "invoice.list",
  "api_version": "v1",
  "data": {
    "invoices": [
      {
        "id": "11111111-1111-4111-8111-111111111111",
        "quickbooksInvoiceId": "1042",
        "invoiceNumber": "INV-1042",
        "status": "open",
        "currency": "usd",
        "totalAmountMinor": 10800,
        "sourceVersion": "3",
        "revision": "invoice-revision-example-3",
        "snapshotId": "22222222-2222-4222-8222-222222222222",
        "checkedThrough": "2026-01-01T11:59:00.000Z",
        "ready": true,
        "issues": []
      }
    ],
    "nextCursor": null
  }
}

The response is { object: invoice.list, api_version: v1, data: { invoices: InvoiceSummary[], nextCursor } }. The private SDK's carden.invoices.list(filters?, options?) returns the data object, not the HTTP envelope. Request options include signal and timeoutMs.

Invoice summary fields

FieldMeaning
id / quickbooksInvoiceIdCarden invoice UUID / the authoritative external QuickBooks Invoice ID.
invoiceNumber / statusSource invoice number, nullable when unavailable, and the current known state.
currency / totalAmountMinorLowercase currency and integer minor-unit total; either can be null for unresolved source data.
sourceVersionSource version when available; null when unavailable.
revision / snapshotIdCurrent source/mapping revision and snapshot UUID, nullable when unavailable. Their presence alone does not establish readiness.
checkedThroughSource freshness boundary used for inspection; nullable when no successful check exists.
readyWhether the inspected invoice is currently ready for supported preparation, not a payment reservation.
issuesArray of code, path, message, and category. Categories: source, mapping, validation, payment, freshness, or access.

Retain unavailable fields as null and inspect issues instead of deriving missing source facts from similar invoices. Preparation rechecks source access, freshness, revision, and full-invoice economics even when ready was true at lookup time. The current freshness check requires a completed source checkpoint within four hours and no active or pending refresh; checkedThrough is that source-check boundary, not the time you opened the page.

Retrieve invoice detail

Retrieve by Carden UUID · invoices:read
GET /api/v1/invoices/{invoiceId}

A successful response is { object: invoice, api_version: v1, data: InvoiceDetail }. The detail extends InvoiceSummary with invoice, which is a StoredInvoice or null, and provenance. A missing or out-of-scope identifier must not be treated as permission to search another merchant or source.

200 OK · synthetic source and mapping evidence
{
  "object": "invoice",
  "api_version": "v1",
  "data": {
    "id": "11111111-1111-4111-8111-111111111111",
    "quickbooksInvoiceId": "1042",
    "invoiceNumber": "INV-1042",
    "status": "open",
    "currency": "usd",
    "totalAmountMinor": 10800,
    "sourceVersion": "3",
    "revision": "invoice-revision-example-3",
    "snapshotId": "22222222-2222-4222-8222-222222222222",
    "checkedThrough": "2026-01-01T11:59:00.000Z",
    "ready": true,
    "issues": [],
    "invoice": {
      "invoiceNumber": "INV-1042",
      "purchaseOrderReference": null,
      "status": "open",
      "currency": "usd",
      "subtotalAmountMinor": 10000,
      "taxAmountMinor": 800,
      "shippingAmountMinor": 0,
      "discountAmountMinor": 0,
      "totalAmountMinor": 10800,
      "balanceAmountMinor": 10800,
      "taxRepresentation": "transaction",
      "discountRepresentation": "transaction",
      "issuedAt": null,
      "dueAt": null,
      "voidedAt": null,
      "lineItems": [
        {
          "sourceLineId": "1",
          "sourceItemId": "42",
          "sequence": 1,
          "productName": "Industrial filters, boxed",
          "description": null,
          "productCode": "FILTER-01",
          "unitOfMeasure": "box",
          "commodityCode": null,
          "quantity": "2",
          "unitAmountMinor": 5000,
          "subtotalAmountMinor": 10000,
          "taxAmountMinor": null,
          "discountAmountMinor": null,
          "totalAmountMinor": null
        }
      ]
    },
    "provenance": {
      "sourceIntegrationId": "33333333-3333-4333-8333-333333333333",
      "sourceConnectionId": "quickbooks_connection_example",
      "sourceRecordId": "66666666-6666-4666-8666-666666666666",
      "mapperVersion": "quickbooks-stored-invoice.v2",
      "dependencies": [
        {
          "sourceRecordId": "66666666-6666-4666-8666-666666666666",
          "objectType": "Invoice",
          "externalId": "1042"
        },
        {
          "sourceRecordId": "77777777-7777-4777-8777-777777777777",
          "objectType": "Item",
          "externalId": "42"
        },
        {
          "sourceRecordId": "88888888-8888-4888-8888-888888888888",
          "objectType": "Preferences",
          "externalId": "preferences"
        }
      ],
      "mappings": [
        {
          "id": "item_mapping_example",
          "sourceItemId": "42",
          "productCode": "FILTER-01",
          "unitOfMeasure": "box",
          "version": 2,
          "evidence": "Fixture merchant confirmed the item code and that this item is sold by the box.",
          "approvedBy": "fixture_reviewer",
          "approvedAt": "2026-01-01T11:00:00.000Z"
        }
      ]
    }
  }
}

provenance contains sourceIntegrationId, sourceConnectionId, sourceRecordId, mapperVersion, dependencies, and mappings. Each dependency identifies its exact sourceRecordId, objectType, and externalId. Confirmed item mappings retain id, sourceItemId, productCode, unitOfMeasure, version, evidence, approvedBy, and approvedAt. These references describe the Invoice, Item, and Preferences versions and approved factual mappings actually used; they are not raw provider payloads or credentials.

Stored invoice lines include sourceLineId and nullable sourceItemId. Under transaction-level tax or discounts, unallocated line taxAmountMinor, discountAmountMinor, and totalAmountMinor remain null. The example has USD 100.00 of items and USD 8.00 of transaction tax; it does not invent item-level tax or a PO. Its box unit is backed by the synthetic merchant approval, never a global unit default.

SDK lookup and retrieval
// carden is the configured server-side client with an opted-in invoices:read key.
// order.quickbooksInvoiceId is the actual source ID stored with your order.
const page = await carden.invoices.list({
  quickbooksInvoiceId: order.quickbooksInvoiceId,
  limit: 20,
}, { timeoutMs: 5000 });
if (page.invoices.length !== 1 || page.nextCursor !== null) {
  throw new Error("Resolve the missing or ambiguous invoice before preparing payment data.");
}
const invoice = await carden.invoices.retrieve(page.invoices[0].id, { timeoutMs: 5000 });
if (!invoice.ready || !invoice.revision) {
  throw new Error("Review invoice issues and refresh the source before preparation.");
}
// Preparation rechecks access, freshness, revision, and payment eligibility.
// A ready lookup is not a reservation or a guarantee that preparation will succeed.

carden.invoices.retrieve(id, options?) returns InvoiceDetail directly. Public docs expose only synthetic examples; invoice reads remain authenticated and limited to the linked source.

Prepare Stripe fields from an invoice

Prepare from stored invoice · invoices:read + enrichment:write
POST /api/v1/stripe/payment-intent-enrichment/from-invoice

Body fieldRule
invoiceIdCarden invoice UUID. Supply exactly one of invoiceId, quickbooksInvoiceId, or invoiceNumber.
quickbooksInvoiceIdExact external QuickBooks Invoice ID, as an alternative to the other two selectors.
invoiceNumberExact source number, only when it resolves unambiguously.
amountMinorRequired positive safe integer. Must equal the entire open, unpaid invoice total and balance.
currencyRequired three lowercase letters. Must match the invoice currency exactly.
expectedRevisionOptional source/mapping revision from lookup. Recommended to reject a change between review and preparation.
idempotencyKeyRequired, 1–160 letters, digits, periods, underscores, colons, or hyphens. Persist before the first preparation request.

The body is strict: it accepts invoice references, payment expectations, and idempotency, not an inline invoice, arbitrary source selection, or unapproved field overrides. Supplying zero or multiple invoice selectors is invalid.

Preparation request
{
  "invoiceId": "11111111-1111-4111-8111-111111111111",
  "amountMinor": 10800,
  "currency": "usd",
  "expectedRevision": "invoice-revision-example-3",
  "idempotencyKey": "prepare_attempt_1042_1"
}

  • Only exact full, positive, open, unpaid invoices are supported. Partial payments, already-paid invoices, combined invoices, amount mismatches, and currency mismatches are blocked.
  • The linked source must be active and fresh with no pending refresh. Missing, stale, ambiguous, paused, or disconnected source state is an exception, not an automatic live provider pull.
  • Unsupported tax-inclusive data, group lines, ambiguous shipping, unresolved item facts, and invalid arithmetic stay blocked. Merchant-confirmed product-code and unit mappings must preserve actual source meaning.

Prepared fields and stable identity

200 OK · Stripe fields plus preparation metadata
{
  "object": "stripe.payment_intent_enrichment",
  "api_version": "v1",
  "data": {
    "payment_details": {
      "order_reference": "INV-1042"
    },
    "amount_details": {
      "enforce_arithmetic_validation": true,
      "line_items": [
        {
          "product_name": "Industrial filters, boxed",
          "product_code": "FILTER-01",
          "unit_cost": 5000,
          "quantity": 2,
          "unit_of_measure": "box"
        }
      ],
      "tax": {
        "total_tax_amount": 800
      }
    }
  },
  "preparation": {
    "id": "44444444-4444-4444-8444-444444444444",
    "invoiceId": "11111111-1111-4111-8111-111111111111",
    "snapshotId": "22222222-2222-4222-8222-222222222222",
    "revision": "invoice-revision-example-3",
    "sourceIntegrationId": "33333333-3333-4333-8333-333333333333",
    "sourceConnectionId": "quickbooks_connection_example",
    "checkedThrough": "2026-01-01T11:59:00.000Z",
    "createdAt": "2026-01-01T12:00:00.000Z",
    "amountMinor": 10800,
    "currency": "usd"
  }
}

The HTTP response uses object: stripe.payment_intent_enrichment and api_version: v1. data contains only amount_details and payment_details; preparation is a separate top-level property beside data. When using HTTP directly, merge only data into your merchant-owned Stripe request and retain preparation separately.

Preparation fieldMeaning
idStable UUID of the saved preparation. Use this as enrichmentRequestId when reporting this flow.
invoiceId / snapshotId / revisionCarden invoice identity, immutable invoice snapshot, and the exact source/mapping revision used.
sourceIntegrationId / sourceConnectionIdThe QuickBooks source integration and connection that supplied the evidence.
checkedThrough / createdAtThe source check boundary and preparation creation time.
amountMinor / currencyThe exact full payment amount and currency validated for this preparation.

carden.stripe.createPaymentIntentEnrichmentFromInvoice(input, options?) returns { enrichment, preparation, requestId }. enrichment contains only Stripe fields. requestId comes from x-carden-request-id and can be null if the header is absent; it is an HTTP diagnostic ID, not the stable preparation.id.

Accepted identical retries reuse the saved preparation.id and snapshot while current source checks still pass, even though HTTP request IDs differ. A changed source, link, connection, mapping revision, or pending refresh can block replay; idempotency is not a freshness bypass. Reusing the same idempotency key with changed input conflicts. Keep Carden preparation idempotency, your own Stripe payment idempotency, and immutable report event IDs separate.

Handle exceptions and preserve history

ConditionRecovery
Missing or ambiguous invoiceResolve the exact source identity and current connection. Never silently select a similar record.
Pending refresh, stale source, or missing dependenciesFinish the authorized source refresh, inspect issues, and retrieve the current revision.
Paused, disconnected, or inaccessible sourceRestore approved access to the intended source before new preparation; preserve historical reports.
Revision or idempotency conflictReview the changed source/input. Start an explicitly new preparation only after verifying facts and payment state.
Mapping exceptionRecord merchant-confirmed values and evidence. Reprocess trusted current-source failures, not tombstones, ambiguous records, or old sources.
Report delivery failure after StripeRetry the saved observation with preparation.id; never repeat the payment because reporting failed.

After preparation, a source edit or disconnect does not invalidate the need to record an actual payment outcome. Submit reports under the still-authorized Stripe destination using the original preparation.id. Amount and currency mismatches are recorded as correlation exceptions, not successful enrichment; the observed payment facts are retained. Verify invoice references in your own backend as well; the current automatic checks compare amount and currency.

The immutable snapshot and exact source/mapping references are historical preparation evidence, not current source eligibility or proof of qualified savings. Read HTTP status and safe issue details for recovery, retain x-carden-request-id, and use settlement evidence separately for financial claims.