# payments.record

Record evidenced money that already moved and allocate it to explicit claims, or leave an identified amount unapplied. Does not initiate a payment or recognize revenue or expense.

## What it does

Record evidenced cash, wallet, company-card or owner-funded movement against explicit claims, independently of contracts. Each allocation's amount is what it discharges in the claim's own currency, bounded by the claim's balance. A claim in another currency than the payment also takes cashAmount, the payment-currency cash applied to it: the claim leg posts in the claim's currency ledger and the cash in the payment's, each balanced on its own through equity account 3420 Currency exchange.

When that claim was booked at a frozen exchange rate, the difference between it at that rate and the cash in the functional currency is realized FX, posted in the same event to 7150 (loss) or 7250 (gain) against 3420 and attributed to the claim; cash in a third currency is valued at the payment date's rate from the shared rate store, or an evidenced exchangeRate you state.

A person's own card or account (ownerPartyId) is held in the company's currency: state a payment from it of a bill in another currency in the bill's currency without cashAmount, fully allocated, and it is recorded in the account's currency at each bill's booking rate, so the company owes the person that amount, realizes nothing, and the person bears their card's own conversion. A refund of such a bill to that account is stated the same way and reduces what the person is owed at the same rate.

A wallet payment may name a token by CAIP-19: exact smallest units post to that token's ledger, opened at verified precision on its first receipt. The wallet's display currency does not constrain its tokens. Other allocations share the payment's ledger; any residual is held as explicitly unapplied money in the payment currency. Use payments.allocate later without another cash posting. No expense or revenue is recognized. Unapplied card/owner advances retain a separate funding claim. Historical claims remain settleable.

Incoming card/owner refunds require refundsFundingClaim naming the original funding claim and one fully allocated refund or original unapplied receivable. They reduce only that debt; reimbursed excess creates a recoverableClaim on the owner or issuer. Recover it through a separate incoming bank payment.

## Before you send it

An authorized OAuth connection may call it, including a headless client. Effective membership, application grant and token permissions still apply. Describe `payments.record` through `GET /v1/catalog/commands/{name}` before acting.

This command does not accept `source_document_id` in its envelope. Any input evidence requirements remain as documented below.

## Inputs

Put these fields inside the envelope's `input` object. The outer envelope names the command, a stable `idempotency_key` and `effective_at`; [request and recovery rules](/docs/api/) explain those separately. Use exact minor-unit integer strings for monetary fields. Take existing IDs from prior reads or command results; choose a new identity only where the command asks for one.

Required means required within its containing object; an optional parent can be omitted.

| Field | Type | Required | Meaning and accepted values |
|---|---|---|---|
| `exchangeRate` | object | No | An evidenced exchange rate (1 base = numerator/denominator quote), e.g. from a bank statement. It overrides the shared rate store for this command; omit it to use the store.  |
| `exchangeRate.base` | string | Yes |  Pattern: `"^[A-Z]{3}$"`. |
| `exchangeRate.quote` | string | Yes |  Pattern: `"^[A-Z]{3}$"`. |
| `exchangeRate.date` | string | Yes |  Format: date. |
| `exchangeRate.numerator` | string | Yes |  Pattern: `"^[1-9][0-9]*$"`. |
| `exchangeRate.denominator` | string | Yes |  Pattern: `"^[1-9][0-9]*$"`. |
| `exchangeRate.evidence` | array | Yes |  Items: object. Minimum items: `1`. |
| `exchangeRate.evidence[].kind` | string | Yes |  Choose `"tap_message"`, `"x402_receipt"`, `"chain_tx"`, `"signed_doc"`, `"stripe_object"`, `"other"`. |
| `exchangeRate.evidence[].ref` | string | Yes |  Minimum length: `1`. |
| `exchangeRate.evidence[].signer` | string | No |   |
| `refundsFundingClaim` | object | No |   |
| `refundsFundingClaim.claimId` | string | Yes |  Minimum length: `1`. |
| `refundsFundingClaim.component` | object | Yes |   |
| `refundsFundingClaim.component.originLedgerId` | string | Yes |  Minimum length: `1`. |
| `refundsFundingClaim.component.accountCode` | integer | Yes |   |
| `financialAccountId` | string | Yes |  Minimum length: `1`. |
| `direction` | string | Yes |  Choose `"in"`, `"out"`. |
| `amount` | string | Yes |  Pattern: `"^[1-9][0-9]*$"`. |
| `currency` | string | Yes | ISO currency, or a CAIP-19 token for a company-owned wallet; amount is in that unit's exact minor units. Minimum length: `1`. |
| `partyId` | string | Yes |  Minimum length: `1`. |
| `effectiveAt` | string | Yes |  Format: date-time. |
| `sourceFactId` | string | Yes |  Minimum length: `1`. |
| `evidence` | array | Yes |  Items: object. Minimum items: `1`. |
| `evidence[].kind` | string | Yes |  Choose `"tap_message"`, `"x402_receipt"`, `"chain_tx"`, `"signed_doc"`, `"stripe_object"`, `"other"`. |
| `evidence[].ref` | string | Yes |  Minimum length: `1`. |
| `evidence[].signer` | string | No |  Minimum length: `1`. |
| `allocations` | array | Yes |  Items: object. Minimum items: `0`. Maximum items: `100`. |
| `allocations[].claimId` | string | Yes |  Minimum length: `1`. |
| `allocations[].amount` | string | Yes |  Pattern: `"^[1-9][0-9]*$"`. |
| `allocations[].cashAmount` | string | No |  Pattern: `"^[1-9][0-9]*$"`. |
| `allocations[].component` | object | Yes |   |
| `allocations[].component.originLedgerId` | string | Yes |  Minimum length: `1`. |
| `allocations[].component.accountCode` | integer | Yes |   |

