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

# Payments

Payments against invoices.

A payment is money received for an invoice, online through Shortcut or recorded offline. Offline payments can be reversed.

Fields: [The payment object](https://docs.shortcutco.com/developers/reference/objects/payment) · [The payment reversal object](https://docs.shortcutco.com/developers/reference/objects/payment-reversal).

## Record an offline payment

> Records a cash, check, or other offline payment that settles an invoice in full, as Mark paid does in the app: \`amount\` must equal the invoice's \`total\`, and the invoice becomes paid. Partial payments are not supported (\`422 amount\_mismatch\`). Paid and void invoices are refused, and so is an invoice with an online payment in progress (a bank payment awaiting confirmation, or an open checkout link), before anything happens, as the app hides Mark paid then. No card or bank account is ever charged. \`paidOn\` cannot be after today in the workspace's timezone. Repeating a request after it succeeded, with or without its \`Idempotency-Key\`, returns the payment it recorded with \`meta.alreadyRecorded: true\`. Your invoice-paid automations, which may email or text the customer, and Automations rules that start when a payment is recorded or an invoice is paid, run only if the token has \`automations:trigger\`.\
> \
> Returns \[the payment object]\(<https://docs.shortcutco.com/developers/reference/objects/payment).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`amount\_mismatch\`]\(<https://docs.shortcutco.com/developers/concepts/errors#amount\\_mismatch>), \[\`dependency\_unavailable\`]\(<https://docs.shortcutco.com/developers/concepts/errors#dependency\\_unavailable>), \[\`rule\_violation\`]\(<https://docs.shortcutco.com/developers/concepts/errors#rule\\_violation>), \[\`state\_conflict\`]\(<https://docs.shortcutco.com/developers/concepts/errors#state\\_conflict>). Every endpoint can also return the \[common errors]\(<https://docs.shortcutco.com/developers/concepts/errors>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Payments","description":"A payment is money received for an invoice, online through Shortcut or recorded offline. Offline payments can be reversed.\n\nFields: [The payment object](https://docs.shortcutco.com/developers/reference/objects/payment) · [The payment reversal object](https://docs.shortcutco.com/developers/reference/objects/payment-reversal)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["payments:write"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"scut_<env>_<id>_<secret>","description":"A workspace API token. Each operation lists the scopes it needs; `write` implies `read`, and `send`/`complete` are never implied."}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Any string up to 255 characters. Retrying with the same key returns the first response instead of repeating the write, for 24 hours.","schema":{"type":"string","maxLength":255}}},"headers":{"RateLimitLimit":{"schema":{"type":"integer"},"description":"Requests allowed in the tightest window."},"RateLimitRemaining":{"schema":{"type":"integer"},"description":"Requests left in that window."},"RateLimitReset":{"schema":{"type":"integer"},"description":"Seconds until that window resets."}},"schemas":{"Payment":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The payment's id."},"object":{"type":"string","const":"payment","description":"Always `payment`."},"invoiceId":{"type":"string","format":"uuid","description":"The invoice the payment applies to."},"customerId":{"type":"string","format":"uuid","description":"The customer who paid."},"amount":{"type":"number","description":"Amount paid, in US dollars."},"method":{"type":"string","enum":["online","cash","check","ach","other"],"description":"`online` when the customer paid through Shortcut (card or bank). Otherwise how the workspace recorded an offline payment: `cash`, `check`, `ach` (a bank transfer made outside Shortcut), or `other`."},"reference":{"type":["string","null"],"description":"The reference recorded with an offline payment, such as a check number."},"refundedAmount":{"type":"number","description":"Total of the refunds against this payment that have succeeded as of this request, in US dollars; 0 when none. A refund can succeed later without changing the payment or its invoice, so `createdSince` and `updatedSince` syncs do not pick up refund changes; read the payment again for the current total."},"paidAt":{"type":"string","format":"date-time","description":"When the payment was made, ISO 8601 in UTC."},"createdAt":{"type":"string","format":"date-time","description":"When the payment was recorded, ISO 8601 in UTC."}},"required":["id","object","invoiceId","customerId","amount","method","reference","refundedAmount","paidAt","createdAt"],"additionalProperties":false,"description":"A payment against an invoice."},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","description":"Error family, such as `invalid_request` or `permission`."},"code":{"type":"string","description":"Specific error code; see the errors page."},"message":{"type":"string","description":"A human-readable explanation."},"param":{"type":"string","description":"The input the error is about, such as `query.limit`."},"requiredScope":{"type":"string","description":"The scope the token is missing."},"requestId":{"type":"string","description":"Quote this id to support."},"docs":{"type":"string","description":"Link to the error's documentation."}},"required":["type","code","message","requestId","docs"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}},"responses":{"BadRequest":{"description":"The request is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthenticated":{"description":"The token is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"SubscriptionRequired":{"description":"The workspace's subscription needs attention.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The token is missing a required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such object in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"Conflict with the current state or an in-flight request with the same idempotency key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unprocessable":{"description":"The request cannot be applied, or its idempotency key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"Temporarily unavailable; retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/invoices/{id}/payments":{"post":{"operationId":"invoices.payments.create","tags":["Payments"],"summary":"Record an offline payment","description":"Records a cash, check, or other offline payment that settles an invoice in full, as Mark paid does in the app: `amount` must equal the invoice's `total`, and the invoice becomes paid. Partial payments are not supported (`422 amount_mismatch`). Paid and void invoices are refused, and so is an invoice with an online payment in progress (a bank payment awaiting confirmation, or an open checkout link), before anything happens, as the app hides Mark paid then. No card or bank account is ever charged. `paidOn` cannot be after today in the workspace's timezone. Repeating a request after it succeeded, with or without its `Idempotency-Key`, returns the payment it recorded with `meta.alreadyRecorded: true`. Your invoice-paid automations, which may email or text the customer, and Automations rules that start when a payment is recorded or an invoice is paid, run only if the token has `automations:trigger`.\n\nReturns [the payment object](https://docs.shortcutco.com/developers/reference/objects/payment).\n\n**Errors specific to this endpoint:** [`amount_mismatch`](https://docs.shortcutco.com/developers/concepts/errors#amount_mismatch), [`dependency_unavailable`](https://docs.shortcutco.com/developers/concepts/errors#dependency_unavailable), [`rule_violation`](https://docs.shortcutco.com/developers/concepts/errors#rule_violation), [`state_conflict`](https://docs.shortcutco.com/developers/concepts/errors#state_conflict). Every endpoint can also return the [common errors](https://docs.shortcutco.com/developers/concepts/errors).","parameters":[{"name":"id","in":"path","required":true,"description":"The object's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amount":{"type":"number","exclusiveMinimum":0,"description":"Amount received, in US dollars. It must equal the invoice's `total`: recording a payment settles the invoice in full, as Mark paid does in the app."},"method":{"type":"string","enum":["cash","check","other"],"description":"How the customer paid outside Shortcut."},"paidOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day the payment was received, `YYYY-MM-DD`, no later than today in the workspace's timezone. Defaults to now. The payment's `paidAt` is stored as midnight UTC of that date, as the app stores a chosen paid date."},"reference":{"type":"string","minLength":1,"maxLength":255,"description":"A reference such as a check number."}},"required":["amount","method"],"additionalProperties":false}}}},"responses":{"200":{"description":"The same payment was already recorded for this invoice: nothing was recorded again, and `meta.alreadyRecorded` is true.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Payment"},"meta":{"type":"object","properties":{},"additionalProperties":true,"description":"Facts about this request beside the object, such as `alreadyReminded` on a repeated reminder. Present only when there is something to report."}},"required":["data"],"additionalProperties":false}}}},"201":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Payment"},"meta":{"type":"object","properties":{},"additionalProperties":true,"description":"Facts about this request beside the object, such as `alreadyReminded` on a repeated reminder. Present only when there is something to report."}},"required":["data"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/SubscriptionRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}}}}
```

## List payments

> Payments newest first, or oldest first from \`createdSince\`, which syncs new payments. \`refundedAmount\` is the succeeded-refund total at read time; a later refund changes neither the payment nor its invoice, so a sync does not pick it up. A manual payment the workspace undoes is removed; its invoice's \`updatedAt\` changes.\
> \
> Returns a list of \[payment objects]\(<https://docs.shortcutco.com/developers/reference/objects/payment>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Payments","description":"A payment is money received for an invoice, online through Shortcut or recorded offline. Offline payments can be reversed.\n\nFields: [The payment object](https://docs.shortcutco.com/developers/reference/objects/payment) · [The payment reversal object](https://docs.shortcutco.com/developers/reference/objects/payment-reversal)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["payments:read"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"scut_<env>_<id>_<secret>","description":"A workspace API token. Each operation lists the scopes it needs; `write` implies `read`, and `send`/`complete` are never implied."}},"headers":{"RateLimitLimit":{"schema":{"type":"integer"},"description":"Requests allowed in the tightest window."},"RateLimitRemaining":{"schema":{"type":"integer"},"description":"Requests left in that window."},"RateLimitReset":{"schema":{"type":"integer"},"description":"Seconds until that window resets."}},"schemas":{"Payment":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The payment's id."},"object":{"type":"string","const":"payment","description":"Always `payment`."},"invoiceId":{"type":"string","format":"uuid","description":"The invoice the payment applies to."},"customerId":{"type":"string","format":"uuid","description":"The customer who paid."},"amount":{"type":"number","description":"Amount paid, in US dollars."},"method":{"type":"string","enum":["online","cash","check","ach","other"],"description":"`online` when the customer paid through Shortcut (card or bank). Otherwise how the workspace recorded an offline payment: `cash`, `check`, `ach` (a bank transfer made outside Shortcut), or `other`."},"reference":{"type":["string","null"],"description":"The reference recorded with an offline payment, such as a check number."},"refundedAmount":{"type":"number","description":"Total of the refunds against this payment that have succeeded as of this request, in US dollars; 0 when none. A refund can succeed later without changing the payment or its invoice, so `createdSince` and `updatedSince` syncs do not pick up refund changes; read the payment again for the current total."},"paidAt":{"type":"string","format":"date-time","description":"When the payment was made, ISO 8601 in UTC."},"createdAt":{"type":"string","format":"date-time","description":"When the payment was recorded, ISO 8601 in UTC."}},"required":["id","object","invoiceId","customerId","amount","method","reference","refundedAmount","paidAt","createdAt"],"additionalProperties":false,"description":"A payment against an invoice."},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","description":"Error family, such as `invalid_request` or `permission`."},"code":{"type":"string","description":"Specific error code; see the errors page."},"message":{"type":"string","description":"A human-readable explanation."},"param":{"type":"string","description":"The input the error is about, such as `query.limit`."},"requiredScope":{"type":"string","description":"The scope the token is missing."},"requestId":{"type":"string","description":"Quote this id to support."},"docs":{"type":"string","description":"Link to the error's documentation."}},"required":["type","code","message","requestId","docs"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}},"responses":{"BadRequest":{"description":"The request is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthenticated":{"description":"The token is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"SubscriptionRequired":{"description":"The workspace's subscription needs attention.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The token is missing a required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such object in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"Temporarily unavailable; retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/payments":{"get":{"operationId":"payments.list","tags":["Payments"],"summary":"List payments","description":"Payments newest first, or oldest first from `createdSince`, which syncs new payments. `refundedAmount` is the succeeded-refund total at read time; a later refund changes neither the payment nor its invoice, so a sync does not pick it up. A manual payment the workspace undoes is removed; its invoice's `updatedAt` changes.\n\nReturns a list of [payment objects](https://docs.shortcutco.com/developers/reference/objects/payment).","parameters":[{"name":"limit","in":"query","required":false,"description":"How many items to return, 1-200. Defaults to 50.","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `meta.nextCursor` from the previous page. Omit it for the first page.","schema":{"type":"string","minLength":1,"maxLength":4096}},{"name":"invoiceId","in":"query","required":false,"description":"Only payments against this invoice.","schema":{"type":"string","format":"uuid"}},{"name":"customerId","in":"query","required":false,"description":"Only this customer's payments.","schema":{"type":"string","format":"uuid"}},{"name":"createdSince","in":"query","required":false,"description":"ISO 8601 timestamp. Returns objects created at or after it, oldest first. Keep the largest `createdAt` you have seen, subtract five minutes, and pass it on the next sync; deduplicate by `id`.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Payment"}},"meta":{"type":"object","properties":{"nextCursor":{"type":["string","null"],"description":"Pass as `cursor` to get the next page; null on the last page."},"hasMore":{"type":"boolean","description":"Whether another page exists."}},"required":["nextCursor","hasMore"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/SubscriptionRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}}}}
```

## Get a payment

> One payment: its invoice, amount, how it was paid, and \`refundedAmount\`, the succeeded-refund total at the time of the request.\
> \
> Returns \[the payment object]\(<https://docs.shortcutco.com/developers/reference/objects/payment>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Payments","description":"A payment is money received for an invoice, online through Shortcut or recorded offline. Offline payments can be reversed.\n\nFields: [The payment object](https://docs.shortcutco.com/developers/reference/objects/payment) · [The payment reversal object](https://docs.shortcutco.com/developers/reference/objects/payment-reversal)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["payments:read"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"scut_<env>_<id>_<secret>","description":"A workspace API token. Each operation lists the scopes it needs; `write` implies `read`, and `send`/`complete` are never implied."}},"headers":{"RateLimitLimit":{"schema":{"type":"integer"},"description":"Requests allowed in the tightest window."},"RateLimitRemaining":{"schema":{"type":"integer"},"description":"Requests left in that window."},"RateLimitReset":{"schema":{"type":"integer"},"description":"Seconds until that window resets."}},"schemas":{"Payment":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The payment's id."},"object":{"type":"string","const":"payment","description":"Always `payment`."},"invoiceId":{"type":"string","format":"uuid","description":"The invoice the payment applies to."},"customerId":{"type":"string","format":"uuid","description":"The customer who paid."},"amount":{"type":"number","description":"Amount paid, in US dollars."},"method":{"type":"string","enum":["online","cash","check","ach","other"],"description":"`online` when the customer paid through Shortcut (card or bank). Otherwise how the workspace recorded an offline payment: `cash`, `check`, `ach` (a bank transfer made outside Shortcut), or `other`."},"reference":{"type":["string","null"],"description":"The reference recorded with an offline payment, such as a check number."},"refundedAmount":{"type":"number","description":"Total of the refunds against this payment that have succeeded as of this request, in US dollars; 0 when none. A refund can succeed later without changing the payment or its invoice, so `createdSince` and `updatedSince` syncs do not pick up refund changes; read the payment again for the current total."},"paidAt":{"type":"string","format":"date-time","description":"When the payment was made, ISO 8601 in UTC."},"createdAt":{"type":"string","format":"date-time","description":"When the payment was recorded, ISO 8601 in UTC."}},"required":["id","object","invoiceId","customerId","amount","method","reference","refundedAmount","paidAt","createdAt"],"additionalProperties":false,"description":"A payment against an invoice."},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","description":"Error family, such as `invalid_request` or `permission`."},"code":{"type":"string","description":"Specific error code; see the errors page."},"message":{"type":"string","description":"A human-readable explanation."},"param":{"type":"string","description":"The input the error is about, such as `query.limit`."},"requiredScope":{"type":"string","description":"The scope the token is missing."},"requestId":{"type":"string","description":"Quote this id to support."},"docs":{"type":"string","description":"Link to the error's documentation."}},"required":["type","code","message","requestId","docs"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}},"responses":{"BadRequest":{"description":"The request is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthenticated":{"description":"The token is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"SubscriptionRequired":{"description":"The workspace's subscription needs attention.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The token is missing a required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such object in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"Temporarily unavailable; retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/payments/{id}":{"get":{"operationId":"payments.get","tags":["Payments"],"summary":"Get a payment","description":"One payment: its invoice, amount, how it was paid, and `refundedAmount`, the succeeded-refund total at the time of the request.\n\nReturns [the payment object](https://docs.shortcutco.com/developers/reference/objects/payment).","parameters":[{"name":"id","in":"path","required":true,"description":"The object's id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Payment"},"meta":{"type":"object","properties":{},"additionalProperties":true,"description":"Facts about this request beside the object, such as `alreadyReminded` on a repeated reminder. Present only when there is something to report."}},"required":["data"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/SubscriptionRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}}}}
```

## Undo an offline payment

> Undoes a manual (offline) payment with the same rules as Undo payment in the app: the payment is removed and its invoice becomes unpaid again, or overdue when past due. Only the single manual payment on a paid invoice can be undone; online payments, payments with refunds on project invoices, and recorded external payments are refused. The reason is recorded on the customer's notes. Because the payment is removed, it no longer appears in GET /v1/payments. Automations rules that start on an invoice change run only if the token has \`automations:trigger\`. Needs \`payments:write\` and \`invoices:read\`.\
> \
> Returns \[the payment reversal object]\(<https://docs.shortcutco.com/developers/reference/objects/payment-reversal).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`dependency\_unavailable\`]\(<https://docs.shortcutco.com/developers/concepts/errors#dependency\\_unavailable>), \[\`rule\_violation\`]\(<https://docs.shortcutco.com/developers/concepts/errors#rule\\_violation>), \[\`state\_conflict\`]\(<https://docs.shortcutco.com/developers/concepts/errors#state\\_conflict>), \[\`token\_creator\_unavailable\`]\(<https://docs.shortcutco.com/developers/concepts/errors#token\\_creator\\_unavailable>). Every endpoint can also return the \[common errors]\(<https://docs.shortcutco.com/developers/concepts/errors>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Payments","description":"A payment is money received for an invoice, online through Shortcut or recorded offline. Offline payments can be reversed.\n\nFields: [The payment object](https://docs.shortcutco.com/developers/reference/objects/payment) · [The payment reversal object](https://docs.shortcutco.com/developers/reference/objects/payment-reversal)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["payments:write","invoices:read"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"scut_<env>_<id>_<secret>","description":"A workspace API token. Each operation lists the scopes it needs; `write` implies `read`, and `send`/`complete` are never implied."}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Any string up to 255 characters. Retrying with the same key returns the first response instead of repeating the write, for 24 hours.","schema":{"type":"string","maxLength":255}}},"headers":{"RateLimitLimit":{"schema":{"type":"integer"},"description":"Requests allowed in the tightest window."},"RateLimitRemaining":{"schema":{"type":"integer"},"description":"Requests left in that window."},"RateLimitReset":{"schema":{"type":"integer"},"description":"Seconds until that window resets."}},"schemas":{"PaymentReversal":{"type":"object","properties":{"object":{"type":"string","const":"payment_reversal","description":"Always `payment_reversal`."},"paymentId":{"type":"string","format":"uuid","description":"The payment that was removed."},"amount":{"type":"number","description":"The removed payment's amount, in US dollars."},"invoice":{"$ref":"#/components/schemas/Invoice","description":"The invoice after the reversal: unpaid again, or overdue when past due."}},"required":["object","paymentId","amount","invoice"],"additionalProperties":false,"description":"An undone offline payment."},"Invoice":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The invoice's id."},"object":{"type":"string","const":"invoice","description":"Always `invoice`."},"number":{"type":"integer","description":"The invoice number the customer sees."},"kind":{"type":"string","enum":["standard","prepay","project"],"description":"`standard` invoices bill completed visits or manual lines. `prepay` invoices bill a coverage period in advance (see `coverageStartDate`). `project` invoices bill a project (deposit, progress, or final)."},"status":{"type":"string","enum":["draft","unpaid","overdue","paid","void"],"description":"`draft` invoices have not been sent to the customer. `unpaid` invoices are sent and not yet due (or have no due date). `overdue` invoices are past `dueAt`. `paid` and `void` invoices are closed. These match the app's invoice list, except that the app shows a draft as Unpaid or Overdue."},"paymentActivity":{"anyOf":[{"type":"string","enum":["processing","verification"]},{"type":"null"}],"description":"`processing` while a bank payment is in flight, `verification` while the bank needs the customer to verify; otherwise null. The invoice stays `unpaid` or `overdue` until the payment settles."},"customerId":{"type":"string","format":"uuid","description":"The customer billed."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The property (service address) billed, when there is one."},"propertyAddress":{"type":["string","null"],"description":"The property's address as printed on the invoice when it was created."},"propertyLabel":{"type":["string","null"],"description":"The property's label as printed on the invoice when it was created."},"subtotal":{"type":"number","description":"Sum of the lines before tax and fees, in US dollars."},"salesTax":{"type":"number","description":"Sales tax charged, in US dollars."},"processingFee":{"type":"number","description":"The processing fee in `total`. With `processingFeeScope` `card_only` it is 0 until a credit card pays the invoice with the fee, then equals `cardProcessingFee`; it stays 0 when the invoice is paid without the fee (bank, debit, offline, or a card-fee payment review settled at the total), in US dollars."},"processingFeeScope":{"type":"string","enum":["all_payments","card_only"],"description":"Which payments carry the processing fee, fixed when the invoice was created: `all_payments` (in `total`) or `card_only` (only a credit-card payment adds `cardProcessingFee`)."},"cardProcessingFee":{"type":"number","description":"With `card_only`, the fee a credit-card payment adds on top of `total`; bank, debit, check and cash payments never pay it. 0 for `all_payments`, in US dollars."},"lateFees":{"type":"number","description":"Late fees applied and not removed, in US dollars."},"total":{"type":"number","description":"What the customer owes in all: `subtotal + salesTax + processingFee + lateFees`, in US dollars."},"dueDate":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}],"description":"The due date as the customer's invoice prints it, `YYYY-MM-DD`: the calendar date of `dueAt` in UTC (the app stores a due date chosen as a date at midnight UTC). Null when there is none."},"dueAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"The stored due instant. The invoice is `overdue` once this moment passes, as in the app, ISO 8601 in UTC, or null."},"coverageStartDate":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}],"description":"First day a prepay invoice covers, `YYYY-MM-DD`, or null."},"coverageEndDate":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}],"description":"Last day a prepay invoice covers, `YYYY-MM-DD`, or null."},"sentAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the invoice was first sent, ISO 8601 in UTC, or null."},"paidAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the invoice was paid in full, ISO 8601 in UTC, or null."},"createdAt":{"type":"string","format":"date-time","description":"When the invoice was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the invoice last changed, ISO 8601 in UTC."}},"required":["id","object","number","kind","status","paymentActivity","customerId","propertyId","propertyAddress","propertyLabel","subtotal","salesTax","processingFee","processingFeeScope","cardProcessingFee","lateFees","total","dueDate","dueAt","coverageStartDate","coverageEndDate","sentAt","paidAt","createdAt","updatedAt"],"additionalProperties":false,"description":"An invoice: a bill to a customer."},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","description":"Error family, such as `invalid_request` or `permission`."},"code":{"type":"string","description":"Specific error code; see the errors page."},"message":{"type":"string","description":"A human-readable explanation."},"param":{"type":"string","description":"The input the error is about, such as `query.limit`."},"requiredScope":{"type":"string","description":"The scope the token is missing."},"requestId":{"type":"string","description":"Quote this id to support."},"docs":{"type":"string","description":"Link to the error's documentation."}},"required":["type","code","message","requestId","docs"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}},"responses":{"BadRequest":{"description":"The request is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthenticated":{"description":"The token is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"SubscriptionRequired":{"description":"The workspace's subscription needs attention.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The token is missing a required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such object in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"Conflict with the current state or an in-flight request with the same idempotency key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unprocessable":{"description":"The request cannot be applied, or its idempotency key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"Temporarily unavailable; retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/payments/{id}/reverse":{"post":{"operationId":"payments.reverse","tags":["Payments"],"summary":"Undo an offline payment","description":"Undoes a manual (offline) payment with the same rules as Undo payment in the app: the payment is removed and its invoice becomes unpaid again, or overdue when past due. Only the single manual payment on a paid invoice can be undone; online payments, payments with refunds on project invoices, and recorded external payments are refused. The reason is recorded on the customer's notes. Because the payment is removed, it no longer appears in GET /v1/payments. Automations rules that start on an invoice change run only if the token has `automations:trigger`. Needs `payments:write` and `invoices:read`.\n\nReturns [the payment reversal object](https://docs.shortcutco.com/developers/reference/objects/payment-reversal).\n\n**Errors specific to this endpoint:** [`dependency_unavailable`](https://docs.shortcutco.com/developers/concepts/errors#dependency_unavailable), [`rule_violation`](https://docs.shortcutco.com/developers/concepts/errors#rule_violation), [`state_conflict`](https://docs.shortcutco.com/developers/concepts/errors#state_conflict), [`token_creator_unavailable`](https://docs.shortcutco.com/developers/concepts/errors#token_creator_unavailable). Every endpoint can also return the [common errors](https://docs.shortcutco.com/developers/concepts/errors).","parameters":[{"name":"id","in":"path","required":true,"description":"The object's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500,"description":"Why the payment is being undone. It is recorded on the customer's notes, as in the app."}},"required":["reason"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PaymentReversal"},"meta":{"type":"object","properties":{},"additionalProperties":true,"description":"Facts about this request beside the object, such as `alreadyReminded` on a repeated reminder. Present only when there is something to report."}},"required":["data"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/SubscriptionRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}}}}
```
