---
title: "Insert a payment for an invoice"
method: POST
path: "/public/v1/invoices/{id}/payments"
tags: ["Invoice"]
---

# Insert a payment for an invoice

`POST /public/v1/invoices/{id}/payments`

## Request

- Base URL: `https://app.distru.com`
- URL: `https://app.distru.com/public/v1/invoices/{id}/payments`
- Auth: HTTP bearer

Record a payment against an invoice. On success the invoice's `paid_amount`, `remaining_amount`, and payment `status` are recomputed to reflect the new payment.

The recorded amount is capped at the invoice's outstanding balance (its `remaining_amount`): only the portion up to that balance is applied to the invoice, and any excess becomes a customer credit for the account. In the response, the payment's `amount` holds the applied (capped) portion and the generated credit appears in `overpayment_credits` with the excess as its `amount`. On the invoice, `paid_amount` grows by the applied portion only, so it ends equal to `total`, `remaining_amount` drops to `0`, and `status` becomes FULLY_PAID — an overpayment never produces OVER_PAID. For example, sending an `amount` of 150 against an invoice with a `remaining_amount` of "100.00" returns a payment with `amount` "100" and one entry in `overpayment_credits` with `amount` "50"; the invoice then reads `paid_amount` equal to `total`, `remaining_amount` "0.00", and `status` FULLY_PAID. A payment cannot be filed against an invoice that is already fully paid, or against a voided invoice — both are rejected. Returns 404 when the invoice does not exist in the caller's company, and 403 when the API key's user cannot see it under their team restrictions.

If the company is connected to QuickBooks Online there are two extra behaviors. First, Distru synchronously pulls the latest payment and credit data from QuickBooks Online before recording, which can briefly fail with a "try again in a few seconds" error while that refresh runs — retry the request in that case. Second, the payment (or its invoice) is only queued for sync to QuickBooks Online once its dependencies are already synced there; otherwise the sync is deferred. A 200 is therefore not confirmation the payment reached QuickBooks Online — the response's `quickbooks_sync_enqueued` flag tells you whether a sync was queued, and you should poll QuickBooks Online to observe the final result. The payment may also be pushed to LeafLink when that integration is configured for the customer.

Required permission: `invoices_permissions_receive_payment`. The authenticated user must also be allowed to view invoices under their team restrictions.

## Path parameters

- `id` string, required

## Request body

- object
  - `payment_method_id` string, required: The `id` of the payment method to record this payment under. Required. Retrieve valid IDs from GET /public/v1/payment-methods.
  - `amount` number, required: The payment amount. Required. Rounded to 2 decimal places. Capped at the invoice's `remaining_amount`: only the portion up to the outstanding balance is applied — that portion is returned as the payment's `amount` and added to the invoice's `paid_amount` — while any excess becomes a customer credit, returned in the payment's `overpayment_credits`. E.g. sending 150 when "100.00" remains records a payment of "100" and a credit of "50".
  - `payment_datetime` string, required: The datetime the payment was made, as an ISO8601 datetime (e.g. `2026-08-20T00:00:00Z`). Required.
  - `description` string, required: A free-text description of the payment. Required.
  - `quickbooks_deposit_account_id` string: QuickBooks Online deposit account ID. Optional. Mutually exclusive with `quickbooks_deposit_account_name` — sending both is rejected. When your company is connected to QuickBooks Online and you send neither, the payment is deposited to the company's Sales Deposit Account (Settings → QuickBooks); when that account is missing, not active or not of an allowed type, the request is rejected with a `base` error naming it — send an account then. With no Sales Deposit Account set, sending neither is rejected on both deposit account fields. When your company is not connected to QuickBooks Online, sending this is rejected. The account must be active and of type "Bank" or "Other Current Asset".
  - `quickbooks_deposit_account_name` string: QuickBooks Online deposit account name. Optional. Mutually exclusive with `quickbooks_deposit_account_id` — sending both is rejected. Omit both to use the company's Sales Deposit Account (see `quickbooks_deposit_account_id`). A name containing `:` is a sub-account's full name (`Parent:Child`) and matches that account exactly; it must itself be active and of type "Bank" or "Other Current Asset". Any other name matches among active "Bank" and "Other Current Asset" accounts: a top-level account with that name (its full name) wins; otherwise the one sub-account with that short name. A short name shared by several such sub-accounts is rejected with a message listing their full names — send the full name instead. When the top-level account with that name is inactive or of another type and a sub-account shares its name, the request is rejected with a message naming that sub-account's full name, rather than depositing to it. When your company is not connected to QuickBooks Online, sending this is rejected.