## After acceptance

When the command emits events, its documented effects and receipt are recorded in the command transaction. The response returns `commandId`, `replayed`, the command-specific `result` below and emitted `events` with their IDs and CIDs. A command is not automatically a cash movement or revenue recognition: use the behavior above to determine what this command records.

Inspect `result` and the affected records or reports before continuing. Save returned identifiers for later calls. Fetch `GET /v1/commands/{id}` with `commandId` to recover the accepted receipt; retry the same intent with the same idempotency key if the response was lost. Some commands can succeed with `events: []` and return a transient result and `commandId` without persisting a receipt. A lookup of that ID can return null; retain the returned result and verify the affected record. Retrying can re-evaluate the current state rather than replay a stored result. A domain `no_change` is a separate success outcome with no persisted receipt.

### Result fields

Required means required within its containing object; an optional parent can be omitted.

| Field | Type | Required | Meaning and accepted values |
|---|---|---|---|
| `paymentId` | string | Yes |  Minimum length: `1`. |
| `currency` | string | No | The currency the payment was recorded in: a personal account's own, when a payment stated in a foreign bill's currency was converted at its booking rate. Minimum length: `1`. |
| `amount` | string | No | The amount recorded, in `currency`.  |
| `residual` | string | Yes |   |
| `recoverableClaim` | object | No |   |
| `recoverableClaim.claimId` | string | Yes |  Minimum length: `1`. |
| `recoverableClaim.component` | object | Yes |   |
| `recoverableClaim.component.originLedgerId` | string | Yes |  Minimum length: `1`. |
| `recoverableClaim.component.accountCode` | integer | Yes |   |
| `unappliedClaim` | object | No |   |
| `unappliedClaim.claimId` | string | Yes |  Minimum length: `1`. |
| `unappliedClaim.component` | object | Yes |   |
| `unappliedClaim.component.originLedgerId` | string | Yes |  Minimum length: `1`. |
| `unappliedClaim.component.accountCode` | integer | Yes |   |
| `fundingClaims` | array | Yes |  Items: object. |
| `fundingClaims[].claimId` | string | Yes |  Minimum length: `1`. |
| `fundingClaims[].component` | object | Yes |   |
| `fundingClaims[].component.originLedgerId` | string | Yes |  Minimum length: `1`. |
| `fundingClaims[].component.accountCode` | integer | Yes |   |


[All commands](/docs/command-reference/) · [Operation and errors](/docs/api-reference/operations/commands-execute/) · [Reusable schemas](/docs/api-reference/components/)

Keep credentials out of prompts; rehearse writes only in a disposable sandbox.

## Exact request schema


