Create a credit note (line-based, or commit relief)
const url = 'http://localhost:8080/v1/credit-notes';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"invoice_id":"example","reason":"example","lines":[{"invoice_line_item_id":"example","description":"example","quantity":1,"unit_amount_cents":1}],"refund_amount_cents":1,"credit_amount_cents":1,"out_of_band_amount_cents":1,"refund_type":"refund","auto_issue":true,"commit_relief":{"invoice_id":"example","reason":"example","retire_cents":1,"retire_all":true,"refund_amount_cents":1,"out_of_band_amount_cents":1}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url http://localhost:8080/v1/credit-notes \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "invoice_id": "example", "reason": "example", "lines": [ { "invoice_line_item_id": "example", "description": "example", "quantity": 1, "unit_amount_cents": 1 } ], "refund_amount_cents": 1, "credit_amount_cents": 1, "out_of_band_amount_cents": 1, "refund_type": "refund", "auto_issue": true, "commit_relief": { "invoice_id": "example", "reason": "example", "retire_cents": 1, "retire_all": true, "refund_amount_cents": 1, "out_of_band_amount_cents": 1 } }'Two shapes. LINE-BASED (regular invoices): lines[] + refund/credit/out_of_band allocation; capped by the invoice’s remaining creditable gross. COMMIT RELIEF (ADR-080, paid commit invoices only): pass commit_relief and NO lines — the server retires commit credits and derives the refundable cash from the telescoping price-ratio anchor (discounted commits refund at the purchase rate, never at face). The relief credit note is created AND issued in one transaction; the credit-balance channel is forbidden on relief. Unpaid commit invoices: void the invoice instead.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”Makes the call safe to retry. Send a unique value (a UUID works) and
the same value on every retry. For 24 hours, a repeat with the same
key, method, path and body gets the first response again, with an
Idempotent-Replayed: true header, instead of running again. The
error cases are in docs/api-surface.md. The usage routes do not take
it: each usage event carries its own idempotency_key.
Request Bodyrequired
Section titled “Request Bodyrequired”object
object
Optional. The invoice line this credit line reverses.
Not with commit_relief; put the relief’s split inside commit_relief.
Not with commit_relief; put the relief’s split inside commit_relief.
Older single-channel form. On a paid invoice whose three
*_amount_cents fields are all 0, refund or credit
puts the whole note in that channel. Not with commit_relief.
Mutually exclusive with lines and credit_amount_cents. The
relief’s split goes in here, not at the top level: a top-level
refund_amount_cents, out_of_band_amount_cents or
refund_type is a 422. Example after a lost dispute:
{"invoice_id": "inv_…", "commit_relief": {"retire_all": true, "out_of_band_amount_cents": 5000}}.
object
Optional. Defaults to the top-level invoice_id.
Optional. Defaults to the top-level reason.
Commit credits to retire (1..remaining).
Retire the LIVE remaining (absorbs racing drawdowns).
Optional allocation; must sum with out_of_band to the derived cash.
Responses
Section titled “Responses”Credit note (issued immediately for commit relief)
A credit note reduces what a customer owes on an invoice, or gives
money back after it was paid. Its total is split three ways: refund
to the card (refund_amount_cents), credit to the customer’s
balance (credit_amount_cents), and money returned outside Hardcount
(out_of_band_amount_cents).
object
Prepaid commit credits this note retired. Absent on other notes.
The refund part’s state at Stripe. unknown: Stripe gave no
clear answer (a timeout, a network error, a Stripe 5xx, a 409 or
a 429), so the customer may already be refunded. Don’t refund it
again in the Stripe Dashboard. Retry it with
POST /v1/credit-notes/{id}/retry-refund, which looks for the
refund at Stripe first and then resends the same request with
the same idempotency key.
What an issued invoice or credit note prints about its buyer, copied
when the document was issued (ADR-109). The printed name is
legal_name when set, otherwise display_name.
object
On an invoice, the tax ID its tax was calculated with when set, otherwise the billing profile’s tax ID at issue.
What an issued invoice or credit note prints about its seller (the tenant’s company), copied when the document was issued (ADR-109).
object
Tax provider’s reversal transaction, set when the note is issued.
True when issued_at is test-clock time.
True on a draft that Hardcount will issue automatically.
True when the tax reversal failed and will be retried.
object
Real-world time the row was written, when created_at is test-clock time.
Example
{ "status": "draft", "refund_status": "none"}State gate (unpaid commit → void; fully-consumed commit; in-flight charge)
Validation (over-retire with live remaining; allocation mismatch; zero-cash slice), or an unknown field (param names it; the body must use only the fields listed here)