> For the complete documentation index, see [llms.txt](https://docs.getsphere.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.getsphere.com/features/integrations/api/transaction-api/transactions.md).

# Transactions

Create invoices and credit notes, retrieve them, and cancel a transaction.

A transaction is an invoice (`type: debit`) or a credit note (`type: credit`). Create it as a `pending` draft or `finalized` in one call and finalizing runs the tax engine and returns `subtotal`, `tax` and `total`. A credit note sets `type: credit` and references the original invoice with `original_transaction_id`.

## Create a transaction

> Create an invoice (type: debit) or a credit note (type: credit), as a pending draft or finalized in one call. A finalized request runs the tax engine and returns subtotal, tax and total. Re-posting the same external\_id updates the transaction.

```json
{"openapi":"3.1.0","info":{"title":"Sphere API","version":"1.0.0"},"servers":[{"url":"https://api.getsphere.com/v1"},{"url":"https://server.getsphere.com/tax_api/v1"}],"security":[{"apiKeyAuth":[]}],"components":{"securitySchemes":{"apiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-KEY"}},"schemas":{"CreateTransactionRequest":{"additionalProperties":false,"description":"Body for POST /v1/transactions. ``external_id`` is the natural\nidempotency key. ``customer_id`` / ``product_id`` / ``original_transaction_id``\nall reference the caller's own external ids (never Sphere PKs). The customer\nand each line's product are created if missing, and the inline detail here\n(``customer_name`` / ``customer_email`` / ``customer_tax_ids`` /\n``customer_tax_exempt`` / ``billing_address`` and each line's\n``product_name`` / ``product_tax_code``) is applied whenever sent — omitted\nfields keep the record's current value.","properties":{"external_id":{"maxLength":255,"minLength":1,"title":"External Id","type":"string"},"type":{"allOf":[{"$ref":"#/components/schemas/TypeEnum"}],"title":"Type"},"status":{"allOf":[{"$ref":"#/components/schemas/CreateTransactionRequestStatusEnum"}],"title":"Status"},"currency":{"description":"ISO 4217 currency code, e.g. USD.","maxLength":3,"minLength":3,"title":"Currency","type":"string"},"customer_id":{"maxLength":255,"minLength":1,"title":"Customer Id","type":"string"},"finalized_on":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"default":null,"title":"Finalized On"},"external_reference_number":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"default":null,"title":"External Reference Number"},"billing_address":{"anyOf":[{"$ref":"#/components/schemas/AddressRequest"},{"type":"null"}],"default":null},"shipping_address":{"anyOf":[{"$ref":"#/components/schemas/AddressRequest"},{"type":"null"}],"default":null},"line_items":{"items":{"$ref":"#/components/schemas/TransactionLineItemRequest"},"minItems":1,"title":"Line Items","type":"array"},"original_transaction_id":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"default":null,"title":"Original Transaction Id"},"description":{"anyOf":[{"maxLength":1024,"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"customer_name":{"anyOf":[{"maxLength":1024,"type":"string"},{"type":"null"}],"default":null,"title":"Customer Name"},"customer_email":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"default":null,"title":"Customer Email"},"customer_tax_ids":{"anyOf":[{"items":{"$ref":"#/components/schemas/CustomerTaxIdRequest"},"type":"array"},{"type":"null"}],"default":null,"title":"Customer Tax Ids"},"customer_tax_exempt":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"title":"Customer Tax Exempt"},"sphere_tax_calculation_id":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"default":null,"description":"Finalize this transaction using a prior tax calculation instead of recalculating. Pass the sphere_tax_calculation_id returned by a previous POST /tax_api/calculate_tax call to commit the exact quote shown to the customer — the stored tax is applied verbatim and the transaction is linked to that calculation. The calculation's line items must cover this transaction's lines. Valid only when status is 'finalized'; omit to calculate fresh at finalization.","title":"Sphere Tax Calculation Id"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"Arbitrary JSON object to store alongside the transaction and return on reads — e.g. your own order id or notes. Omit to leave the current value unchanged; pass null to clear it. At most 16384 bytes when serialized.","title":"Metadata"}},"required":["external_id","type","status","currency","customer_id","line_items"],"title":"CreateTransactionRequest","type":"object"},"TypeEnum":{"enum":["debit","credit"],"type":"string"},"CreateTransactionRequestStatusEnum":{"enum":["pending","finalized"],"type":"string"},"AddressRequest":{"additionalProperties":false,"description":"A postal address (billing or shipping).","properties":{"address1":{"anyOf":[{"maxLength":1024,"type":"string"},{"type":"null"}],"default":null,"title":"Address1"},"address2":{"anyOf":[{"maxLength":1024,"type":"string"},{"type":"null"}],"default":null,"title":"Address2"},"city":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"default":null,"title":"City"},"state":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"default":null,"title":"State"},"postal_code":{"anyOf":[{"maxLength":64,"type":"string"},{"type":"null"}],"default":null,"title":"Postal Code"},"country":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"default":null,"title":"Country"}},"title":"AddressRequest","type":"object"},"TransactionLineItemRequest":{"additionalProperties":false,"description":"One line on a transaction. ``amount`` is a major-unit decimal (e.g.\n\"100.00\"); ``product_id`` is the caller's product external_id. The product is\ncreated if it doesn't exist, and ``product_name`` / ``product_tax_code``, when\nsent, are applied to it (created or existing) — omitted fields keep the\nproduct's current value. A product with no tax code is UNKNOWN.\n\n``quantity`` and ``unit_price`` are optional and carried through for the\ninvoice document only. ``amount`` stays the authoritative taxable total —\nthey are not cross-validated against it (discounts, tax-inclusive pricing,\nand rounding legitimately break quantity * unit_price == amount).","properties":{"external_id":{"maxLength":238,"minLength":1,"title":"External Id","type":"string"},"product_id":{"maxLength":255,"minLength":1,"title":"Product Id","type":"string"},"amount":{"pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Amount","type":"string"},"discount_amount":{"default":"0","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Discount Amount","type":"string"},"quantity":{"anyOf":[{"pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","type":"string"},{"type":"null"}],"default":null,"title":"Quantity"},"unit_price":{"anyOf":[{"pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","type":"string"},{"type":"null"}],"default":null,"title":"Unit Price"},"description":{"anyOf":[{"maxLength":1024,"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"tax_inclusive":{"default":false,"title":"Tax Inclusive","type":"boolean"},"product_name":{"anyOf":[{"maxLength":1024,"type":"string"},{"type":"null"}],"default":null,"title":"Product Name"},"product_tax_code":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Product Tax Code"}},"required":["external_id","product_id","amount"],"title":"TransactionLineItemRequest","type":"object"},"CustomerTaxIdRequest":{"additionalProperties":false,"description":"A tax identifier on a customer (e.g. a VAT number).","properties":{"tax_id":{"maxLength":255,"minLength":1,"title":"Tax Id","type":"string"},"country":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"default":null,"title":"Country"},"secondary_id":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"default":null,"description":"Egypt only: the UIN, validated together with the TRN in tax_id. Ignored for every other country. Send other registrations, such as a Québec QST alongside a GST number, as separate tax_ids entries.","title":"Secondary Id"}},"required":["tax_id"],"title":"CustomerTaxIdRequest","type":"object"},"TransactionResponse":{"description":"A transaction. subtotal, tax and total appear once finalized, and\noriginal_transaction_id only on credit notes.","properties":{"external_id":{"title":"External Id","type":"string"},"type":{"title":"Type","type":"string"},"status":{"title":"Status","type":"string"},"currency":{"title":"Currency","type":"string"},"external_reference_number":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"External Reference Number"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Customer Id"},"finalized_on":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"format":"date-time","title":"Finalized On"},"line_items":{"items":{"$ref":"#/components/schemas/LineItemResponse"},"title":"Line Items","type":"array"},"original_transaction_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Original Transaction Id"},"subtotal":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Subtotal"},"tax":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tax"},"total":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Total"},"invoice_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Link to download the invoice as an HTML file, present once the transaction is finalized or paid. Expires after 1 hour; fetch the transaction again for a fresh link rather than storing it.","format":"uri","title":"Invoice Url"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"The JSON object supplied when the transaction was written.","title":"Metadata"},"created_at":{"format":"date-time","title":"Created At","type":"string"}},"required":["external_id","type","status","currency","created_at"],"title":"TransactionResponse","type":"object"},"LineItemResponse":{"description":"A transaction line item.","properties":{"external_id":{"title":"External Id","type":"string"},"product_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Product Id"},"amount":{"title":"Amount","type":"string"},"discount_amount":{"title":"Discount Amount","type":"string"},"quantity":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Quantity"},"unit_price":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Unit Price"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"tax":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tax"}},"required":["external_id","amount","discount_amount"],"title":"LineItemResponse","type":"object"}}},"paths":{"/transactions":{"post":{"operationId":"transactions_create","description":"Create an invoice (type: debit) or a credit note (type: credit), as a pending draft or finalized in one call. A finalized request runs the tax engine and returns subtotal, tax and total. Re-posting the same external_id updates the transaction.","summary":"Create a transaction","tags":["Transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTransactionRequest"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/CreateTransactionRequest"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/CreateTransactionRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionResponse"}}},"description":""},"400":{"description":"Validation error, keyed by the failing field."},"403":{"description":"Missing, invalid, or inactive API key, or a key not provisioned for the Transaction API."},"429":{"description":"Rate limit exceeded. Carries Retry-After and RateLimit-* headers."}}}}}}
```

## GET /transactions/{external\_id}

> Retrieve a transaction

```json
{"openapi":"3.1.0","info":{"title":"Sphere API","version":"1.0.0"},"servers":[{"url":"https://api.getsphere.com/v1"},{"url":"https://server.getsphere.com/tax_api/v1"}],"security":[{"apiKeyAuth":[]}],"components":{"securitySchemes":{"apiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-KEY"}},"schemas":{"TransactionResponse":{"description":"A transaction. subtotal, tax and total appear once finalized, and\noriginal_transaction_id only on credit notes.","properties":{"external_id":{"title":"External Id","type":"string"},"type":{"title":"Type","type":"string"},"status":{"title":"Status","type":"string"},"currency":{"title":"Currency","type":"string"},"external_reference_number":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"External Reference Number"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Customer Id"},"finalized_on":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"format":"date-time","title":"Finalized On"},"line_items":{"items":{"$ref":"#/components/schemas/LineItemResponse"},"title":"Line Items","type":"array"},"original_transaction_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Original Transaction Id"},"subtotal":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Subtotal"},"tax":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tax"},"total":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Total"},"invoice_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Link to download the invoice as an HTML file, present once the transaction is finalized or paid. Expires after 1 hour; fetch the transaction again for a fresh link rather than storing it.","format":"uri","title":"Invoice Url"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"The JSON object supplied when the transaction was written.","title":"Metadata"},"created_at":{"format":"date-time","title":"Created At","type":"string"}},"required":["external_id","type","status","currency","created_at"],"title":"TransactionResponse","type":"object"},"LineItemResponse":{"description":"A transaction line item.","properties":{"external_id":{"title":"External Id","type":"string"},"product_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Product Id"},"amount":{"title":"Amount","type":"string"},"discount_amount":{"title":"Discount Amount","type":"string"},"quantity":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Quantity"},"unit_price":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Unit Price"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Description"},"tax":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tax"}},"required":["external_id","amount","discount_amount"],"title":"LineItemResponse","type":"object"}}},"paths":{"/transactions/{external_id}":{"get":{"operationId":"transactions_retrieve","summary":"Retrieve a transaction","parameters":[{"in":"path","name":"external_id","schema":{"type":"string"},"description":"The external_id you assigned to the record.","required":true}],"tags":["Transactions"],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionResponse"}}},"description":""},"403":{"description":"Missing, invalid, or inactive API key, or a key not provisioned for the Transaction API."},"404":{"description":"No record with that external_id."},"429":{"description":"Rate limit exceeded. Carries Retry-After and RateLimit-* headers."}}}}}}
```

## Cancel a transaction

> Voids a transaction so it no longer contributes to your tax liability. No request body is needed, and the call is idempotent (re-cancelling returns the original cancelled\_at).

```json
{"openapi":"3.1.0","info":{"title":"Sphere API","version":"1.0.0"},"servers":[{"url":"https://api.getsphere.com/v1"},{"url":"https://server.getsphere.com/tax_api/v1"}],"security":[{"apiKeyAuth":[]}],"components":{"securitySchemes":{"apiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-KEY"}},"schemas":{"CancelResponse":{"description":"A cancelled transaction.","properties":{"external_id":{"title":"External Id","type":"string"},"status":{"title":"Status","type":"string"},"cancelled_at":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"format":"date-time","title":"Cancelled At"}},"required":["external_id","status"],"title":"CancelResponse","type":"object"}}},"paths":{"/transactions/{external_id}/cancel":{"post":{"operationId":"transactions_cancel_create","description":"Voids a transaction so it no longer contributes to your tax liability. No request body is needed, and the call is idempotent (re-cancelling returns the original cancelled_at).","summary":"Cancel a transaction","parameters":[{"in":"path","name":"external_id","schema":{"type":"string"},"description":"The external_id you assigned to the record.","required":true}],"tags":["Transactions"],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelResponse"}}},"description":""},"403":{"description":"Missing, invalid, or inactive API key, or a key not provisioned for the Transaction API."},"404":{"description":"No record with that external_id."},"429":{"description":"Rate limit exceeded. Carries Retry-After and RateLimit-* headers."}}}}}}
```