```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "name": {
      "const": "payments.record"
    },
    "input": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "financialAccountId",
        "direction",
        "amount",
        "currency",
        "partyId",
        "effectiveAt",
        "sourceFactId",
        "evidence",
        "allocations"
      ],
      "properties": {
        "exchangeRate": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "base",
            "quote",
            "date",
            "numerator",
            "denominator",
            "evidence"
          ],
          "description": "An evidenced exchange rate (1 base = numerator/denominator quote), e.g. from a bank statement. It overrides the shared rate store for this command; omit it to use the store.",
          "properties": {
            "base": {
              "type": "string",
              "pattern": "^[A-Z]{3}$"
            },
            "quote": {
              "type": "string",
              "pattern": "^[A-Z]{3}$"
            },
            "date": {
              "type": "string",
              "format": "date"
            },
            "numerator": {
              "type": "string",
              "pattern": "^[1-9][0-9]*$"
            },
            "denominator": {
              "type": "string",
              "pattern": "^[1-9][0-9]*$"
            },
            "evidence": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "kind",
                  "ref"
                ],
                "properties": {
                  "kind": {
                    "enum": [
                      "tap_message",
                      "x402_receipt",
                      "chain_tx",
                      "signed_doc",
                      "stripe_object",
                      "other"
                    ]
                  },
                  "ref": {
                    "type": "string",
                    "minLength": 1
                  },
                  "signer": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "refundsFundingClaim": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "claimId": {
              "type": "string",
              "minLength": 1
            },
            "component": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "originLedgerId",
                "accountCode"
              ],
              "properties": {
                "originLedgerId": {
                  "type": "string",
                  "minLength": 1
                },
                "accountCode": {
                  "type": "integer"
                }
              }
            }
          },
          "required": [
            "claimId",
            "component"
          ]
        },
        "financialAccountId": {
          "type": "string",
          "minLength": 1
        },
        "direction": {
          "enum": [
            "in",
            "out"
          ]
        },
        "amount": {
          "type": "string",
          "pattern": "^[1-9][0-9]*$"
        },
        "currency": {
          "type": "string",
          "minLength": 1,
          "description": "ISO currency, or a CAIP-19 token for a company-owned wallet; amount is in that unit's exact minor units."
        },
        "partyId": {
          "type": "string",
          "minLength": 1
        },
        "effectiveAt": {
          "type": "string",
          "format": "date-time"
        },
        "sourceFactId": {
          "type": "string",
          "minLength": 1
        },
        "evidence": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "properties": {
              "kind": {
                "enum": [
                  "tap_message",
                  "x402_receipt",
                  "chain_tx",
                  "signed_doc",
                  "stripe_object",
                  "other"
                ]
              },
              "ref": {
                "type": "string",
                "minLength": 1
              },
              "signer": {
                "type": "string",
                "minLength": 1
              }
            },
            "required": [
              "kind",
              "ref"
            ],
            "additionalProperties": false
          }
        },
        "allocations": {
          "type": "array",
          "minItems": 0,
          "maxItems": 100,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "claimId",
              "component",
              "amount"
            ],
            "properties": {
              "claimId": {
                "type": "string",
                "minLength": 1
              },
              "amount": {
                "type": "string",
                "pattern": "^[1-9][0-9]*$"
              },
              "cashAmount": {
                "type": "string",
                "pattern": "^[1-9][0-9]*$"
              },
              "component": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "originLedgerId",
                  "accountCode"
                ],
                "properties": {
                  "originLedgerId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "accountCode": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        }
      }
    },
    "idempotency_key": {
      "type": "string",
      "minLength": 1,
      "maxLength": 256
    },
    "effective_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "name",
    "input",
    "idempotency_key",
    "effective_at"
  ],
  "additionalProperties": false
}
```

## Accepted command receipt


```json
{
  "type": "object",
  "required": [
    "commandId",
    "replayed",
    "result",
    "events"
  ],
  "properties": {
    "commandId": {
      "type": "string"
    },
    "replayed": {
      "type": "boolean"
    },
    "imported": {
      "const": true,
      "description": "The command's events are history from before the business joined Economico, recorded as an import: free of monthly events."
    },
    "result": {
      "type": "object",
      "properties": {
        "paymentId": {
          "type": "string",
          "minLength": 1
        },
        "currency": {
          "type": "string",
          "minLength": 1,
          "description": "The currency the payment was recorded in: a personal account's own, when a payment stated in a foreign bill's currency was converted at its booking rate."
        },
        "amount": {
          "type": "string",
          "description": "The amount recorded, in `currency`."
        },
        "residual": {
          "type": "string"
        },
        "recoverableClaim": {
          "type": "object",
          "properties": {
            "claimId": {
              "type": "string",
              "minLength": 1
            },
            "component": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "originLedgerId",
                "accountCode"
              ],
              "properties": {
                "originLedgerId": {
                  "type": "string",
                  "minLength": 1
                },
                "accountCode": {
                  "type": "integer"
                }
              }
            }
          },
          "required": [
            "claimId",
            "component"
          ]
        },
        "unappliedClaim": {
          "type": "object",
          "properties": {
            "claimId": {
              "type": "string",
              "minLength": 1
            },
            "component": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "originLedgerId",
                "accountCode"
              ],
              "properties": {
                "originLedgerId": {
                  "type": "string",
                  "minLength": 1
                },
                "accountCode": {
                  "type": "integer"
                }
              }
            }
          },
          "required": [
            "claimId",
            "component"
          ]
        },
        "fundingClaims": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "claimId": {
                "type": "string",
                "minLength": 1
              },
              "component": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "originLedgerId",
                  "accountCode"
                ],
                "properties": {
                  "originLedgerId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "accountCode": {
                    "type": "integer"
                  }
                }
              }
            },
            "required": [
              "claimId",
              "component"
            ]
          }
        }
      },
      "required": [
        "paymentId",
        "residual",
        "fundingClaims"
      ]
    },
    "events": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "cid": {
            "type": "string"
          }
        }
      }
    }
  }
}
```