## Response `200`

A single payment

- PaymentResponse: A single Payment
  - `data` Payment: A record of money exchanged — received from a customer against an invoice, or paid to a vendor against a purchase order.
    - `amount` string, required: The payment amount as a decimal string with trailing zeros trimmed (e.g. `"150"` or `"99.5"`), in the currency of the related invoice or purchase. For an INVOICE payment this is the amount applied to the invoice: it includes any portion covered by applied credits (`credit_uses`) but excludes any overpaid portion that became a customer credit (`overpayment_credits`) — the invoice's `paid_amount` is the sum of `amount` across its active payments. Normally at least `0.01`; the one exception is a payment synced from QuickBooks Online to represent a void, which appears as `"0"`. Always present.
    - `company` CompanyCompact: A lightweight reference to a company — just its identity — embedded on other entities (orders, invoices, products, etc.) to point at the full company without inlining it. The company is a trading partner (a customer or vendor) in your Distru network. Use the id to fetch its full details from the companies endpoint.
      - `id` string, required: ID for this company
      - `name` string, required: Human readable name for this company
      - `tasks` TaskCompact[], required: The tasks linked to this company that the authenticated user can see: none without `tasks_permissions_view`, and only those their team restrictions allow. An empty array when there are none.
        - `due_datetime` string, required: When the task is due, as a UTC ISO8601 datetime.
        - `id` string, required: ID of the task.
        - `name` string, required: The task's name.
        - `status` 'ACTIVE' | 'COMPLETED', required: The task's status.
      - `updated_datetime` string, required: ISO 8601 datetime this company was last updated at
    - `credit_uses` PaymentCreditUse[], nullable: Credits applied toward this invoice payment (an empty array when none were applied). Null for PURCHASE payments.
      - `amount` string, required: The amount of credit applied toward the payment, as a decimal string (e.g. `"25.00"`). Always present.
      - `credit` PaymentCredit: A compact representation of a credit related to a payment
        - `amount` string, required: The credit's current remaining amount as a decimal string (e.g. `"50.00"`); reflects credit already spent, not the original issued amount. Always present.
        - `credit_number` string, required: The credit number as shown in the Distru UI. Always present.
        - `id` string, required: ID for this credit. Always present.
        - `source` 'INVOICE_PAYMENT' | 'QB_CREDIT_MEMO' | 'QB_PAYMENT' | 'RETURN' | 'USER', required: How the credit originated. INVOICE_PAYMENT (from an invoice overpayment), RETURN (from a return), USER (manually created), or QB_CREDIT_MEMO / QB_PAYMENT (synced from QuickBooks Online). Always present.
      - `id` string, required: ID for this credit use. Always present.
    - `description` string, nullable: Free-text note attached to the payment, or null if none was entered.
    - `fully_paid_with_credits` boolean, required: True when the payment was covered entirely by credits; in that case `payment_method` is null. Defaults to false. Always present.
    - `id` string, required: The payment's ID. Always present.
    - `inserted_datetime` string, required: ISO8601 datetime the payment record was created in Distru. Distinct from `payment_datetime`. Always present.
    - `invoice` CompactInvoice: A compact view of an invoice as nested inside another entity (an order or a payment) in Distru. Use its id to fetch the full invoice from the invoices endpoint.
      - `id` string, required: ID for this invoice
      - `invoice_number` string, required: The invoice number as shown in the Distru UI (e.g. "INV-0001"). Unique per company.
      - `status` string, required: The payment status of this invoice (SCREAMING_CASE), reflecting how much of its total has been paid — distinct from the parent order's fulfillment `status`.• NOT_PAID: no payments applied.• PARTIALLY_PAID: paid in part but less than the total.• FULLY_PAID: paid in full.• OVER_PAID: payments exceed the total.
      - `total` string, required: The invoice total (line items plus charges/taxes minus discounts), as a decimal string (e.g. "150.50").
    - `overpayment_credits` PaymentCredit[], nullable: Credits generated from overpaying this invoice payment (an empty array when there was no overpayment). Leaves out credits the authenticated user cannot view under their team restrictions. Null for PURCHASE payments.
      - `amount` string, required: The credit's current remaining amount as a decimal string (e.g. `"50.00"`); reflects credit already spent, not the original issued amount. Always present.
      - `credit_number` string, required: The credit number as shown in the Distru UI. Always present.
      - `id` string, required: ID for this credit. Always present.
      - `source` 'INVOICE_PAYMENT' | 'QB_CREDIT_MEMO' | 'QB_PAYMENT' | 'RETURN' | 'USER', required: How the credit originated. INVOICE_PAYMENT (from an invoice overpayment), RETURN (from a return), USER (manually created), or QB_CREDIT_MEMO / QB_PAYMENT (synced from QuickBooks Online). Always present.
    - `payment_datetime` string, required: The full ISO8601 datetime the payment was recorded as made (e.g. `"2022-07-10T00:00:00Z"`). This is the user-entered payment datetime, distinct from `inserted_datetime` (when the record was created in Distru). Always present.
    - `payment_method` PaymentMethod: A way payments are made or received (e.g. Cash, Check, Credit Card, Bank Transfer).
      - `active` boolean, required: True when this payment method is active and can be selected on new payments. Defaults to false.
      - `deleted_at` string: ISO 8601 datetime this payment method was soft-deleted, or null when it has not been deleted
      - `id` string, required: ID for this payment method
      - `inserted_datetime` string, required: The datetime this payment method was created at
      - `name` string, required: Name of the payment method (e.g. "Cash")
      - `qb_payment_method_id` string: The ID of the matching payment method in QuickBooks Online, or null when this payment method is not mapped to one
      - `type` 'CASH' | 'CHECK' | 'CREDIT_CARD' | 'BANK_REMITTANCE' | 'BANK_TRANSFER', required: The payment method type (SCREAMING_CASE). One of CASH, CHECK, CREDIT_CARD, BANK_REMITTANCE, or BANK_TRANSFER.
      - `updated_datetime` string, required: The datetime this payment method was last updated at
    - `payment_number` string, required: The payment number as shown in the Distru UI. Unique per company. Always present.
    - `payment_type` string, required: What this payment is tied to: INVOICE (money received from a customer against an invoice) or PURCHASE (money paid to a vendor against a purchase). Determines which of `invoice`/`purchase` is populated and whether `credit_uses`/`overpayment_credits` are present. Always present.
    - `purchase` PaymentPurchase: A compact representation of the purchase a payment belongs to
      - `id` string, required: The purchase's ID. Always present.
      - `purchase_number` string, required: The purchase number as shown in the Distru UI. Always present.
      - `status` string, nullable: The purchase's status, or null if the purchase has no status set.
      - `total` string, required: The purchase's total as a decimal string (e.g. `"1200.00"`). Defaults to `"0"`. Always present.
    - `quickbooks_deposit_account_id` string, nullable: ID of the QuickBooks Online deposit account this payment posts to, or null when the payment is not linked to a deposit account.
    - `quickbooks_deposit_account_name` string, nullable: Name of the QuickBooks Online deposit account in `quickbooks_deposit_account_id`. For an INVOICE payment it is the account's full name (`Parent:Child` for a sub-account), which [POST /public/v1/invoices/{id}/payments](#insert-a-payment-for-an-invoice) accepts back as `quickbooks_deposit_account_name`; for a PURCHASE payment it is the account's own name. Only returned on the single-payment (show) response, and null there when no deposit account is linked; absent from list responses.
    - `quickbooks_sync_enqueued` boolean: Whether a QuickBooks Online sync was queued for this payment. Only present on the payment creation response; absent from list and show responses.
    - `status` string, required: The payment's status. POSTED for a live payment; VOIDED for one that was voided (retained for history rather than deleted). Always present.
    - `updated_datetime` string, required: ISO8601 datetime the payment record was last modified in Distru. Equals `inserted_datetime` until the payment is edited or voided. Always present.

## Other responses

- `400`: Invalid parameters
- `401`: Missing or invalid API token
- `403`: The API token lacks the required permission, or team restrictions hide the record
- `404`: Not Found

---

[API](https://skmtc.dev/distru/apis/distru-api.md) - [All operations](https://skmtc.dev/distru/apis/distru-api/llms.txt) - [OpenAPI document](https://skmtc.dev/distru/apis/distru-api/revisions/9d851a88e82f?raw)
