{
  "components": {
    "schemas": {
      "AcceptPartnerNettingAgreementDto": {
        "description": "Your account under an agreement you were offered.",
        "properties": {
          "accountId": {
            "description": "Your account under the agreement. ACTIVE, fiat, in the agreement currency.",
            "example": "a1c93e6f-52b7-4d08-8e51-6b2f0c9d3a47",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "accountId"
        ],
        "type": "object"
      },
      "AccountBalanceDto": {
        "description": "An account's money, as decimal strings at the currency's own scale. available is what you can move today.",
        "properties": {
          "available": {
            "description": "What can be moved today: total minus reserved.",
            "example": "1000.00",
            "type": "string"
          },
          "reserved": {
            "description": "Money held against something in flight. On a crypto account, what a conversion or an outgoing payment from it holds back until it settles. Always '0' on a fiat account today — there is no fiat reservation lifecycle on this surface yet.",
            "example": "0.00",
            "type": "string"
          },
          "total": {
            "description": "The whole balance of the account.",
            "example": "1000.00",
            "type": "string"
          }
        },
        "required": [
          "available",
          "reserved",
          "total"
        ],
        "type": "object"
      },
      "AccountIbanDto": {
        "description": "The payment coordinate money can be sent to, and the name it is held under.",
        "properties": {
          "active": {
            "description": "Whether this coordinate accepts funds. False while the sub-client that owns it is anything other than VERIFIED; true once it is. Read it rather than inferring activation from the coordinate's existence.",
            "example": false,
            "type": "boolean"
          },
          "bic": {
            "description": "The BIC that goes with it.",
            "example": "TCBKBHBMXXX",
            "type": "string"
          },
          "holderName": {
            "description": "The payee name on the coordinate — the owner's verified legal name, never the account label. It is the name presented for payee-name checks where the receiving scheme runs them.",
            "example": "Fatima Al-Khalifa",
            "type": "string"
          },
          "iban": {
            "description": "The IBAN money can be sent to.",
            "example": "BH29TCBK00001234567890",
            "type": "string"
          }
        },
        "required": [
          "iban",
          "bic",
          "holderName",
          "active"
        ],
        "type": "object"
      },
      "AccountLocalRailDto": {
        "description": "Local details for one account's currency on its domestic payment scheme: the bank that holds the account, the numbers a payer enters, and the reference to quote.",
        "properties": {
          "accountNumber": {
            "description": "The account number, on a scheme that uses one (USD, GBP). Null otherwise.",
            "nullable": true,
            "type": "string"
          },
          "active": {
            "description": "Whether these details accept funds, on the same rule as iban.active: false while the sub-client that owns the account is anything other than VERIFIED.",
            "example": false,
            "type": "boolean"
          },
          "bankAddress": {
            "description": "That bank's address, or null if none is recorded.",
            "example": "Wiesenstrasse 17, 8952 Schlieren, Switzerland",
            "nullable": true,
            "type": "string"
          },
          "bankName": {
            "description": "The bank that holds the account.",
            "example": "InCore Bank AG",
            "type": "string"
          },
          "beneficiaryName": {
            "description": "The account name a payer enters.",
            "example": "Fatima Al-Khalifa",
            "type": "string"
          },
          "bic": {
            "description": "That bank's BIC.",
            "example": "INCOCHZZ",
            "type": "string"
          },
          "currency": {
            "description": "The currency the details receive.",
            "example": "EUR",
            "type": "string"
          },
          "iban": {
            "description": "The IBAN, on a scheme that uses one (EUR, CHF). Null otherwise.",
            "example": "CH0508799123456789012",
            "nullable": true,
            "type": "string"
          },
          "paymentReference": {
            "description": "The reference a payer quotes with a payment to these details.",
            "example": "TCB-7K2M9QXA",
            "nullable": true,
            "type": "string"
          },
          "rail": {
            "description": "The domestic payment scheme these details are reached on.",
            "example": "SEPA / SEPA Instant",
            "type": "string"
          },
          "routingNumber": {
            "description": "The ABA routing number (USD). Null otherwise.",
            "nullable": true,
            "type": "string"
          },
          "sortCode": {
            "description": "The sort code (GBP). Null otherwise.",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "rail",
          "currency",
          "beneficiaryName",
          "bankName",
          "bic",
          "bankAddress",
          "iban",
          "accountNumber",
          "routingNumber",
          "sortCode",
          "paymentReference",
          "active"
        ],
        "type": "object"
      },
      "AddPartnerBeneficiaryNetworkDto": {
        "description": "The network to add to a wallet destination.",
        "properties": {
          "chain": {
            "description": "The network to add. It must be one of the destination's reachableChains.",
            "enum": [
              "ETHEREUM",
              "BITCOIN",
              "SOLANA",
              "POLYGON",
              "AVALANCHE",
              "ARBITRUM",
              "OPTIMISM",
              "BASE"
            ],
            "example": "BASE",
            "type": "string"
          }
        },
        "required": [
          "chain"
        ],
        "type": "object"
      },
      "AddPartnerSettlementConnectionDto": {
        "description": "A member to allow onto your connections list, named by their exact handle. Nothing is asked of them.",
        "properties": {
          "handle": {
            "description": "The sender's exact handle. Added to your allowlist immediately; nothing is asked of them.",
            "example": "acme-treasury",
            "type": "string"
          },
          "note": {
            "description": "A note for your own operators, at most 255 characters. Never shown to the member.",
            "example": "Prime broker — onboarded 2026-09",
            "type": "string"
          }
        },
        "required": [
          "handle"
        ],
        "type": "object"
      },
      "AddSubClientCurrencyDto": {
        "description": "The currency to open a MAIN account and IBAN in.",
        "properties": {
          "currency": {
            "description": "ISO 4217. Its MAIN account and IBAN are created for the sub-client, the same way POST /sub-clients does at creation.",
            "example": "USD",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Alternative to the Idempotency-Key header. One of the two is required; sending both is allowed only if they match.",
            "example": "acme-2026-09-02-0001",
            "type": "string"
          }
        },
        "required": [
          "currency"
        ],
        "type": "object"
      },
      "ApprovePartnerSettlementRequestDto": {
        "description": "The account you are paying a request from. The money is yours, so the choice is too.",
        "properties": {
          "fromAccountId": {
            "description": "The account YOU pay from. The money is yours, so the choice of source account is too.",
            "example": "a1c93e6f-52b7-4d08-8e51-6b2f0c9d3a47",
            "type": "string"
          }
        },
        "required": [
          "fromAccountId"
        ],
        "type": "object"
      },
      "AttestationDto": {
        "description": "Your statement that you performed customer due diligence and screening on this sub-client under your agreed programme.",
        "properties": {
          "cddPerformedAt": {
            "description": "When you performed the due diligence (ISO 8601).",
            "example": "2026-08-28T09:00:00.000Z",
            "format": "date-time",
            "type": "string"
          },
          "cddStandard": {
            "description": "The depth of due diligence you performed.",
            "enum": [
              "standard",
              "enhanced"
            ],
            "example": "standard",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Alternative to the Idempotency-Key header. One of the two is required; sending both is allowed only if they match.",
            "example": "acme-2026-09-02-0001",
            "type": "string"
          },
          "pepStatus": {
            "description": "The politically-exposed-person result your screening returned for this customer.",
            "enum": [
              "none",
              "pep",
              "pep_related"
            ],
            "example": "none",
            "type": "string"
          },
          "riskRating": {
            "description": "The customer risk rating your programme assigned.",
            "enum": [
              "low",
              "medium",
              "high"
            ],
            "example": "low",
            "type": "string"
          },
          "screeningResult": {
            "description": "What your screening returned. Send match_reviewed_cleared when a hit was raised and you cleared it.",
            "enum": [
              "clear",
              "match_reviewed_cleared",
              "match"
            ],
            "example": "clear",
            "type": "string"
          },
          "text": {
            "description": "The attestation wording agreed with TCB for your programme, sent verbatim.",
            "example": "We have performed customer due diligence and screening on this customer under our agreed reliance programme.",
            "type": "string"
          },
          "verificationMethod": {
            "description": "How you verified this customer's identity under your programme, e.g. \"documentary\", \"electronic\" or \"biometric\".",
            "example": "documentary",
            "type": "string"
          },
          "verificationResult": {
            "description": "The outcome of that verification. A sub-client is activated only on verified.",
            "enum": [
              "verified",
              "not_verified"
            ],
            "example": "verified",
            "type": "string"
          },
          "verifierRef": {
            "description": "Your own case, file or vendor reference for it. TCB stores it, does not resolve it, and uses it to ask you for the file.",
            "example": "acme-case-88214",
            "type": "string"
          },
          "version": {
            "description": "The version string of the agreed wording.",
            "example": "reliance-2026-09",
            "type": "string"
          }
        },
        "required": [
          "text",
          "version",
          "cddPerformedAt",
          "cddStandard",
          "screeningResult",
          "verificationMethod",
          "verificationResult",
          "verifierRef",
          "pepStatus",
          "riskRating"
        ],
        "type": "object"
      },
      "AttestationListResponse": {
        "description": "A sub-client's attestations, newest first.",
        "properties": {
          "items": {
            "description": "Every attestation on the sub-client, newest first.",
            "items": {
              "$ref": "#/components/schemas/PartnerAttestationResponse"
            },
            "type": "array"
          }
        },
        "required": [
          "items"
        ],
        "type": "object"
      },
      "CapabilitiesFlagsDto": {
        "description": "What the owner of an account may do with it right now. Derived from verification state, so it changes the moment that does.",
        "properties": {
          "holdCrypto": {
            "description": "Whether this owner may open crypto networks and receive on them; an address already opened keeps receiving. A sub-client follows its client: true when the client holds crypto (KYC approved and an active crypto account), unless Three Comma Bank has set it for this sub-client. Like every flag, false until the sub-client is VERIFIED.",
            "example": true,
            "type": "boolean"
          },
          "holdSavings": {
            "description": "Reserved. Always false in v1: vault routes act for you, never for a sub-client.",
            "example": false,
            "type": "boolean"
          },
          "receive": {
            "description": "Whether money may be credited to this owner.",
            "example": true,
            "type": "boolean"
          },
          "sendCrypto": {
            "description": "Whether this owner may send crypto out. Defaults the same way as holdCrypto: it follows the client unless Three Comma Bank has set it for this sub-client.",
            "example": true,
            "type": "boolean"
          },
          "sendExternal": {
            "description": "Whether this owner may send money out of TCB.",
            "example": false,
            "type": "boolean"
          },
          "sendInternal": {
            "description": "Whether this owner may be debited by a within-tree transfer.",
            "example": true,
            "type": "boolean"
          }
        },
        "required": [
          "receive",
          "sendInternal",
          "sendExternal",
          "holdSavings",
          "holdCrypto",
          "sendCrypto"
        ],
        "type": "object"
      },
      "CreatePartnerAccountDto": {
        "description": "The account in a currency, under you or under the sub-client you are acting for.",
        "properties": {
          "currency": {
            "description": "ISO 4217. If the owner already holds an account in this currency, that account is returned (200) and nothing is opened.",
            "example": "EUR",
            "type": "string"
          },
          "externalRef": {
            "description": "Your own identifier for the account. Unique per owner. Must not begin with 'tcb:', which is reserved. Applied only when this call opens the account.",
            "example": "acme:payroll-eur",
            "nullable": true,
            "type": "object"
          },
          "idempotencyKey": {
            "description": "Alternative to the Idempotency-Key header. One of the two is required; sending both is allowed only if they match.",
            "example": "acme-2026-09-02-0001",
            "type": "string"
          },
          "label": {
            "description": "Your name for the account. Shown to you, never used as an IBAN holder name. Applied only when this call opens the account.",
            "example": "Payroll reserve",
            "type": "string"
          },
          "requestIban": {
            "default": false,
            "description": "No longer needed: an account this call opens always carries its IBAN. Accepted and ignored.",
            "example": true,
            "type": "boolean"
          },
          "role": {
            "description": "Not accepted. Sending it is refused with 409 ACCOUNT_MAIN_EXISTS rather than silently ignored.",
            "type": "string"
          }
        },
        "required": [
          "currency",
          "label"
        ],
        "type": "object"
      },
      "CreatePartnerBeneficiaryDto": {
        "description": "A payout destination to register: the payee and the bank account or wallet itself, in one call.",
        "properties": {
          "addressLine1": {
            "type": "string"
          },
          "addressLine2": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "country": {
            "description": "ISO 3166-1 alpha-2",
            "type": "string"
          },
          "currency": {
            "description": "ISO 4217",
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "entityType": {
            "default": "INDIVIDUAL",
            "enum": [
              "INDIVIDUAL",
              "BUSINESS"
            ],
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Your idempotency key for this registration — an alternative to the Idempotency-Key header. One of the two is required; sending both is allowed only if they match.",
            "example": "acme-payee-2026-09-03-0001",
            "type": "string"
          },
          "instrument": {
            "allOf": [
              {
                "$ref": "#/components/schemas/InstrumentInputDto"
              }
            ],
            "description": "The destination itself — a bank account (kind FIAT_BANK) or a wallet (kind CRYPTO_ADDRESS). Validated against the registry for the stated currency/rail or chain; a wallet also requires the travelRule capture."
          },
          "name": {
            "maxLength": 255,
            "type": "string"
          },
          "nickname": {
            "maxLength": 100,
            "type": "string"
          },
          "postalCode": {
            "type": "string"
          },
          "state": {
            "type": "string"
          }
        },
        "required": [
          "name",
          "instrument"
        ],
        "type": "object"
      },
      "CreatePartnerConversionDto": {
        "description": "The currency pair and the exact amount to sell, plus the accounts to debit and credit.",
        "properties": {
          "amount": {
            "description": "Amount of fromCurrency to sell, as a decimal string. Never a float — a JSON number cannot represent every decimal amount exactly, and money is the last place to discover that. Must not carry more fractional digits than fromCurrency settles at (USD: 2, USDC: 6).",
            "example": "1000.00",
            "type": "string"
          },
          "fromCurrency": {
            "description": "Currency to sell. You must hold an account in it.",
            "example": "USDC",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Client idempotency key. Mandatory — send it here or as the Idempotency-Key header. Replaying it returns the original result; reusing it with different parameters is rejected.",
            "example": "acme-conversion-2026-08-31-0001",
            "type": "string"
          },
          "quoteId": {
            "description": "A quote from POST /conversions/quote for this exact conversion. With it, the conversion executes against that quote, at the quoted rate and commission, and is never re-quoted. It must be unexpired and unused, and the request must repeat what was quoted (fromCurrency, toCurrency, amount, sourceAccountId, targetAccountId, toAccountId). Otherwise the conversion is refused with QUOTE_EXPIRED, QUOTE_ALREADY_USED, QUOTE_MISMATCH or QUOTE_NOT_FOUND, nothing is converted, and the idempotency key stays usable. Without it, the conversion is priced when it executes.",
            "example": "5e2c9a17-8b40-4d63-a1f8-3c7e0b9d2f46",
            "format": "uuid",
            "type": "string"
          },
          "sourceAccountId": {
            "description": "Account to debit. Omitted, your single active account in fromCurrency is used; ambiguity is refused rather than guessed. Every active account of yours in fromCurrency counts, including the account your crypto deposit address credits, so once you hold more than one this field is effectively mandatory — otherwise the request answers 409 CONVERSION_ACCOUNT_AMBIGUOUS with details.accountIds naming each candidate.",
            "example": "4d80f3b6-9a17-4c25-8e93-0b6d1f7a3c58",
            "format": "uuid",
            "type": "string"
          },
          "targetAccountId": {
            "description": "Account to credit. Omitted, your single active account in toCurrency is used; ambiguity is refused rather than guessed. Once you hold more than one account in toCurrency this field is effectively mandatory — otherwise the request answers 409 CONVERSION_ACCOUNT_AMBIGUOUS.",
            "example": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
            "format": "uuid",
            "type": "string"
          },
          "toAccountId": {
            "description": "Where the converted amount ends up: a fiat account in toCurrency, either one of your own or one of your sub-clients'. Your own account: the conversion is credited to it directly. A sub-client's account: the conversion is credited to your own account in toCurrency (targetAccountId, or your single active one) and moved on to the sub-client in the same step; the response carries the transferId of that move. Needs a key holding both trade:execute and transfer:execute. The sub-client must be able to receive.",
            "example": "9c3e5a1f-2b7d-4e60-8a94-6f1d0c2b7e35",
            "format": "uuid",
            "type": "string"
          },
          "toCurrency": {
            "description": "Currency to buy. You must hold an account in it.",
            "example": "USD",
            "type": "string"
          }
        },
        "required": [
          "fromCurrency",
          "toCurrency",
          "amount"
        ],
        "type": "object"
      },
      "CreatePartnerCryptoDepositAddressDto": {
        "description": "The asset and chain to issue your deposit address for.",
        "properties": {
          "asset": {
            "description": "The asset the address accepts. The pilot supports 'USDC' only.",
            "example": "USDC",
            "type": "string"
          },
          "chain": {
            "description": "The chain the address lives on. The pilot supports 'ARBITRUM' only.",
            "example": "ARBITRUM",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Alternative to the Idempotency-Key header.",
            "example": "acme-crypto-address-0001",
            "type": "string"
          }
        },
        "required": [
          "asset",
          "chain"
        ],
        "type": "object"
      },
      "CreatePartnerDepositDto": {
        "description": "Fiat to move into the curated vault for that currency, and the sub-account to attribute it to.",
        "properties": {
          "amount": {
            "description": "Amount as a decimal string. Never a float — a JSON number cannot represent every decimal amount exactly, and money is the last place to discover that. Must not carry more fractional digits than the currency settles at (USD: 2), and amounts below 0.000001 are rejected at pre-flight.",
            "example": "1000.00",
            "type": "string"
          },
          "currency": {
            "description": "Fiat currency to deposit. Selects the active vault for that currency.",
            "example": "USD",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Client idempotency key. Mandatory — send it here or as the Idempotency-Key header. Replaying it returns the original result; reusing it with different parameters is rejected.",
            "example": "acme-deposit-2026-08-27-0001",
            "type": "string"
          },
          "sourceAccountId": {
            "description": "Source fiat account. Omitted, your active account in that currency is used. Once you hold more than one account in that currency this field is effectively mandatory — otherwise the deposit is refused as ambiguous (409 SOURCE_ACCOUNT_AMBIGUOUS) before anything is charged. The account your crypto deposit address credits is never a deposit source: naming it answers 400 SOURCE_ACCOUNT_NOT_USABLE — convert the balance first, then deposit the fiat.",
            "example": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
            "format": "uuid",
            "type": "string"
          },
          "subAccountId": {
            "description": "Sub-account to credit. Omitted, your default sub-account is used. A sub-account is a partition of your own book — it does not change where the shares are custodied.",
            "example": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "currency",
          "amount"
        ],
        "type": "object"
      },
      "CreatePartnerPayoutDto": {
        "description": "A payout request: the registered destination to pay, the currency and amount, the optional source account, and the reference carried to the rail.",
        "properties": {
          "amount": {
            "description": "Amount to pay, as a decimal string. Never a float. Must not carry more fractional digits than the currency settles at (EUR: 2). Amounts below 0.000001 are refused.",
            "example": "1250.00",
            "type": "string"
          },
          "currency": {
            "description": "The payout currency. Must be the destination's currency — a payout is single-currency — and selects the fiat account the money leaves.",
            "example": "EUR",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Client idempotency key. Mandatory — send it here or as the Idempotency-Key header. Replaying it returns the same payout in its current state; reusing it with different parameters is rejected.",
            "example": "acme-payout-2026-09-06-0001",
            "type": "string"
          },
          "instrumentId": {
            "description": "The destination to pay: the instrumentId of a destination you registered, which must have completed screening, TCB approval and its holding period. There is no way to pass raw bank details here.",
            "example": "1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97",
            "format": "uuid",
            "type": "string"
          },
          "quoteId": {
            "description": "A quote from POST /payouts/quote for this exact payout. With it, the payout is charged the quoted Sending fee. It must be unexpired and unused, and the request must repeat what was quoted (instrumentId, currency, amount, sourceAccountId, and the x-on-behalf-of header). Otherwise the payout is refused with QUOTE_EXPIRED, QUOTE_ALREADY_USED, QUOTE_MISMATCH or QUOTE_NOT_FOUND, nothing is charged, and the idempotency key stays usable. Without it, the fee is priced when the payout is made.",
            "example": "0b6f2d84-3c19-4e7a-9a52-6d1e8f4c7b30",
            "format": "uuid",
            "type": "string"
          },
          "reference": {
            "description": "Your end-to-end reference for the payment, carried to the rail as the remittance information the receiving bank shows. 1–140 characters.",
            "example": "INV-2026-0042",
            "type": "string"
          },
          "sourceAccountId": {
            "description": "The fiat account the money leaves. Omitted, your single active account in that currency is used. Once you hold more than one account in that currency this field is effectively mandatory — otherwise the payout is refused as ambiguous (409 SOURCE_ACCOUNT_AMBIGUOUS) with nothing charged.",
            "example": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "instrumentId",
          "currency",
          "amount",
          "reference"
        ],
        "type": "object"
      },
      "CreatePartnerSettlementDto": {
        "description": "A same-currency movement to an account belonging to a DIFFERENT client of the bank. Name the account to debit and exactly one way of naming who is paid.",
        "properties": {
          "amount": {
            "description": "How much to settle, as a decimal string. Never a float, never an exponent, never a thousands separator.",
            "example": "1500.00",
            "type": "string"
          },
          "currency": {
            "description": "The currency both accounts hold (ISO 4217).",
            "example": "USD",
            "type": "string"
          },
          "endToEndId": {
            "description": "Your end-to-end reference. ISO 20022 shape, at most 35 characters, preserved verbatim and shown to both sides.",
            "example": "ACME-INV-2026-0042",
            "type": "string"
          },
          "fromAccountId": {
            "description": "The account to debit. Acting on behalf of a sub-client, it must be one of that sub-client's own accounts. Fiat, active, and in this currency.",
            "example": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
            "format": "uuid",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Your key for this settlement, here or in the Idempotency-Key header. Mandatory in one of the two.",
            "example": "acme-2026-09-08-0001",
            "type": "string"
          },
          "instrumentId": {
            "description": "Pay a destination you registered with kind INTERNAL_TCB. Exactly one of instrumentId, resolveToken and toAccountId.",
            "example": "2f6b1a90-7c34-4de1-91a8-5b0e3d7c4f21",
            "format": "uuid",
            "type": "string"
          },
          "remittance": {
            "description": "Optional structured remittance, at most 1 KB of JSON. Reaches both sides untouched.",
            "example": {
              "dueDate": "2026-09-30",
              "invoice": "INV-2026-0042"
            },
            "type": "object"
          },
          "resolveToken": {
            "description": "The token GET /network/resolve returned. The target is read out of the SIGNED token, not out of this request, which is what makes \"what was shown is what was paid\" true.",
            "type": "string"
          },
          "toAccountId": {
            "description": "Pay a known account id directly.",
            "example": "a1c93e6f-52b7-4d08-8e51-6b2f0c9d3a47",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "fromAccountId",
          "amount",
          "currency",
          "endToEndId"
        ],
        "type": "object"
      },
      "CreatePartnerSettlementHoldDto": {
        "description": "Funds to reserve against a named member, and the reference the release will settle under.",
        "properties": {
          "amount": {
            "description": "Decimal string, greater than zero.",
            "example": "1500.00",
            "type": "string"
          },
          "currency": {
            "description": "ISO 4217 code.",
            "example": "USD",
            "type": "string"
          },
          "endToEndId": {
            "description": "The reference the release will settle under.",
            "example": "ACME-DVP-2026-0042",
            "type": "string"
          },
          "fromAccountId": {
            "description": "The account to reserve against. Must belong to the acting node, be ACTIVE and fiat, and hold this currency.",
            "example": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Your key for this hold. Replaying it returns the original hold.",
            "example": "acme-hold-2026-09-08-0001",
            "type": "string"
          },
          "instrumentId": {
            "description": "Reserve against a saved network payee. Name exactly one of instrumentId, resolveToken or toAccountId — the same three ways POST /settlements names who is paid, so a hold and the settlement it becomes cannot resolve differently.",
            "type": "string"
          },
          "remittance": {
            "description": "Optional structured remittance, at most 1 KB of JSON.",
            "type": "object"
          },
          "resolveToken": {
            "description": "The token GET /network/resolve returned. Resolve a handle or a TCB IBAN there and cite the token here: it is what makes the member you were SHOWN the member the release pays.",
            "type": "string"
          },
          "toAccountId": {
            "description": "Reserve against a known account id directly.",
            "type": "string"
          }
        },
        "required": [
          "fromAccountId",
          "amount",
          "currency",
          "endToEndId"
        ],
        "type": "object"
      },
      "CreatePartnerSettlementRequestDto": {
        "description": "An ask: the amount you want another member to pay you, the account you want credited, and the reference the settlement will carry.",
        "properties": {
          "amount": {
            "description": "Decimal string, greater than zero.",
            "example": "1500.00",
            "type": "string"
          },
          "currency": {
            "description": "ISO 4217 code. Both sides must hold it.",
            "example": "USD",
            "type": "string"
          },
          "dueBy": {
            "description": "When the ask lapses, ISO-8601 and in the future. Nothing runs on a clock: the request is marked EXPIRED the next time it is read or an approval arrives late, never by a job — so do not treat a passed dueBy as an event you will be told about.",
            "example": "2026-10-01T12:00:00.000Z",
            "type": "string"
          },
          "endToEndId": {
            "description": "YOUR end-to-end reference, ISO 20022 shape, at most 35 characters. It travels onto the settlement the payer books, so the invoice number you chose is what reaches both statements.",
            "example": "ACME-INV-2026-0042",
            "type": "string"
          },
          "fromAccountId": {
            "description": "The account YOU want credited when the payer approves. Must belong to the acting node, be ACTIVE and fiat, and be able to land this currency.",
            "example": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Your key for this request. Replaying it returns the original request.",
            "example": "acme-req-2026-09-08-0001",
            "type": "string"
          },
          "remittance": {
            "description": "Optional structured remittance, at most 1 KB of JSON. Reaches both sides intact.",
            "example": {
              "invoice": "INV-2026-0042"
            },
            "type": "object"
          },
          "toClientAccountId": {
            "description": "The member being asked to pay, when you already hold its id.",
            "example": "246f8056-fc27-4e06-a589-0866d9cbffbd",
            "type": "string"
          },
          "toHandle": {
            "description": "The member being asked to pay, by network handle. Name exactly one of toHandle, toIban or toClientAccountId.",
            "example": "acme-treasury",
            "type": "string"
          },
          "toIban": {
            "description": "The member being asked to pay, by one of its TCB IBANs.",
            "example": "BH00TCB00000000000001",
            "type": "string"
          }
        },
        "required": [
          "fromAccountId",
          "amount",
          "currency",
          "endToEndId"
        ],
        "type": "object"
      },
      "CreatePartnerSettlementReturnDto": {
        "description": "Your ask for a settlement to be returned, and why. The full amount only in this version.",
        "properties": {
          "amount": {
            "description": "Optional, and the FULL settlement amount is the only value accepted in this version. Anything else is refused with 422 SETTLEMENT_RETURN_PARTIAL_UNSUPPORTED rather than approximated.",
            "example": "1500.00",
            "type": "string"
          },
          "reason": {
            "description": "Why you are asking for the money back, at most 280 characters.",
            "example": "Paid twice against the same invoice",
            "type": "string"
          }
        },
        "type": "object"
      },
      "CreatePartnerShareRedemptionDto": {
        "description": "A request to take tcbUSD out of the vault at once, for shares you hold.",
        "properties": {
          "amount": {
            "description": "tcbUSD to take back out of the vault, as a decimal string (up to 18 fractional digits). The vault burns the shares that amount is worth; the tcbUSD is booked to the sub-account.",
            "example": "400",
            "type": "string"
          },
          "currency": {
            "description": "Currency of the step: the fiat currency for a mint or a token redemption, and the currency of the vault (and of its tcbUSD) for the vault steps. Selects the token and the vault.",
            "example": "USD",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Client idempotency key. Mandatory — send it here or as the Idempotency-Key header. Replaying it returns the original result; reusing it with different parameters is rejected.",
            "example": "acme-step-2026-10-12-0001",
            "type": "string"
          },
          "subAccountId": {
            "description": "Sub-account the step belongs to. Omitted, your default sub-account is used. A sub-account is a partition of your own book: tcbUSD and shares are all held in the one TCB wallet assigned to you, and each sub-account can only spend what is booked to it.",
            "example": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "currency",
          "amount"
        ],
        "type": "object"
      },
      "CreatePartnerShareRedemptionRequestDto": {
        "description": "A request to queue a redemption in the vault's queue, for shares you hold.",
        "properties": {
          "amount": {
            "description": "tcbUSD to take back out of the vault, as a decimal string (up to 18 fractional digits). The vault burns the shares that amount is worth; the tcbUSD is booked to the sub-account.",
            "example": "400",
            "type": "string"
          },
          "currency": {
            "description": "Currency of the step: the fiat currency for a mint or a token redemption, and the currency of the vault (and of its tcbUSD) for the vault steps. Selects the token and the vault.",
            "example": "USD",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Client idempotency key. Mandatory — send it here or as the Idempotency-Key header. Replaying it returns the original result; reusing it with different parameters is rejected.",
            "example": "acme-step-2026-10-12-0001",
            "type": "string"
          },
          "subAccountId": {
            "description": "Sub-account the step belongs to. Omitted, your default sub-account is used. A sub-account is a partition of your own book: tcbUSD and shares are all held in the one TCB wallet assigned to you, and each sub-account can only spend what is booked to it.",
            "example": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "currency",
          "amount"
        ],
        "type": "object"
      },
      "CreatePartnerShareSubscriptionDto": {
        "description": "A request to put tcbUSD you hold into the vault for shares.",
        "properties": {
          "amount": {
            "description": "tcbUSD to put into the currency's vault, as a decimal string (up to 18 fractional digits). Drawn from the tcbUSD booked to the sub-account; you receive vault shares.",
            "example": "1000",
            "type": "string"
          },
          "currency": {
            "description": "Currency of the step: the fiat currency for a mint or a token redemption, and the currency of the vault (and of its tcbUSD) for the vault steps. Selects the token and the vault.",
            "example": "USD",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Client idempotency key. Mandatory — send it here or as the Idempotency-Key header. Replaying it returns the original result; reusing it with different parameters is rejected.",
            "example": "acme-step-2026-10-12-0001",
            "type": "string"
          },
          "subAccountId": {
            "description": "Sub-account the step belongs to. Omitted, your default sub-account is used. A sub-account is a partition of your own book: tcbUSD and shares are all held in the one TCB wallet assigned to you, and each sub-account can only spend what is booked to it.",
            "example": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "currency",
          "amount"
        ],
        "type": "object"
      },
      "CreatePartnerSubAccountDto": {
        "description": "A new named partition of your own vault position.",
        "properties": {
          "externalRef": {
            "description": "Your own identifier for whatever this sub-account stands for on your books. Unique within your principal, so it can be used as a stable handle. Must not begin with 'tcb:', which is reserved for sub-accounts TCB provisions for you.",
            "example": "acme-fund-002",
            "type": "string"
          },
          "label": {
            "description": "Human-readable name for this sub-account.",
            "example": "Growth Fund II",
            "type": "string"
          }
        },
        "required": [
          "label",
          "externalRef"
        ],
        "type": "object"
      },
      "CreatePartnerTokenMintDto": {
        "description": "A request to mint tcbUSD from one of your fiat accounts.",
        "properties": {
          "amount": {
            "description": "Fiat to turn into tcbUSD, as a decimal string; you receive the same amount of tcbUSD. Must not carry more fractional digits than the currency settles at (USD: 2).",
            "example": "1000.00",
            "type": "string"
          },
          "currency": {
            "description": "Currency of the step: the fiat currency for a mint or a token redemption, and the currency of the vault (and of its tcbUSD) for the vault steps. Selects the token and the vault.",
            "example": "USD",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Client idempotency key. Mandatory — send it here or as the Idempotency-Key header. Replaying it returns the original result; reusing it with different parameters is rejected.",
            "example": "acme-step-2026-10-12-0001",
            "type": "string"
          },
          "sourceAccountId": {
            "description": "Fiat account to debit. Omitted, your one active account in that currency is used; once you hold more than one, name it or the mint is refused as ambiguous before anything is charged.",
            "example": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
            "format": "uuid",
            "type": "string"
          },
          "subAccountId": {
            "description": "Sub-account the step belongs to. Omitted, your default sub-account is used. A sub-account is a partition of your own book: tcbUSD and shares are all held in the one TCB wallet assigned to you, and each sub-account can only spend what is booked to it.",
            "example": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "currency",
          "amount"
        ],
        "type": "object"
      },
      "CreatePartnerTokenRedemptionDto": {
        "description": "A request to redeem tcbUSD you hold to one of your fiat accounts.",
        "properties": {
          "amount": {
            "description": "tcbUSD to burn, as a decimal string; the same amount of fiat is credited. Must not carry more fractional digits than the currency settles at (USD: 2), because a bank cannot be credited a fraction of a cent.",
            "example": "250.00",
            "type": "string"
          },
          "currency": {
            "description": "Currency of the step: the fiat currency for a mint or a token redemption, and the currency of the vault (and of its tcbUSD) for the vault steps. Selects the token and the vault.",
            "example": "USD",
            "type": "string"
          },
          "destinationAccountId": {
            "description": "Fiat account to credit. Omitted, your one active account in that currency is used; once you hold more than one, name it.",
            "example": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
            "format": "uuid",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Client idempotency key. Mandatory — send it here or as the Idempotency-Key header. Replaying it returns the original result; reusing it with different parameters is rejected.",
            "example": "acme-step-2026-10-12-0001",
            "type": "string"
          },
          "subAccountId": {
            "description": "Sub-account the step belongs to. Omitted, your default sub-account is used. A sub-account is a partition of your own book: tcbUSD and shares are all held in the one TCB wallet assigned to you, and each sub-account can only spend what is booked to it.",
            "example": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "currency",
          "amount"
        ],
        "type": "object"
      },
      "CreatePartnerTransferDto": {
        "description": "A same-currency movement between two accounts in your tree. Both accounts must resolve under your root client.",
        "properties": {
          "amount": {
            "description": "How much to move, as a decimal string. Never a float, never an exponent, never a thousands separator.",
            "example": "250.00",
            "type": "string"
          },
          "currency": {
            "description": "The currency of both accounts (ISO 4217). A pair in different currencies is refused with TRANSFER_CURRENCY_MISMATCH.",
            "example": "USD",
            "type": "string"
          },
          "fromAccountId": {
            "description": "The account to debit. Acting on behalf of a sub-client, it must be one of that sub-client's own accounts.",
            "example": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
            "format": "uuid",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Alternative to the Idempotency-Key header. One of the two is required; sending both is allowed only if they match.",
            "example": "acme-transfer-2026-09-02-0001",
            "type": "string"
          },
          "metadata": {
            "description": "Free-form, yours. Stored and returned untouched.",
            "example": {
              "ledgerRef": "JRNL-2026-0412"
            },
            "type": "object"
          },
          "reference": {
            "description": "Your own note, shown on both statements.",
            "example": "Invoice 2026-0412",
            "maxLength": 140,
            "nullable": true,
            "type": "string"
          },
          "toAccountId": {
            "description": "The account to credit. Any account in your tree, in the same currency.",
            "example": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "fromAccountId",
          "toAccountId",
          "amount",
          "currency"
        ],
        "type": "object"
      },
      "CreatePartnerWebhookDto": {
        "description": "The endpoint to deliver events to, and the events to send it.",
        "properties": {
          "events": {
            "description": "Event types to deliver — a non-empty subset of the catalogue.",
            "example": [
              "deposit.settled",
              "withdrawal.settled"
            ],
            "items": {
              "enum": [
                "deposit.settled",
                "deposit.failed",
                "withdrawal.settled",
                "withdrawal.failed",
                "conversion.settled",
                "conversion.failed",
                "sub_client.created",
                "sub_client.verification.updated",
                "sub_client.closed",
                "account.created",
                "account.iban.issued",
                "account.closed",
                "transfer.completed",
                "crypto_deposit.credited",
                "beneficiary.activated",
                "beneficiary.blocked",
                "payout.settled",
                "payout.failed",
                "payout.returned",
                "payout.held",
                "payout.released",
                "settlement.settled",
                "settlement.reversed",
                "settlement.request.created",
                "settlement.request.approved",
                "settlement.request.declined",
                "settlement.hold.created",
                "settlement.hold.released",
                "settlement.hold.cancelled",
                "settlement.return.requested",
                "settlement.return.accepted",
                "settlement.return.declined",
                "settlement.netting.agreement.proposed",
                "settlement.netting.agreement.accepted",
                "settlement.netting.agreement.declined",
                "settlement.netting.agreement.ended",
                "settlement.netting.obligation.created",
                "settlement.netting.obligation.withdrawn",
                "settlement.netting.cut",
                "token_mint.settled",
                "token_mint.failed",
                "token_redemption.settled",
                "token_redemption.failed",
                "share_subscription.settled",
                "share_subscription.failed",
                "share_redemption.settled",
                "share_redemption.failed",
                "share_redemption_request.queued",
                "share_redemption_request.settled",
                "share_redemption_request.cancelled",
                "share_redemption_request.failed"
              ],
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Absolute https URL events are POSTed to.",
            "example": "https://partner.example.com/tcb/webhooks",
            "type": "string"
          }
        },
        "required": [
          "url",
          "events"
        ],
        "type": "object"
      },
      "CreatePartnerWithdrawalDto": {
        "description": "Fiat to redeem out of the curated vault for that currency, and the account to credit.",
        "properties": {
          "amount": {
            "description": "Amount of fiat to withdraw, as a decimal string. Never a float. Must not carry more fractional digits than the currency settles at (USD: 2) — a finer amount would be rounded down on settlement and the remainder left as dust, so it is refused instead. Amounts below 0.000001 are rejected at pre-flight.",
            "example": "250.00",
            "type": "string"
          },
          "currency": {
            "description": "Fiat currency to withdraw. Selects the active vault for that currency, and the settlement account the fiat is credited to.",
            "example": "USD",
            "type": "string"
          },
          "destinationAccountId": {
            "description": "Destination fiat account for the credit. Omitted, your active account in that currency is used. Once you hold more than one account in that currency this field is effectively mandatory — otherwise the withdrawal is refused as ambiguous (409 DESTINATION_ACCOUNT_AMBIGUOUS) with nothing withdrawn. The account your crypto deposit address credits cannot receive a withdrawal: naming it answers 400 DESTINATION_ACCOUNT_NOT_USABLE.",
            "example": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
            "format": "uuid",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Client idempotency key. Mandatory — send it here or as the Idempotency-Key header. Replaying it returns the original result; reusing it with different parameters is rejected.",
            "example": "acme-withdrawal-2026-08-30-0001",
            "type": "string"
          },
          "subAccountId": {
            "description": "Sub-account to withdraw from. Omitted, your default sub-account is used. The withdrawal is authorised against THAT sub-account's available position, not against your whole vault balance.",
            "example": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "currency",
          "amount"
        ],
        "type": "object"
      },
      "CreateSubClientDto": {
        "description": "A new end customer, together with the currencies it should hold a MAIN account in.",
        "properties": {
          "attestation": {
            "allOf": [
              {
                "$ref": "#/components/schemas/AttestationDto"
              }
            ],
            "description": "REQUIRED before the sub-client can be activated. Optional on this call only: omitting it leaves the sub-client REQUIREMENTS_DUE."
          },
          "currencies": {
            "description": "ISO 4217, at least one. One MAIN account per currency is reserved atomically, each with an IBAN that stays inactive until the sub-client is VERIFIED.",
            "example": [
              "EUR"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "externalRef": {
            "description": "Your own identifier for this sub-client. Unique within your client account. Must not begin with 'tcb:', which is reserved.",
            "example": "acme:cust-04231",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Alternative to the Idempotency-Key header. One of the two is required; sending both is allowed only if they match.",
            "example": "acme-2026-09-02-0001",
            "type": "string"
          },
          "identity": {
            "description": "PersonIdentity when kind is \"person\", BusinessIdentity when kind is \"business\". Send the activation baseline for that kind; anything still missing lands the sub-client REQUIREMENTS_DUE and is named in requirements.currentlyDue rather than rejecting the call. `examples` on this schema carries one of each shape — see guides/sub-clients.mdx for the full field-by-field reference.",
            "example": {
              "address": {
                "city": "Manama",
                "country": "BH",
                "line1": "14 Road 2825"
              },
              "dateOfBirth": "1988-04-17",
              "firstName": "Fatima",
              "lastName": "Al-Khalifa",
              "nationality": "BH"
            },
            "examples": [
              {
                "address": {
                  "city": "Manama",
                  "country": "BH",
                  "line1": "14 Road 2825"
                },
                "dateOfBirth": "1988-04-17",
                "firstName": "Fatima",
                "lastName": "Al-Khalifa",
                "nationalId": "880417012",
                "nationality": "BH"
              },
              {
                "businessActivity": "Payment services",
                "incorporation": {
                  "country": "BH",
                  "date": "2019-02-01"
                },
                "legalForm": "W.L.L.",
                "parties": [
                  {
                    "address": "BH",
                    "dateOfBirth": "1978-06-30",
                    "firstName": "Yousef",
                    "lastName": "Al-Sayed",
                    "nationalId": "780630221",
                    "nationality": "BH",
                    "ownershipPercent": "60",
                    "role": "ubo"
                  }
                ],
                "registeredAddress": {
                  "city": "Manama",
                  "country": "BH",
                  "line1": "Bahrain Bay Tower"
                },
                "registrationNumber": "CR-114523",
                "seniorManagement": [
                  {
                    "firstName": "Layla",
                    "lastName": "Mansour",
                    "role": "CEO"
                  }
                ]
              }
            ],
            "type": "object"
          },
          "kind": {
            "description": "Whether this end customer is a natural person or a business. It decides which identity shape is expected below.",
            "enum": [
              "person",
              "business"
            ],
            "example": "person",
            "type": "string"
          },
          "legalName": {
            "description": "The verified legal name. It is the payee name on every IBAN issued for this sub-client — presented for payee-name checks where the scheme runs them — so it must match the identity record's name. It is a payee/reconciliation name on a coordinate under your master relationship, not account title.",
            "example": "Fatima Al-Khalifa",
            "type": "string"
          },
          "metadata": {
            "description": "Free-form, yours. Stored and returned untouched.",
            "example": {
              "onboardedBy": "app",
              "segment": "retail"
            },
            "type": "object"
          }
        },
        "required": [
          "kind",
          "externalRef",
          "legalName",
          "currencies"
        ],
        "type": "object"
      },
      "DirectoryHitDto": {
        "description": "One member in the directory.",
        "properties": {
          "handle": {
            "example": "acme-treasury",
            "type": "string"
          },
          "kind": {
            "example": "CLIENT",
            "type": "string"
          },
          "legalName": {
            "example": "Acme Trading Ltd",
            "type": "string"
          }
        },
        "required": [
          "handle",
          "legalName",
          "kind"
        ],
        "type": "object"
      },
      "IdentityRecordResponse": {
        "description": "The identity record you supplied for a sub-client, as stored. TCB adds nothing to it.",
        "properties": {
          "business": {
            "description": "The business identity you supplied, as stored. Null when kind is person.",
            "example": {
              "businessActivity": "Payment services",
              "incorporation": {
                "country": "BH",
                "date": "2019-02-01"
              },
              "legalForm": "W.L.L.",
              "parties": [
                {
                  "address": "BH",
                  "dateOfBirth": "1978-06-30",
                  "firstName": "Yousef",
                  "lastName": "Al-Sayed",
                  "nationalId": "780630221",
                  "nationality": "BH",
                  "ownershipPercent": "60",
                  "role": "ubo"
                }
              ],
              "registeredAddress": {
                "city": "Manama",
                "country": "BH",
                "line1": "Bahrain Bay Tower"
              },
              "registrationNumber": "CR-114523",
              "seniorManagement": [
                {
                  "firstName": "Layla",
                  "lastName": "Mansour",
                  "role": "CEO"
                }
              ]
            },
            "nullable": true,
            "type": "object"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "kind": {
            "description": "Which of the two blocks below is populated.",
            "enum": [
              "person",
              "business"
            ],
            "example": "person",
            "type": "string"
          },
          "person": {
            "description": "The person identity you supplied, as stored. Null when kind is business.",
            "example": {
              "address": {
                "city": "Manama",
                "country": "BH",
                "line1": "14 Road 2825"
              },
              "dateOfBirth": "1988-04-17",
              "firstName": "Fatima",
              "lastName": "Al-Khalifa",
              "nationality": "BH"
            },
            "nullable": true,
            "type": "object"
          },
          "subClientId": {
            "description": "The sub-client this record belongs to.",
            "example": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
            "format": "uuid",
            "type": "string"
          },
          "updatedAt": {
            "description": "When the record last changed.",
            "example": "2026-08-28T09:00:00.000Z",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "subClientId",
          "kind",
          "updatedAt",
          "disclosure"
        ],
        "type": "object"
      },
      "InstrumentInputDto": {
        "description": "The destination itself. details carries the rail fields for a bank account, or { address, memo? } for a wallet; the server validates it against the registry for the stated currency and rail, or chain.",
        "properties": {
          "accountHolderName": {
            "description": "Name on the account, as supplied. Soft-compared to the party name.",
            "type": "string"
          },
          "bankName": {
            "type": "string"
          },
          "chain": {
            "description": "CRYPTO_ADDRESS: the network. Required for a single-chain address (Bitcoin, Solana); for an EVM address give `chain` or `networks` (when both, `chain` is the primary and must be one of `networks`).",
            "enum": [
              "ETHEREUM",
              "BITCOIN",
              "SOLANA",
              "POLYGON",
              "AVALANCHE",
              "ARBITRUM",
              "OPTIMISM",
              "BASE"
            ],
            "type": "string"
          },
          "currency": {
            "description": "ISO 4217. Required for FIAT_BANK.",
            "type": "string"
          },
          "details": {
            "description": "Rail fields for FIAT_BANK (iban / accountNumber / bicSwift / sortCode / routingNumber / bankCountry), { address, memo? } for CRYPTO_ADDRESS, { clientAccountId, subAccountId? } for INTERNAL_TCB.",
            "type": "object"
          },
          "kind": {
            "enum": [
              "FIAT_BANK",
              "CRYPTO_ADDRESS",
              "INTERNAL_TCB"
            ],
            "type": "string"
          },
          "label": {
            "description": "Free-text label for this destination.",
            "type": "string"
          },
          "networks": {
            "description": "EVM CRYPTO_ADDRESS only: every network the destination is payable on from the start. Each must be a network Three Comma Bank sends on. Several networks need a self-hosted wallet (`travelRule.selfHosted: true`) with no contract code on any of them.",
            "items": {
              "enum": [
                "ETHEREUM",
                "BITCOIN",
                "SOLANA",
                "POLYGON",
                "AVALANCHE",
                "ARBITRUM",
                "OPTIMISM",
                "BASE"
              ],
              "type": "string"
            },
            "type": "array"
          },
          "rail": {
            "description": "Optional override. The rail is server-inferred from (country, currency) by default (§1.28a).",
            "enum": [
              "SEPA",
              "SEPA_INSTANT",
              "SWIFT",
              "SWIFT_NO_IBAN",
              "ACH",
              "FEDWIRE",
              "FPS",
              "CHAPS",
              "LOCAL"
            ],
            "type": "string"
          },
          "travelRule": {
            "$ref": "#/components/schemas/TravelRuleDto"
          }
        },
        "required": [
          "kind",
          "details"
        ],
        "type": "object"
      },
      "NettingObligationPartyDto": {
        "description": "The member on one side of an obligation.",
        "properties": {
          "clientAccountId": {
            "format": "uuid",
            "type": "string"
          },
          "legalName": {
            "example": "Acme Trading Ltd",
            "type": "string"
          }
        },
        "required": [
          "clientAccountId",
          "legalName"
        ],
        "type": "object"
      },
      "NettingPartyDto": {
        "description": "One side of an agreement: the member, its account under it, and its frozen legal name.",
        "properties": {
          "accountId": {
            "description": "The partition under the agreement. null until the counterparty accepts.",
            "format": "uuid",
            "nullable": true,
            "type": "object"
          },
          "clientAccountId": {
            "format": "uuid",
            "type": "string"
          },
          "legalName": {
            "description": "Frozen when the agreement was proposed.",
            "example": "Acme Trading Ltd",
            "type": "string"
          }
        },
        "required": [
          "clientAccountId",
          "accountId",
          "legalName"
        ],
        "type": "object"
      },
      "NettingPositionDto": {
        "description": "The OPEN set as you read it: what you owe, what you are owed, the net, who owes it, and whether you may cut now.",
        "properties": {
          "netAmount": {
            "description": "|youOwe − owedToYou|.",
            "example": "1500.00",
            "type": "string"
          },
          "netPayerClientAccountId": {
            "description": "Who owes the net. null when it is zero.",
            "format": "uuid",
            "nullable": true,
            "type": "object"
          },
          "openObligations": {
            "description": "OPEN obligations both ways.",
            "example": 3,
            "type": "number"
          },
          "owedToYou": {
            "description": "Σ OPEN owed to you.",
            "example": "2500.00",
            "type": "string"
          },
          "youCut": {
            "description": "Whether YOU may cut now: you owe the net, or the net is zero and something is open.",
            "example": true,
            "type": "boolean"
          },
          "youOwe": {
            "description": "Σ OPEN you owe.",
            "example": "4000.00",
            "type": "string"
          }
        },
        "required": [
          "openObligations",
          "youOwe",
          "owedToYou",
          "netAmount",
          "netPayerClientAccountId",
          "youCut"
        ],
        "type": "object"
      },
      "PageOfAccountsResponse": {
        "description": "A page of accounts. Pass nextCursor back as cursor to fetch the following page; a null nextCursor means this was the last one.",
        "properties": {
          "items": {
            "description": "This page of accounts.",
            "items": {
              "$ref": "#/components/schemas/PartnerAccountResponse"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass this back as cursor for the next page. Null when this was the last page.",
            "example": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "items",
          "nextCursor"
        ],
        "type": "object"
      },
      "PageOfBeneficiariesResponse": {
        "description": "A page of destinations. Pass nextCursor back as cursor to fetch the following page; a null nextCursor means this was the last one.",
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/PartnerBeneficiaryResponse"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass this back as cursor to fetch the following page. Null means this was the last one.",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "items",
          "nextCursor"
        ],
        "type": "object"
      },
      "PageOfCryptoDepositsResponse": {
        "description": "A page of crypto deposits, newest first. Pass nextCursor back as cursor to fetch the following page; a null nextCursor means this was the last one.",
        "properties": {
          "items": {
            "description": "The deposits, newest first.",
            "items": {
              "$ref": "#/components/schemas/PartnerCryptoDepositResponse"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass back as cursor for the next page; null on the last page.",
            "example": null,
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "items",
          "nextCursor"
        ],
        "type": "object"
      },
      "PageOfDirectoryHitsResponse": {
        "description": "A page of directory members. Pass nextCursor back as cursor to fetch the following page; a null nextCursor means this was the last one.",
        "properties": {
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/DirectoryHitDto"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass it back as cursor. Opaque.",
            "example": null,
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "items",
          "nextCursor",
          "disclosure"
        ],
        "type": "object"
      },
      "PageOfNettingAgreementsResponse": {
        "description": "A page of agreements, newest first. Pass nextCursor back as cursor to fetch the following page; a null nextCursor means this was the last one.",
        "properties": {
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/PartnerNettingAgreementResponse"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass it back as cursor. Opaque.",
            "example": null,
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "items",
          "nextCursor",
          "disclosure"
        ],
        "type": "object"
      },
      "PageOfNettingCutsResponse": {
        "description": "A page of cuts, newest first. Pass nextCursor back as cursor to fetch the following page; a null nextCursor means this was the last one.",
        "properties": {
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/PartnerNettingCutResponse"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass it back as cursor. Opaque.",
            "example": null,
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "items",
          "nextCursor",
          "disclosure"
        ],
        "type": "object"
      },
      "PageOfNettingObligationsResponse": {
        "description": "A page of obligations, newest first. Pass nextCursor back as cursor to fetch the following page; a null nextCursor means this was the last one.",
        "properties": {
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/PartnerNettingObligationResponse"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass it back as cursor. Opaque.",
            "example": null,
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "items",
          "nextCursor",
          "disclosure"
        ],
        "type": "object"
      },
      "PageOfPartnerChainStepsResponse": {
        "description": "A page of chain steps of one kind, newest first.",
        "properties": {
          "items": {
            "description": "Newest first.",
            "items": {
              "$ref": "#/components/schemas/PartnerChainStepResponse"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass as cursor to read the next page. Null on the last page. Opaque.",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "items",
          "nextCursor"
        ],
        "type": "object"
      },
      "PageOfPartnerStatementsResponse": {
        "description": "A page of statements. Pass nextCursor back as cursor to fetch the following page; a null nextCursor means this was the last one.",
        "properties": {
          "items": {
            "description": "This page of statements.",
            "items": {
              "$ref": "#/components/schemas/PartnerStatementListItemResponse"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass this back as cursor for the next page. Null when this was the last page.",
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "items",
          "nextCursor"
        ],
        "type": "object"
      },
      "PageOfPartnerVaultDepositsResponse": {
        "description": "A page of vault deposits. Pass nextCursor back as cursor to fetch the following page; a null nextCursor means this was the last one.",
        "properties": {
          "items": {
            "description": "Newest first.",
            "items": {
              "$ref": "#/components/schemas/PartnerVaultDepositListItem"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass as cursor for the next page. Null on the last page.",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "items",
          "nextCursor"
        ],
        "type": "object"
      },
      "PageOfPartnerVaultWithdrawalsResponse": {
        "description": "A page of vault withdrawals. Pass nextCursor back as cursor to fetch the following page; a null nextCursor means this was the last one.",
        "properties": {
          "items": {
            "description": "Newest first.",
            "items": {
              "$ref": "#/components/schemas/PartnerVaultWithdrawalListItem"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass as cursor for the next page. Null on the last page.",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "items",
          "nextCursor"
        ],
        "type": "object"
      },
      "PageOfSettlementHoldsResponse": {
        "description": "A page of settlement holds, newest first. Pass nextCursor back as cursor to fetch the following page.",
        "properties": {
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/PartnerSettlementHoldResponse"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass it back as cursor. Opaque.",
            "example": null,
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "items",
          "nextCursor",
          "disclosure"
        ],
        "type": "object"
      },
      "PageOfSettlementRequestsResponse": {
        "description": "A page of settlement requests, newest first. Pass nextCursor back as cursor to fetch the following page.",
        "properties": {
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/PartnerSettlementRequestResponse"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass it back as cursor. Opaque.",
            "example": null,
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "items",
          "nextCursor",
          "disclosure"
        ],
        "type": "object"
      },
      "PageOfSettlementReturnsResponse": {
        "description": "A page of return requests, newest first. Pass nextCursor back as cursor to fetch the following page.",
        "properties": {
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/PartnerSettlementReturnResponse"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass it back as cursor. Opaque.",
            "example": null,
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "items",
          "nextCursor",
          "disclosure"
        ],
        "type": "object"
      },
      "PageOfSettlementsResponse": {
        "description": "A page of settlements, newest first. Pass nextCursor back as cursor to fetch the following page; a null nextCursor means this was the last one.",
        "properties": {
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/PartnerSettlementResponse"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass it back as cursor. Opaque.",
            "example": null,
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "items",
          "nextCursor",
          "disclosure"
        ],
        "type": "object"
      },
      "PageOfSubClientsResponse": {
        "description": "A page of sub-clients. Pass nextCursor back as cursor to fetch the following page; a null nextCursor means this was the last one.",
        "properties": {
          "items": {
            "description": "This page of sub-clients.",
            "items": {
              "$ref": "#/components/schemas/PartnerSubClientResponse"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass this back as cursor for the next page. Null when this was the last page.",
            "example": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "items",
          "nextCursor"
        ],
        "type": "object"
      },
      "PageOfTransfersResponse": {
        "description": "A page of transfers, oldest first. Pass nextCursor back as cursor to fetch the following page; a null nextCursor means this was the last one.",
        "properties": {
          "items": {
            "description": "This page of transfers.",
            "items": {
              "$ref": "#/components/schemas/PartnerTransferResponse"
            },
            "type": "array"
          },
          "nextCursor": {
            "description": "Pass this back as cursor for the next page. Null when this was the last page.",
            "example": "0c93a6e1-58fb-4d27-9a04-7e1b3c5d8f26",
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "items",
          "nextCursor"
        ],
        "type": "object"
      },
      "PartnerAccountResponse": {
        "description": "One fiat account: who owns it, what it holds, its IBAN if it has one, and what may be done with it.",
        "properties": {
          "accountId": {
            "description": "The account id.",
            "example": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
            "format": "uuid",
            "type": "string"
          },
          "balance": {
            "allOf": [
              {
                "$ref": "#/components/schemas/AccountBalanceDto"
              }
            ],
            "description": "What the account holds."
          },
          "capabilities": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapabilitiesFlagsDto"
              }
            ],
            "description": "What may be done with the account today, following its owner's verification."
          },
          "createdAt": {
            "description": "When the account was opened.",
            "example": "2026-08-14T08:42:11.000Z",
            "format": "date-time",
            "type": "string"
          },
          "currency": {
            "description": "The currency the account holds — an ISO 4217 code for a fiat account, or the asset symbol for a crypto one (for example USDC).",
            "example": "EUR",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "externalRef": {
            "description": "Your own identifier for the account, or null if you gave none.",
            "example": "acme:payroll-eur",
            "nullable": true,
            "type": "object"
          },
          "iban": {
            "allOf": [
              {
                "$ref": "#/components/schemas/AccountIbanDto"
              }
            ],
            "description": "The IBAN a payer can always use. Every currency account of one fiat account receives on that account's IBAN, and a payment in this currency lands in this account. Null if the account has none.",
            "nullable": true
          },
          "label": {
            "description": "The name you gave the account.",
            "example": "Payroll reserve",
            "type": "string"
          },
          "localRails": {
            "description": "Local details for this account's currency on its domestic payment scheme, where the currency has one — for example SEPA for EUR, Faster Payments for GBP. Empty when there are none, which is always the case for JPY, BHD and a crypto account.",
            "items": {
              "$ref": "#/components/schemas/AccountLocalRailDto"
            },
            "type": "array"
          },
          "ownerId": {
            "description": "Who the account belongs to — you, or one of your sub-clients.",
            "example": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
            "format": "uuid",
            "type": "string"
          },
          "ownerType": {
            "description": "CLIENT when the account is your own, SUB_CLIENT when it belongs to a sub-client.",
            "enum": [
              "CLIENT",
              "SUB_CLIENT"
            ],
            "example": "SUB_CLIENT",
            "type": "string"
          },
          "role": {
            "description": "MAIN is the owner's account for that currency. SUB is retired: an extra account beside the MAIN that an older version of POST /accounts opened; existing ones are folded into the MAIN.",
            "enum": [
              "MAIN",
              "SUB"
            ],
            "example": "MAIN",
            "type": "string"
          },
          "status": {
            "description": "CLOSED accounts hold no balance and take no further movements.",
            "enum": [
              "ACTIVE",
              "CLOSED"
            ],
            "example": "ACTIVE",
            "type": "string"
          }
        },
        "required": [
          "accountId",
          "ownerType",
          "ownerId",
          "currency",
          "role",
          "label",
          "externalRef",
          "status",
          "balance",
          "iban",
          "capabilities",
          "createdAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerAddedNetworkDto": {
        "description": "The network the call added, and its status.",
        "properties": {
          "chain": {
            "enum": [
              "ETHEREUM",
              "BITCOIN",
              "SOLANA",
              "POLYGON",
              "AVALANCHE",
              "ARBITRUM",
              "OPTIMISM",
              "BASE"
            ],
            "example": "BASE",
            "type": "string"
          },
          "status": {
            "description": "PENDING_APPROVAL: every network added through the API awaits TCB approval before a payout may use it.",
            "enum": [
              "PENDING_APPROVAL",
              "ACTIVE",
              "RETIRED"
            ],
            "example": "PENDING_APPROVAL",
            "type": "string"
          }
        },
        "required": [
          "chain",
          "status"
        ],
        "type": "object"
      },
      "PartnerAddressInfoResponse": {
        "description": "What a wallet address is: its family, the networks it is valid on, the ones TCB sends on, and where it carries contract code.",
        "properties": {
          "checksumAddress": {
            "description": "The address in its canonical form — EIP-55 checksummed for an EVM address. Null when the address is valid on no network.",
            "example": "0x8Ba1f109551bD432803012645Ac136ddd64DBA72",
            "nullable": true,
            "type": "string"
          },
          "contractOn": {
            "description": "Reachable networks where the address carries contract code (a smart-contract wallet). Register such an address on one network at a time.",
            "items": {
              "enum": [
                "ETHEREUM",
                "BITCOIN",
                "SOLANA",
                "POLYGON",
                "AVALANCHE",
                "ARBITRUM",
                "OPTIMISM",
                "BASE"
              ],
              "type": "string"
            },
            "type": "array"
          },
          "family": {
            "description": "The address family (EVM), or null for a single-network or unrecognised address.",
            "enum": [
              "EVM"
            ],
            "example": "EVM",
            "nullable": true,
            "type": "string"
          },
          "reachableChains": {
            "description": "The subset of validChains TCB sends on — the networks a registration may name in instrument.networks.",
            "items": {
              "enum": [
                "ETHEREUM",
                "BITCOIN",
                "SOLANA",
                "POLYGON",
                "AVALANCHE",
                "ARBITRUM",
                "OPTIMISM",
                "BASE"
              ],
              "type": "string"
            },
            "type": "array"
          },
          "unknownOn": {
            "description": "Reachable networks where the address could not be checked for contract code. Treated like contractOn until a later check succeeds.",
            "items": {
              "enum": [
                "ETHEREUM",
                "BITCOIN",
                "SOLANA",
                "POLYGON",
                "AVALANCHE",
                "ARBITRUM",
                "OPTIMISM",
                "BASE"
              ],
              "type": "string"
            },
            "type": "array"
          },
          "validChains": {
            "description": "Every network whose address format accepts this address.",
            "items": {
              "enum": [
                "ETHEREUM",
                "BITCOIN",
                "SOLANA",
                "POLYGON",
                "AVALANCHE",
                "ARBITRUM",
                "OPTIMISM",
                "BASE"
              ],
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "family",
          "validChains",
          "reachableChains",
          "contractOn",
          "unknownOn",
          "checksumAddress"
        ],
        "type": "object"
      },
      "PartnerAttestationResponse": {
        "description": "One recorded attestation, exactly as received. Attestations are append-only: a newer one supersedes a stale one and nothing is ever edited or removed.",
        "properties": {
          "attestationId": {
            "description": "The attestation id.",
            "example": "b7f204e9-1c86-4a53-9e70-3d5f8b1c0a29",
            "format": "uuid",
            "type": "string"
          },
          "cddPerformedAt": {
            "description": "When you performed the due diligence.",
            "example": "2026-08-28T09:00:00.000Z",
            "format": "date-time",
            "type": "string"
          },
          "cddStandard": {
            "description": "The depth of due diligence you performed.",
            "enum": [
              "standard",
              "enhanced"
            ],
            "example": "standard",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "level": {
            "description": "The verification level the attestation supports.",
            "enum": [
              "RELIANCE"
            ],
            "example": "RELIANCE",
            "type": "string"
          },
          "payloadSha256": {
            "description": "A digest of the attestation exactly as received, so what was recorded can be checked against what you sent.",
            "example": "0f4c8b1d92a7e35604fd1c8a37b2905e6417da8c25f0b93e71c6482da05f3b9e",
            "type": "string"
          },
          "pepStatus": {
            "description": "Whether the customer is a politically exposed person. Null if you did not say.",
            "enum": [
              "none",
              "pep",
              "pep_related"
            ],
            "example": "none",
            "nullable": true,
            "type": "string"
          },
          "receivedAt": {
            "description": "When TCB recorded it.",
            "example": "2026-08-28T09:00:04.000Z",
            "format": "date-time",
            "type": "string"
          },
          "riskRating": {
            "description": "The customer risk rating your programme assigned. Null for an attestation recorded before this field existed.",
            "enum": [
              "low",
              "medium",
              "high"
            ],
            "example": "low",
            "nullable": true,
            "type": "string"
          },
          "screeningResult": {
            "description": "What your screening returned.",
            "enum": [
              "clear",
              "match_reviewed_cleared",
              "match"
            ],
            "example": "clear",
            "type": "string"
          },
          "subClientId": {
            "description": "The sub-client this attestation is about.",
            "example": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
            "format": "uuid",
            "type": "string"
          },
          "text": {
            "description": "The attestation wording, exactly as you sent it.",
            "example": "We have performed customer due diligence and screening on this customer under our agreed reliance programme.",
            "type": "string"
          },
          "verificationMethod": {
            "description": "How the customer's identity was verified under your programme. Null for an attestation recorded before this field existed.",
            "example": "documentary",
            "nullable": true,
            "type": "object"
          },
          "verificationResult": {
            "description": "The outcome of that verification. A sub-client is activated only on verified. Null for an attestation recorded before this field existed.",
            "enum": [
              "verified",
              "not_verified"
            ],
            "example": "verified",
            "nullable": true,
            "type": "string"
          },
          "verifierRef": {
            "description": "Your own file, case or vendor reference. TCB stores it and does not resolve it.",
            "example": "acme-case-88214",
            "nullable": true,
            "type": "object"
          },
          "version": {
            "description": "The version of the agreed wording you sent.",
            "example": "reliance-2026-09",
            "type": "string"
          }
        },
        "required": [
          "attestationId",
          "subClientId",
          "level",
          "text",
          "version",
          "cddPerformedAt",
          "cddStandard",
          "verificationMethod",
          "verificationResult",
          "verifierRef",
          "screeningResult",
          "pepStatus",
          "riskRating",
          "payloadSha256",
          "receivedAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerBeneficiaryCreatedResponse": {
        "description": "The destination you just registered, plus any non-blocking warnings about it.",
        "properties": {
          "addressFamily": {
            "description": "For a wallet whose address format is shared by several networks, the family: EVM. Null for a bank destination and for a single-network wallet (Bitcoin, Solana).",
            "enum": [
              "EVM"
            ],
            "example": "EVM",
            "nullable": true,
            "type": "string"
          },
          "beneficiaryId": {
            "description": "The destination id — what a future payout will name.",
            "example": "9b3e5c17-2a80-4f64-b1d9-6c0e8a4f2d53",
            "type": "string"
          },
          "chain": {
            "description": "The chain, for a wallet destination.",
            "example": null,
            "nullable": true,
            "type": "string"
          },
          "createdAt": {
            "description": "When the destination was registered.",
            "example": "2026-09-03T10:15:30.000Z",
            "format": "date-time",
            "type": "string"
          },
          "currency": {
            "description": "ISO 4217, for a bank destination.",
            "example": "EUR",
            "nullable": true,
            "type": "string"
          },
          "deletedAt": {
            "description": "Set once the destination has been removed. Removed destinations stay readable.",
            "example": null,
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "details": {
            "description": "The destination details exactly as stored, for your reconciliation.",
            "example": {
              "bicSwift": "COBADEFFXXX",
              "iban": "DE89370400440532013000"
            },
            "type": "object"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "extensibility": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerExtensibilityDto"
              }
            ],
            "description": "Whether networks can be added and, when not, why. Null for a bank destination.",
            "nullable": true
          },
          "extensible": {
            "description": "True when networks can be added to this destination: a self-hosted wallet whose ownership is proven and that carries no contract code on any of its active networks.",
            "example": false,
            "type": "boolean"
          },
          "instrumentId": {
            "description": "The registered instrument id under this destination.",
            "example": "1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97",
            "nullable": true,
            "type": "string"
          },
          "kind": {
            "description": "FIAT_BANK for a bank account, CRYPTO_ADDRESS for a wallet.",
            "enum": [
              "FIAT_BANK",
              "CRYPTO_ADDRESS"
            ],
            "example": "FIAT_BANK",
            "type": "string"
          },
          "label": {
            "description": "Your free-text label for this destination, if you set one.",
            "nullable": true,
            "type": "string"
          },
          "last4": {
            "description": "The last characters of the identifying number, for display.",
            "example": "3000",
            "nullable": true,
            "type": "string"
          },
          "name": {
            "description": "The payee name, as you registered it.",
            "example": "Acme Supplies GmbH",
            "type": "string"
          },
          "networks": {
            "description": "Every network this wallet destination has been opened on, retired ones included, oldest first. Empty for a bank destination. `chain` is the primary ACTIVE one.",
            "items": {
              "$ref": "#/components/schemas/PartnerBeneficiaryNetworkDto"
            },
            "type": "array"
          },
          "nickname": {
            "description": "Your display alias for this payee, if you set one.",
            "nullable": true,
            "type": "string"
          },
          "ownership": {
            "$ref": "#/components/schemas/PartnerOwnershipDto"
          },
          "rail": {
            "description": "The payment rail the destination clears on, for a bank destination.",
            "example": "SEPA",
            "nullable": true,
            "type": "string"
          },
          "reachableChains": {
            "description": "The networks this address could be paid on through TCB: the networks its format is valid on that TCB sends on. The list POST …/networks accepts. Empty for a bank destination.",
            "example": [
              "ETHEREUM",
              "POLYGON",
              "ARBITRUM"
            ],
            "items": {
              "enum": [
                "ETHEREUM",
                "BITCOIN",
                "SOLANA",
                "POLYGON",
                "AVALANCHE",
                "ARBITRUM",
                "OPTIMISM",
                "BASE"
              ],
              "type": "string"
            },
            "type": "array"
          },
          "screening": {
            "$ref": "#/components/schemas/PartnerBeneficiaryScreeningDto"
          },
          "status": {
            "description": "Where the destination stands: PENDING_APPROVAL (awaiting TCB approval — every API-registered destination starts here), HOLD (approved; the holding period runs until usableAt), BLOCKED (screening hit or operator block), or DELETED. There is no stored \"active\" state — usable is derived, and true only in HOLD once usableAt has passed.",
            "enum": [
              "PENDING_VERIFICATION",
              "PENDING_APPROVAL",
              "HOLD",
              "BLOCKED",
              "SUPERSEDED",
              "DELETED"
            ],
            "example": "PENDING_APPROVAL",
            "type": "string"
          },
          "usable": {
            "description": "True once — and only while — a payout may name this destination: approved, holding period elapsed, not blocked, not deleted.",
            "example": false,
            "type": "boolean"
          },
          "usableAt": {
            "description": "When the holding period ends and the destination becomes usable. Null until TCB approval sets the clock.",
            "example": null,
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "warnings": {
            "description": "Non-blocking signals about the destination you just registered. An empty array means nothing was flagged.",
            "items": {
              "$ref": "#/components/schemas/PartnerBeneficiaryWarningDto"
            },
            "type": "array"
          }
        },
        "required": [
          "beneficiaryId",
          "instrumentId",
          "name",
          "nickname",
          "kind",
          "currency",
          "rail",
          "chain",
          "label",
          "details",
          "last4",
          "status",
          "usable",
          "usableAt",
          "screening",
          "addressFamily",
          "networks",
          "reachableChains",
          "ownership",
          "extensible",
          "extensibility",
          "createdAt",
          "deletedAt",
          "disclosure",
          "warnings"
        ],
        "type": "object"
      },
      "PartnerBeneficiaryNetworkAddedResponse": {
        "description": "The destination after the network was added, plus the added network.",
        "properties": {
          "addressFamily": {
            "description": "For a wallet whose address format is shared by several networks, the family: EVM. Null for a bank destination and for a single-network wallet (Bitcoin, Solana).",
            "enum": [
              "EVM"
            ],
            "example": "EVM",
            "nullable": true,
            "type": "string"
          },
          "beneficiaryId": {
            "description": "The destination id — what a future payout will name.",
            "example": "9b3e5c17-2a80-4f64-b1d9-6c0e8a4f2d53",
            "type": "string"
          },
          "chain": {
            "description": "The chain, for a wallet destination.",
            "example": null,
            "nullable": true,
            "type": "string"
          },
          "createdAt": {
            "description": "When the destination was registered.",
            "example": "2026-09-03T10:15:30.000Z",
            "format": "date-time",
            "type": "string"
          },
          "currency": {
            "description": "ISO 4217, for a bank destination.",
            "example": "EUR",
            "nullable": true,
            "type": "string"
          },
          "deletedAt": {
            "description": "Set once the destination has been removed. Removed destinations stay readable.",
            "example": null,
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "details": {
            "description": "The destination details exactly as stored, for your reconciliation.",
            "example": {
              "bicSwift": "COBADEFFXXX",
              "iban": "DE89370400440532013000"
            },
            "type": "object"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "extensibility": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerExtensibilityDto"
              }
            ],
            "description": "Whether networks can be added and, when not, why. Null for a bank destination.",
            "nullable": true
          },
          "extensible": {
            "description": "True when networks can be added to this destination: a self-hosted wallet whose ownership is proven and that carries no contract code on any of its active networks.",
            "example": false,
            "type": "boolean"
          },
          "instrumentId": {
            "description": "The registered instrument id under this destination.",
            "example": "1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97",
            "nullable": true,
            "type": "string"
          },
          "kind": {
            "description": "FIAT_BANK for a bank account, CRYPTO_ADDRESS for a wallet.",
            "enum": [
              "FIAT_BANK",
              "CRYPTO_ADDRESS"
            ],
            "example": "FIAT_BANK",
            "type": "string"
          },
          "label": {
            "description": "Your free-text label for this destination, if you set one.",
            "nullable": true,
            "type": "string"
          },
          "last4": {
            "description": "The last characters of the identifying number, for display.",
            "example": "3000",
            "nullable": true,
            "type": "string"
          },
          "name": {
            "description": "The payee name, as you registered it.",
            "example": "Acme Supplies GmbH",
            "type": "string"
          },
          "network": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerAddedNetworkDto"
              }
            ],
            "description": "The network this call added."
          },
          "networks": {
            "description": "Every network this wallet destination has been opened on, retired ones included, oldest first. Empty for a bank destination. `chain` is the primary ACTIVE one.",
            "items": {
              "$ref": "#/components/schemas/PartnerBeneficiaryNetworkDto"
            },
            "type": "array"
          },
          "nickname": {
            "description": "Your display alias for this payee, if you set one.",
            "nullable": true,
            "type": "string"
          },
          "ownership": {
            "$ref": "#/components/schemas/PartnerOwnershipDto"
          },
          "rail": {
            "description": "The payment rail the destination clears on, for a bank destination.",
            "example": "SEPA",
            "nullable": true,
            "type": "string"
          },
          "reachableChains": {
            "description": "The networks this address could be paid on through TCB: the networks its format is valid on that TCB sends on. The list POST …/networks accepts. Empty for a bank destination.",
            "example": [
              "ETHEREUM",
              "POLYGON",
              "ARBITRUM"
            ],
            "items": {
              "enum": [
                "ETHEREUM",
                "BITCOIN",
                "SOLANA",
                "POLYGON",
                "AVALANCHE",
                "ARBITRUM",
                "OPTIMISM",
                "BASE"
              ],
              "type": "string"
            },
            "type": "array"
          },
          "screening": {
            "$ref": "#/components/schemas/PartnerBeneficiaryScreeningDto"
          },
          "status": {
            "description": "Where the destination stands: PENDING_APPROVAL (awaiting TCB approval — every API-registered destination starts here), HOLD (approved; the holding period runs until usableAt), BLOCKED (screening hit or operator block), or DELETED. There is no stored \"active\" state — usable is derived, and true only in HOLD once usableAt has passed.",
            "enum": [
              "PENDING_VERIFICATION",
              "PENDING_APPROVAL",
              "HOLD",
              "BLOCKED",
              "SUPERSEDED",
              "DELETED"
            ],
            "example": "PENDING_APPROVAL",
            "type": "string"
          },
          "usable": {
            "description": "True once — and only while — a payout may name this destination: approved, holding period elapsed, not blocked, not deleted.",
            "example": false,
            "type": "boolean"
          },
          "usableAt": {
            "description": "When the holding period ends and the destination becomes usable. Null until TCB approval sets the clock.",
            "example": null,
            "format": "date-time",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "beneficiaryId",
          "instrumentId",
          "name",
          "nickname",
          "kind",
          "currency",
          "rail",
          "chain",
          "label",
          "details",
          "last4",
          "status",
          "usable",
          "usableAt",
          "screening",
          "addressFamily",
          "networks",
          "reachableChains",
          "ownership",
          "extensible",
          "extensibility",
          "createdAt",
          "deletedAt",
          "disclosure",
          "network"
        ],
        "type": "object"
      },
      "PartnerBeneficiaryNetworkDto": {
        "description": "One network a wallet destination is opened on: its status and the screening verdict for the address on that network.",
        "properties": {
          "addedAt": {
            "description": "When the network was added (or last re-added).",
            "example": "2026-10-21T10:15:30.000Z",
            "format": "date-time",
            "type": "string"
          },
          "chain": {
            "description": "The network.",
            "enum": [
              "ETHEREUM",
              "BITCOIN",
              "SOLANA",
              "POLYGON",
              "AVALANCHE",
              "ARBITRUM",
              "OPTIMISM",
              "BASE"
            ],
            "example": "ARBITRUM",
            "type": "string"
          },
          "id": {
            "description": "The network row id.",
            "example": "4f0c2a91-7d3e-4b58-9a16-2e8d5c7b0f34",
            "nullable": true,
            "type": "string"
          },
          "screening": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerNetworkScreeningDto"
              }
            ],
            "description": "The screening verdict on this network. Null until the address is screened here.",
            "nullable": true
          },
          "status": {
            "description": "ACTIVE (a payout may be sent on this network once the destination is usable), PENDING_APPROVAL (you added it and it awaits TCB approval) or RETIRED (removed; kept for the record).",
            "enum": [
              "PENDING_APPROVAL",
              "ACTIVE",
              "RETIRED"
            ],
            "example": "ACTIVE",
            "type": "string"
          }
        },
        "required": [
          "id",
          "chain",
          "status",
          "screening",
          "addedAt"
        ],
        "type": "object"
      },
      "PartnerBeneficiaryResponse": {
        "description": "A destination in its current state: where it stands in the lifecycle, and whether a payout may name it right now.",
        "properties": {
          "addressFamily": {
            "description": "For a wallet whose address format is shared by several networks, the family: EVM. Null for a bank destination and for a single-network wallet (Bitcoin, Solana).",
            "enum": [
              "EVM"
            ],
            "example": "EVM",
            "nullable": true,
            "type": "string"
          },
          "beneficiaryId": {
            "description": "The destination id — what a future payout will name.",
            "example": "9b3e5c17-2a80-4f64-b1d9-6c0e8a4f2d53",
            "type": "string"
          },
          "chain": {
            "description": "The chain, for a wallet destination.",
            "example": null,
            "nullable": true,
            "type": "string"
          },
          "createdAt": {
            "description": "When the destination was registered.",
            "example": "2026-09-03T10:15:30.000Z",
            "format": "date-time",
            "type": "string"
          },
          "currency": {
            "description": "ISO 4217, for a bank destination.",
            "example": "EUR",
            "nullable": true,
            "type": "string"
          },
          "deletedAt": {
            "description": "Set once the destination has been removed. Removed destinations stay readable.",
            "example": null,
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "details": {
            "description": "The destination details exactly as stored, for your reconciliation.",
            "example": {
              "bicSwift": "COBADEFFXXX",
              "iban": "DE89370400440532013000"
            },
            "type": "object"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "extensibility": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerExtensibilityDto"
              }
            ],
            "description": "Whether networks can be added and, when not, why. Null for a bank destination.",
            "nullable": true
          },
          "extensible": {
            "description": "True when networks can be added to this destination: a self-hosted wallet whose ownership is proven and that carries no contract code on any of its active networks.",
            "example": false,
            "type": "boolean"
          },
          "instrumentId": {
            "description": "The registered instrument id under this destination.",
            "example": "1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97",
            "nullable": true,
            "type": "string"
          },
          "kind": {
            "description": "FIAT_BANK for a bank account, CRYPTO_ADDRESS for a wallet.",
            "enum": [
              "FIAT_BANK",
              "CRYPTO_ADDRESS"
            ],
            "example": "FIAT_BANK",
            "type": "string"
          },
          "label": {
            "description": "Your free-text label for this destination, if you set one.",
            "nullable": true,
            "type": "string"
          },
          "last4": {
            "description": "The last characters of the identifying number, for display.",
            "example": "3000",
            "nullable": true,
            "type": "string"
          },
          "name": {
            "description": "The payee name, as you registered it.",
            "example": "Acme Supplies GmbH",
            "type": "string"
          },
          "networks": {
            "description": "Every network this wallet destination has been opened on, retired ones included, oldest first. Empty for a bank destination. `chain` is the primary ACTIVE one.",
            "items": {
              "$ref": "#/components/schemas/PartnerBeneficiaryNetworkDto"
            },
            "type": "array"
          },
          "nickname": {
            "description": "Your display alias for this payee, if you set one.",
            "nullable": true,
            "type": "string"
          },
          "ownership": {
            "$ref": "#/components/schemas/PartnerOwnershipDto"
          },
          "rail": {
            "description": "The payment rail the destination clears on, for a bank destination.",
            "example": "SEPA",
            "nullable": true,
            "type": "string"
          },
          "reachableChains": {
            "description": "The networks this address could be paid on through TCB: the networks its format is valid on that TCB sends on. The list POST …/networks accepts. Empty for a bank destination.",
            "example": [
              "ETHEREUM",
              "POLYGON",
              "ARBITRUM"
            ],
            "items": {
              "enum": [
                "ETHEREUM",
                "BITCOIN",
                "SOLANA",
                "POLYGON",
                "AVALANCHE",
                "ARBITRUM",
                "OPTIMISM",
                "BASE"
              ],
              "type": "string"
            },
            "type": "array"
          },
          "screening": {
            "$ref": "#/components/schemas/PartnerBeneficiaryScreeningDto"
          },
          "status": {
            "description": "Where the destination stands: PENDING_APPROVAL (awaiting TCB approval — every API-registered destination starts here), HOLD (approved; the holding period runs until usableAt), BLOCKED (screening hit or operator block), or DELETED. There is no stored \"active\" state — usable is derived, and true only in HOLD once usableAt has passed.",
            "enum": [
              "PENDING_VERIFICATION",
              "PENDING_APPROVAL",
              "HOLD",
              "BLOCKED",
              "SUPERSEDED",
              "DELETED"
            ],
            "example": "PENDING_APPROVAL",
            "type": "string"
          },
          "usable": {
            "description": "True once — and only while — a payout may name this destination: approved, holding period elapsed, not blocked, not deleted.",
            "example": false,
            "type": "boolean"
          },
          "usableAt": {
            "description": "When the holding period ends and the destination becomes usable. Null until TCB approval sets the clock.",
            "example": null,
            "format": "date-time",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "beneficiaryId",
          "instrumentId",
          "name",
          "nickname",
          "kind",
          "currency",
          "rail",
          "chain",
          "label",
          "details",
          "last4",
          "status",
          "usable",
          "usableAt",
          "screening",
          "addressFamily",
          "networks",
          "reachableChains",
          "ownership",
          "extensible",
          "extensibility",
          "createdAt",
          "deletedAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerBeneficiaryScreeningDto": {
        "description": "Where screening stands for this destination.",
        "properties": {
          "status": {
            "description": "Where screening stands for this destination: UNSCREENED (not yet checked, or the checker was unavailable at registration — it is re-run before anything is ever sent), CLEAR, REVIEW (usable, but flagged on an open list — check it carefully), or HIT (blocked).",
            "enum": [
              "UNSCREENED",
              "CLEAR",
              "REVIEW",
              "HIT"
            ],
            "example": "CLEAR",
            "type": "string"
          }
        },
        "required": [
          "status"
        ],
        "type": "object"
      },
      "PartnerBeneficiaryWarningDto": {
        "description": "A non-blocking signal about a registration — a near-identical existing destination, or an open-list flag.",
        "properties": {
          "beneficiaryId": {
            "description": "The existing destination the warning compares against, when there is one.",
            "type": "string"
          },
          "beneficiaryName": {
            "description": "The name the existing destination is saved under.",
            "type": "string"
          },
          "code": {
            "description": "What the warning is: LOOKALIKE (very close to a destination you already hold — check it digit by digit), SCREENING_REVIEW (appears on an open list; usable, but every send to it is logged), or DUPLICATE_IN_ORG (the same details were registered under another payee of yours at the same moment — two registrations racing each other; keep one and remove the other).",
            "example": "LOOKALIKE",
            "type": "string"
          },
          "instrumentId": {
            "description": "The existing instrument the warning compares against, when there is one.",
            "type": "string"
          },
          "message": {
            "description": "A sentence you can surface as-is.",
            "type": "string"
          },
          "reason": {
            "description": "Which rule produced the warning.",
            "type": "string"
          }
        },
        "required": [
          "code",
          "message"
        ],
        "type": "object"
      },
      "PartnerChainStepOnchain": {
        "description": "The transaction behind a step.",
        "properties": {
          "txHash": {
            "description": "The step's transaction: the mint, the burn, the vault deposit or the vault withdrawal. Null until it lands, and on a queued redemption (see queue).",
            "example": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "txHash"
        ],
        "type": "object"
      },
      "PartnerChainStepQueue": {
        "description": "A queued redemption's place in the vault queue and what has been paid.",
        "properties": {
          "cancelTxHash": {
            "description": "The transaction that cancelled it, when you cancelled it.",
            "nullable": true,
            "type": "string"
          },
          "claimableAt": {
            "description": "The earliest time the vault may pay the request (its notice period). Null until the vault confirms the request.",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "fills": {
            "description": "What the vault has paid, part by part.",
            "items": {
              "$ref": "#/components/schemas/PartnerChainStepQueueFill"
            },
            "type": "array"
          },
          "onchainRequestId": {
            "description": "The request's position id in the vault's queue. Null until the vault confirms it.",
            "example": "42",
            "nullable": true,
            "type": "string"
          },
          "requestTxHash": {
            "description": "The transaction that placed the request in the queue.",
            "nullable": true,
            "type": "string"
          },
          "sharesEscrowed": {
            "description": "The shares held in the vault's queue for this request, at the vault's share scale.",
            "example": "398.120000000000000000000000",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "onchainRequestId",
          "claimableAt",
          "sharesEscrowed",
          "requestTxHash",
          "cancelTxHash",
          "fills"
        ],
        "type": "object"
      },
      "PartnerChainStepQueueFill": {
        "description": "One part of a queued redemption the vault paid.",
        "properties": {
          "bookedAt": {
            "description": "When the fill was booked to your sub-account. Null while it is being booked.",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "tokens": {
            "description": "tcbUSD paid by this fill, as a decimal string.",
            "example": "400",
            "type": "string"
          },
          "txHash": {
            "description": "The transaction in which the vault paid this part.",
            "example": "0x8c41…",
            "type": "string"
          }
        },
        "required": [
          "txHash",
          "tokens",
          "bookedAt"
        ],
        "type": "object"
      },
      "PartnerChainStepResponse": {
        "description": "One step of the tokenised deposit chain — a mint, a token redemption, a subscription, or an instant or queued vault redemption — in its current state. Every step answers with this shape.",
        "properties": {
          "amount": {
            "description": "What you asked to move, as a decimal string: fiat for a mint, tcbUSD for every other step. Normalised: a submitted '1000.00' comes back as '1000'.",
            "example": "1000",
            "type": "string"
          },
          "createdAt": {
            "description": "When you submitted the step.",
            "format": "date-time",
            "type": "string"
          },
          "currency": {
            "description": "The currency of the step.",
            "example": "USD",
            "type": "string"
          },
          "custody": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerCustodyRef"
              }
            ],
            "description": "Where the tcbUSD and the shares are held for you."
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "fiatAccountId": {
            "description": "The fiat account debited by a mint or credited by a token redemption. Null on the vault steps.",
            "format": "uuid",
            "nullable": true,
            "type": "string"
          },
          "id": {
            "description": "The step id. Fetch it again with GET on the same path plus /{id}.",
            "example": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "The idempotency key you sent, echoed back.",
            "example": "acme-step-2026-10-12-0001",
            "type": "string"
          },
          "onchain": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerChainStepOnchain"
              }
            ],
            "description": "The transaction behind the step."
          },
          "queue": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerChainStepQueue"
              }
            ],
            "description": "The queue position and fills of a queued redemption. Null on every other step.",
            "nullable": true
          },
          "replayed": {
            "description": "True when this body is the stored result of an earlier call under the same key. Money moved once.",
            "example": false,
            "type": "boolean"
          },
          "settledAt": {
            "description": "When the step reached a final state. Null until it does.",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "shares": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerChainStepShares"
              }
            ],
            "description": "The vault shares the step moved."
          },
          "status": {
            "description": "Where the step stands. SETTLED: done. FAILED: nothing moved. QUEUED (queued redemptions only): the shares wait in the vault queue. CANCELLED (queued redemptions only): cancelled before anything was paid, the shares are back. FAILED_PENDING_COMPENSATION and COMPENSATED: money may have moved and TCB is resolving it — do not retry with a new key.",
            "enum": [
              "PENDING",
              "EXECUTING_ONCHAIN",
              "QUEUED",
              "SETTLED",
              "CANCELLED",
              "FAILED",
              "FAILED_PENDING_COMPENSATION",
              "COMPENSATED"
            ],
            "example": "SETTLED",
            "type": "string"
          },
          "subAccountId": {
            "description": "The sub-account the step is booked to.",
            "format": "uuid",
            "type": "string"
          },
          "token": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerTokenRef"
              }
            ],
            "description": "The token the step moves."
          },
          "tokens": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerChainStepTokens"
              }
            ],
            "description": "The tcbUSD the step moved."
          },
          "type": {
            "description": "Which step this is.",
            "enum": [
              "TOKEN_MINT",
              "TOKEN_REDEMPTION",
              "SHARE_SUBSCRIPTION",
              "SHARE_REDEMPTION",
              "SHARE_REDEMPTION_REQUEST"
            ],
            "example": "TOKEN_MINT",
            "type": "string"
          },
          "vault": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerVaultRef"
              }
            ],
            "description": "The vault, on the vault steps. Null on a mint or a token redemption.",
            "nullable": true
          }
        },
        "required": [
          "id",
          "type",
          "status",
          "idempotencyKey",
          "replayed",
          "subAccountId",
          "currency",
          "amount",
          "token",
          "vault",
          "custody",
          "fiatAccountId",
          "tokens",
          "shares",
          "queue",
          "onchain",
          "settledAt",
          "createdAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerChainStepShares": {
        "description": "The vault shares a step moved.",
        "properties": {
          "moved": {
            "description": "The vault shares this step moved, as a decimal string at the vault's own share scale: received by a subscription, burned by a redemption. Null on the token steps, and until a vault step has settled.",
            "example": "987.654321000000000000000000",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "moved"
        ],
        "type": "object"
      },
      "PartnerChainStepTokens": {
        "description": "The tcbUSD a step moved.",
        "properties": {
          "moved": {
            "description": "The tcbUSD this step moved, as a decimal string: minted, burned, put into the vault, or paid out of it. On a queued redemption, what has been paid so far. Null until the step has moved anything.",
            "example": "1000",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "moved"
        ],
        "type": "object"
      },
      "PartnerConversionCommission": {
        "description": "The commission a conversion is charged: a charge to you, in the currency it is taken in.",
        "properties": {
          "amount": {
            "description": "The commission, as a decimal string.",
            "example": "2.5",
            "type": "string"
          },
          "currency": {
            "description": "The currency the commission is taken in: one of the two currencies of the conversion.",
            "example": "USD",
            "type": "string"
          }
        },
        "required": [
          "amount",
          "currency"
        ],
        "type": "object"
      },
      "PartnerConversionFrom": {
        "description": "The sell side: what you asked to sell, what actually filled, and what did not.",
        "properties": {
          "currency": {
            "description": "The currency sold.",
            "example": "USDC",
            "type": "string"
          },
          "filledAmount": {
            "description": "What actually sold. Equal to requestedAmount on a whole fill. Null until the order settles.",
            "example": "1000",
            "nullable": true,
            "type": "string"
          },
          "requestedAmount": {
            "description": "What you asked to sell, as a decimal string. Normalised, not echoed verbatim: a submitted '1000.00' comes back as '1000'.",
            "example": "1000",
            "type": "string"
          },
          "unfilledAmount": {
            "description": "What did not sell: requestedAmount minus filledAmount. '0' on a whole fill. Null until the order settles.",
            "example": "0",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "currency",
          "requestedAmount",
          "filledAmount",
          "unfilledAmount"
        ],
        "type": "object"
      },
      "PartnerConversionFromQuoted": {
        "description": "The sell side of a conversion quote.",
        "properties": {
          "amount": {
            "description": "What the quote sells, as a decimal string.",
            "example": "1000",
            "type": "string"
          },
          "currency": {
            "description": "The currency sold.",
            "example": "USDC",
            "type": "string"
          }
        },
        "required": [
          "currency",
          "amount"
        ],
        "type": "object"
      },
      "PartnerConversionQuoteRate": {
        "description": "The rate a conversion quote holds, and how it was produced.",
        "properties": {
          "note": {
            "description": "What pricingModel means for this number, in words.",
            "example": "This rate came from a venue that prices independently of TCB.",
            "type": "string"
          },
          "pricingModel": {
            "description": "How this rate was produced. Always MARKET: a conversion is only ever quoted by a venue that prices independently of TCB.",
            "enum": [
              "MARKET"
            ],
            "example": "MARKET",
            "type": "string"
          },
          "quoted": {
            "description": "The quoted price, as units of the buy currency per one unit of the sell currency.",
            "example": "0.9999",
            "type": "string"
          }
        },
        "required": [
          "quoted",
          "pricingModel",
          "note"
        ],
        "type": "object"
      },
      "PartnerConversionQuoteRequestDto": {
        "description": "A conversion to quote: the same fields as the conversion, without the idempotency key.",
        "properties": {
          "amount": {
            "description": "Amount of fromCurrency to sell, as a decimal string. Never a float — a JSON number cannot represent every decimal amount exactly, and money is the last place to discover that. Must not carry more fractional digits than fromCurrency settles at (USD: 2, USDC: 6).",
            "example": "1000.00",
            "type": "string"
          },
          "fromCurrency": {
            "description": "Currency to sell. You must hold an account in it.",
            "example": "USDC",
            "type": "string"
          },
          "sourceAccountId": {
            "description": "Account to debit. Omitted, your single active account in fromCurrency is used; ambiguity is refused rather than guessed. Every active account of yours in fromCurrency counts, including the account your crypto deposit address credits, so once you hold more than one this field is effectively mandatory — otherwise the request answers 409 CONVERSION_ACCOUNT_AMBIGUOUS with details.accountIds naming each candidate.",
            "example": "4d80f3b6-9a17-4c25-8e93-0b6d1f7a3c58",
            "format": "uuid",
            "type": "string"
          },
          "targetAccountId": {
            "description": "Account to credit. Omitted, your single active account in toCurrency is used; ambiguity is refused rather than guessed. Once you hold more than one account in toCurrency this field is effectively mandatory — otherwise the request answers 409 CONVERSION_ACCOUNT_AMBIGUOUS.",
            "example": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
            "format": "uuid",
            "type": "string"
          },
          "toAccountId": {
            "description": "Where the converted amount ends up: a fiat account in toCurrency, either one of your own or one of your sub-clients'. Your own account: the conversion is credited to it directly. A sub-client's account: the conversion is credited to your own account in toCurrency (targetAccountId, or your single active one) and moved on to the sub-client in the same step; the response carries the transferId of that move. Needs a key holding both trade:execute and transfer:execute. The sub-client must be able to receive.",
            "example": "9c3e5a1f-2b7d-4e60-8a94-6f1d0c2b7e35",
            "format": "uuid",
            "type": "string"
          },
          "toCurrency": {
            "description": "Currency to buy. You must hold an account in it.",
            "example": "USD",
            "type": "string"
          }
        },
        "required": [
          "fromCurrency",
          "toCurrency",
          "amount"
        ],
        "type": "object"
      },
      "PartnerConversionQuoteResponse": {
        "description": "A conversion quote: the rate a market venue quotes, the commission at that rate, what the conversion would credit, and until when a conversion naming quoteId executes at it.",
        "properties": {
          "commission": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerConversionCommission"
              }
            ],
            "description": "The commission the conversion will be charged at this rate. Null when it is charged none.",
            "nullable": true
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "expiresAt": {
            "description": "When the quote stops being usable: the venue's own quote window, and never more than 60 seconds. A conversion naming it after this is refused with QUOTE_EXPIRED.",
            "example": "2026-10-30T10:15:58.000Z",
            "format": "date-time",
            "type": "string"
          },
          "from": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerConversionFromQuoted"
              }
            ],
            "description": "The sell side."
          },
          "networkFee": {
            "description": "Always null: TCB covers any network (gas) cost of a conversion and never charges it, so there is no network fee to report. Null does not mean the cost was zero.",
            "example": null,
            "nullable": true,
            "type": "string"
          },
          "quoteId": {
            "description": "Name this as quoteId on POST /conversions to execute at this quote.",
            "example": "5e2c9a17-8b40-4d63-a1f8-3c7e0b9d2f46",
            "format": "uuid",
            "type": "string"
          },
          "rate": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerConversionQuoteRate"
              }
            ],
            "description": "The quoted rate."
          },
          "receiveAmount": {
            "description": "What the conversion credits at the quoted rate, net of the commission where the commission is taken from the currency you receive, as a decimal string.",
            "example": "997.40",
            "type": "string"
          },
          "toCurrency": {
            "description": "The currency bought.",
            "example": "USD",
            "type": "string"
          }
        },
        "required": [
          "quoteId",
          "from",
          "toCurrency",
          "rate",
          "commission",
          "receiveAmount",
          "networkFee",
          "expiresAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerConversionRate": {
        "description": "The rate the conversion filled at, and how that rate was produced. Always read pricingModel before presenting the number anywhere.",
        "properties": {
          "executed": {
            "description": "The price the conversion actually filled at, as units of the buy currency per one unit of the sell currency. Null until the order settles.",
            "example": "0.9998",
            "nullable": true,
            "type": "string"
          },
          "note": {
            "description": "What pricingModel means for this number, in words. Null until the fill establishes which venue priced it.",
            "example": "This rate came from a venue that prices independently of TCB.",
            "nullable": true,
            "type": "string"
          },
          "pricingModel": {
            "description": "How this rate was produced. MARKET means a venue priced it independently of TCB — the only way a conversion is filled: when no such venue can price the pair the request is refused (503 PRICING_UNAVAILABLE) rather than priced internally. SIMULATED appears only on conversions settled before 2026-09-06 and means TCB generated the rate from a fixed internal table; it is not a market rate — never present, store or report it as one. Null until the fill establishes which venue priced it.",
            "enum": [
              "MARKET",
              "SIMULATED"
            ],
            "example": "MARKET",
            "nullable": true,
            "type": "string"
          },
          "quoted": {
            "description": "The price quoted before the order was placed. Null when none was taken.",
            "example": "0.9999",
            "nullable": true,
            "type": "string"
          },
          "quotedExpiresAt": {
            "description": "When that quote stopped being usable.",
            "example": "2026-09-02T10:15:58.000Z",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "executed",
          "quoted",
          "quotedExpiresAt",
          "pricingModel",
          "note"
        ],
        "type": "object"
      },
      "PartnerConversionResponse": {
        "description": "A conversion in its current state: what sold, what it bought, and at what rate.",
        "properties": {
          "commission": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerConversionCommission"
              }
            ],
            "description": "The commission this conversion was charged, as booked when it settled. Null until it settles, and null on a settled conversion that was charged none. Where it is taken from the currency you receive, to.amount is already net of it.",
            "nullable": true
          },
          "conversionId": {
            "description": "The conversion id. Fetch this conversion again with GET /conversions/{id}.",
            "example": "6a4d0f38-7c15-42be-9038-4b7e1c6a2d59",
            "type": "string"
          },
          "createdAt": {
            "description": "When you submitted the conversion.",
            "example": "2026-09-02T10:15:28.000Z",
            "format": "date-time",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "from": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerConversionFrom"
              }
            ],
            "description": "The sell side."
          },
          "idempotencyKey": {
            "description": "The idempotency key you sent, echoed back.",
            "example": "acme-conversion-2026-08-31-0001",
            "type": "string"
          },
          "networkFee": {
            "description": "Always null: TCB covers any network (gas) cost of a conversion and never charges it, so there is no network fee to report. Null does not mean the cost was zero.",
            "example": null,
            "nullable": true,
            "type": "string"
          },
          "rate": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerConversionRate"
              }
            ],
            "description": "The rate this conversion filled at, and how it was produced."
          },
          "replayed": {
            "description": "True when this body is the stored result of an earlier call under the same key. Money moved once.",
            "example": false,
            "type": "boolean"
          },
          "settledAt": {
            "description": "When the conversion settled. Null until it does.",
            "example": "2026-09-02T10:15:33.000Z",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "status": {
            "description": "Where the conversion stands. SETTLED means both accounts moved. FAILED means nothing moved. FAILED_PENDING_COMPENSATION and COMPENSATED mean an order moved money and a TCB operator is resolving it — do not retry with a new key.",
            "enum": [
              "PENDING",
              "EXECUTING_ONCHAIN",
              "SETTLED",
              "FAILED",
              "FAILED_PENDING_COMPENSATION",
              "COMPENSATED"
            ],
            "example": "SETTLED",
            "type": "string"
          },
          "to": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerConversionTo"
              }
            ],
            "description": "The buy side."
          },
          "toAccountId": {
            "description": "The account you named as toAccountId, where the converted amount ends up. Null when you named none.",
            "example": "9c3e5a1f-2b7d-4e60-8a94-6f1d0c2b7e35",
            "format": "uuid",
            "nullable": true,
            "type": "string"
          },
          "tradeOrderId": {
            "description": "The order this conversion drove. Quote it in a support request.",
            "example": "e5c17a03-9d42-4b68-8f31-0a7c2e6b4d95",
            "nullable": true,
            "type": "string"
          },
          "transferId": {
            "description": "The transfer that moved the converted amount to a sub-client's account named as toAccountId, as listed by GET /transfers. Null when no move was needed (no toAccountId, or one of your own accounts) and until the conversion settles.",
            "example": "2f8b6d14-7a3c-4e91-b5d0-8c1e4f7a9b26",
            "format": "uuid",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "conversionId",
          "status",
          "idempotencyKey",
          "replayed",
          "from",
          "to",
          "rate",
          "commission",
          "networkFee",
          "tradeOrderId",
          "toAccountId",
          "transferId",
          "settledAt",
          "createdAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerConversionTo": {
        "description": "The buy side: the currency bought and the amount credited.",
        "properties": {
          "amount": {
            "description": "What the fill bought and credited to the target account, as a decimal string. Null until the order settles.",
            "example": "999.80",
            "nullable": true,
            "type": "string"
          },
          "currency": {
            "description": "The currency bought.",
            "example": "USD",
            "type": "string"
          }
        },
        "required": [
          "currency",
          "amount"
        ],
        "type": "object"
      },
      "PartnerCryptoBalanceResponse": {
        "description": "The amount of one asset an account holds.",
        "properties": {
          "asset": {
            "description": "The asset symbol.",
            "example": "USDC",
            "type": "string"
          },
          "balance": {
            "description": "The amount held, as a decimal string.",
            "example": "250.5",
            "type": "string"
          }
        },
        "required": [
          "asset",
          "balance"
        ],
        "type": "object"
      },
      "PartnerCryptoDepositAddressResponse": {
        "description": "Your deposit address for one asset on one chain, and the account arrivals to it are credited to. Static: the same call always returns the same address.",
        "properties": {
          "accountId": {
            "description": "The account arrivals are credited to. Read its balance on GET /accounts/{id}.",
            "example": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
            "type": "string"
          },
          "address": {
            "description": "The deposit address itself. Static: every call for the same asset and chain returns this same address.",
            "example": "0x5c1f0a2b3d4e5f60718293a4b5c6d7e8f9012345",
            "type": "string"
          },
          "addressId": {
            "description": "The id of this address registration.",
            "example": "9d2c6a4e-73b8-4e8b-a35c-4692b0f11d70",
            "type": "string"
          },
          "asset": {
            "description": "The asset the address accepts.",
            "example": "USDC",
            "type": "string"
          },
          "chain": {
            "description": "The chain the address lives on.",
            "example": "ARBITRUM",
            "type": "string"
          },
          "createdAt": {
            "description": "When the address was first issued.",
            "format": "date-time",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          }
        },
        "required": [
          "addressId",
          "address",
          "chain",
          "asset",
          "accountId",
          "createdAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerCryptoDepositResponse": {
        "description": "One recorded on-chain arrival at your deposit address, in its current state — credited, or recorded without a credit where the asset is not accepted.",
        "properties": {
          "amount": {
            "description": "The amount that arrived, as a decimal string at the asset's own scale.",
            "example": "1000",
            "type": "string"
          },
          "asset": {
            "description": "The asset that arrived.",
            "example": "USDC",
            "type": "string"
          },
          "chain": {
            "description": "The chain it arrived on.",
            "example": "ARBITRUM",
            "type": "string"
          },
          "creditedAccountId": {
            "description": "The account the funds were credited to, once status is CREDITED; null before that, and on a FAILED record.",
            "example": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
            "nullable": true,
            "type": "object"
          },
          "creditedAt": {
            "description": "When the credit was applied; null until then.",
            "nullable": true,
            "type": "object"
          },
          "cryptoDepositId": {
            "description": "The deposit id. Stable across webhook replays of the same transfer.",
            "example": "2b7e1c6a-2d59-46a4-8f38-7c1542be9038",
            "type": "string"
          },
          "detectedAt": {
            "description": "When TCB first recorded the arrival.",
            "format": "date-time",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "status": {
            "description": "DETECTED and CONFIRMING are transient and usually invisible — arrivals are reported to TCB already confirmed, so a deposit normally first appears as CREDITED. FAILED means the arrival was recorded but could not be credited (for example an asset the pilot does not accept); it is never applied to a balance, and resolving it is a manual step on TCB’s side — contact TCB.",
            "enum": [
              "DETECTED",
              "CONFIRMING",
              "CREDITED",
              "FAILED"
            ],
            "example": "CREDITED",
            "type": "string"
          },
          "transferIndex": {
            "description": "The transfer’s position within its transaction, when one transaction carried several transfers. Each position is a distinct deposit; null when the transaction carried one transfer.",
            "example": "2",
            "nullable": true,
            "type": "object"
          },
          "txHash": {
            "description": "The transaction hash of the on-chain transfer — the deposit’s identity.",
            "example": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396",
            "type": "object"
          }
        },
        "required": [
          "cryptoDepositId",
          "status",
          "asset",
          "chain",
          "amount",
          "txHash",
          "transferIndex",
          "creditedAccountId",
          "detectedAt",
          "creditedAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerCustodyRef": {
        "description": "Where the shares are held for you.",
        "properties": {
          "mode": {
            "description": "How the position is held. TCB_SUBACCOUNT means TCB custodies it for you in the one TCB wallet assigned to you: you hold no keys, and your shares and any tcbUSD you hold are book entries against that wallet.",
            "example": "TCB_SUBACCOUNT",
            "type": "string"
          },
          "walletAddress": {
            "description": "The wallet TCB holds your shares in.",
            "example": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094",
            "type": "string"
          }
        },
        "required": [
          "mode",
          "walletAddress"
        ],
        "type": "object"
      },
      "PartnerDepositOnchain": {
        "description": "The transactions behind the deposit, once each leg has landed.",
        "properties": {
          "depositTxHash": {
            "description": "The transaction that moved the underlying into the vault. Null until it lands.",
            "example": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396",
            "nullable": true,
            "type": "string"
          },
          "mintTxHash": {
            "description": "The transaction that minted the underlying for the deposit. Null until it lands.",
            "example": "0x9d20b7e548c1f36a0742e9bd35c108af62d497130ba85e6c2f9d40718ac35be2",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "depositTxHash",
          "mintTxHash"
        ],
        "type": "object"
      },
      "PartnerDepositResponse": {
        "description": "A deposit in its current state: what was requested, what settled, where the shares sit and the transactions that put them there.",
        "properties": {
          "amount": {
            "description": "What was deposited, as a decimal string. Normalised, not echoed verbatim: a submitted '1000.00' comes back as '1000'.",
            "example": "1000",
            "type": "string"
          },
          "createdAt": {
            "description": "When you submitted the deposit.",
            "example": "2026-09-02T10:15:28.000Z",
            "format": "date-time",
            "type": "string"
          },
          "currency": {
            "description": "The currency deposited.",
            "example": "USD",
            "type": "string"
          },
          "custody": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerCustodyRef"
              }
            ],
            "description": "Where the shares are held for you."
          },
          "depositId": {
            "description": "The deposit id. Fetch this deposit again with GET /deposits/{id}.",
            "example": "2f6c9a41-3e58-4b70-9d12-6a8f0c3e5b71",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "idempotencyKey": {
            "description": "The idempotency key you sent, echoed back.",
            "example": "acme-deposit-2026-08-27-0001",
            "type": "string"
          },
          "onchain": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDepositOnchain"
              }
            ],
            "description": "The transactions behind the deposit."
          },
          "replayed": {
            "description": "True when this body is the stored result of an earlier call under the same key. Money moved once.",
            "example": false,
            "type": "boolean"
          },
          "settledAt": {
            "description": "When the deposit settled. Null until it does.",
            "example": "2026-09-02T10:15:34.000Z",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "shares": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDepositShares"
              }
            ],
            "description": "Your share position after this deposit."
          },
          "status": {
            "description": "Where the deposit stands. SETTLED means your shares are minted. FAILED means nothing was charged. FAILED_PENDING_COMPENSATION and COMPENSATED mean money moved and a TCB operator is resolving it — do not retry with a new key.",
            "enum": [
              "PENDING",
              "EXECUTING_ONCHAIN",
              "SETTLED",
              "FAILED",
              "FAILED_PENDING_COMPENSATION",
              "COMPENSATED"
            ],
            "example": "SETTLED",
            "type": "string"
          },
          "vault": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerVaultRef"
              }
            ],
            "description": "The vault the shares were bought in."
          }
        },
        "required": [
          "depositId",
          "status",
          "idempotencyKey",
          "replayed",
          "currency",
          "amount",
          "vault",
          "custody",
          "shares",
          "onchain",
          "settledAt",
          "createdAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerDepositShares": {
        "description": "Your share position after the deposit.",
        "properties": {
          "balance": {
            "description": "The sub-account's whole share balance after this deposit, as a decimal string at the vault's own share scale. Null when the balance could not be read — a settled deposit is never failed over an unavailable read, so retry the fetch rather than the deposit.",
            "example": "1024.518330000000000000000000",
            "nullable": true,
            "type": "string"
          },
          "minted": {
            "description": "The vault shares this deposit received, as a decimal string at the vault's own share scale: the same figure as shares on the deposit list. Null unless the deposit has settled.",
            "example": "999.876543210000000000000000",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "balance",
          "minted"
        ],
        "type": "object"
      },
      "PartnerDisclosureDto": {
        "description": "The pilot disclosure. Identical on every response that carries it, and versioned so you can tell when its wording changed.",
        "properties": {
          "items": {
            "description": "The disclosure in full, one statement per entry.",
            "example": [
              "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
              "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
              "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
              "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
              "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
              "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
              "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "summary": {
            "description": "The disclosure in one sentence.",
            "example": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
            "type": "string"
          },
          "version": {
            "description": "The disclosure version. It changes only when the wording below changes.",
            "example": "2026-10-27",
            "type": "string"
          }
        },
        "required": [
          "version",
          "summary",
          "items"
        ],
        "type": "object"
      },
      "PartnerEarnedPeriod": {
        "description": "What a position earned over a period of whole UTC days, with the deposits and withdrawals inside it.",
        "properties": {
          "deposited": {
            "description": "Deposits inside the period.",
            "example": "0",
            "nullable": true,
            "type": "string"
          },
          "earned": {
            "description": "What the position earned over the period: value at the end minus value at the start, plus withdrawals and minus deposits inside it. Null when not observed.",
            "example": "0.810000",
            "nullable": true,
            "type": "string"
          },
          "from": {
            "description": "First day of the period (UTC, inclusive).",
            "example": "2026-10-01",
            "type": "string"
          },
          "notObserved": {
            "description": "Why a figure on this object is null. NO_PRICED_OBSERVATION: no observed vault share price to value the position at. FLOW_NOT_VALUED: a movement on this sub-account carries no asset figure. PERIOD_ENDPOINT_NOT_OBSERVED: a day bounding the period has no observed share price. EVIDENCE_INCONSISTENT: this sub-account's records disagree and TCB has been alerted; its share figures still stand. HISTORY_TOO_LONG: the sub-account has more ledger entries than one report folds, so its earned figures are withheld; its share figures still stand. Empty when every figure is present. Null always means not observed, never zero.",
            "example": [],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "to": {
            "description": "Last day of the period (UTC, inclusive).",
            "example": "2026-10-07",
            "type": "string"
          },
          "withdrawn": {
            "description": "Withdrawals inside the period.",
            "example": "0",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "from",
          "to",
          "earned",
          "deposited",
          "withdrawn",
          "notObserved"
        ],
        "type": "object"
      },
      "PartnerErrorResponse": {
        "description": "Every non-2xx response. `code` is a stable SCREAMING_SNAKE identifier from the client API error catalogue; `details` carries machine-readable context (decimal strings, never base units, never exponential notation, only the caller's own data) and its keys are additionally promoted to the top level.",
        "properties": {
          "code": {
            "description": "Branch on this, never on `message`. A stable SCREAMING_SNAKE identifier; the codes a given route can answer with are listed in that response's description.",
            "example": "IDEMPOTENCY_KEY_REUSED",
            "type": "string"
          },
          "details": {
            "additionalProperties": true,
            "description": "Machine-readable context for this refusal — only your own data, amounts as decimal strings. Its keys also appear at the top level of the body.",
            "example": {
              "idempotencyKey": "acme-deposit-2026-08-27-0001"
            },
            "type": "object"
          },
          "error": {
            "description": "The HTTP reason phrase.",
            "example": "Conflict",
            "type": "string"
          },
          "message": {
            "description": "What went wrong, in words. Written for a person reading a log.",
            "example": "This Idempotency-Key was already used with different parameters. Use a new key for a different request, or resend the original parameters to replay the first result.",
            "type": "string"
          },
          "method": {
            "description": "The method that was called.",
            "example": "POST",
            "type": "string"
          },
          "path": {
            "description": "The path that was called.",
            "example": "/api/partner/v1/deposits",
            "type": "string"
          },
          "statusCode": {
            "description": "The HTTP status, repeated in the body so a logged payload is self-contained.",
            "example": 409,
            "type": "number"
          },
          "timestamp": {
            "description": "When the refusal was produced.",
            "example": "2026-09-02T10:15:30.000Z",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "statusCode",
          "timestamp",
          "path",
          "method",
          "message"
        ],
        "type": "object"
      },
      "PartnerExtensibilityDto": {
        "properties": {
          "extensible": {
            "description": "True when networks can be added to this destination. The same value as `extensible`.",
            "example": false,
            "type": "boolean"
          },
          "reason": {
            "description": "Why networks cannot be added, null when they can. OWNERSHIP_NOT_PROVEN: submit an ownership proof first. EXCHANGE_OR_VASP_HOSTED: an exchange-hosted address is per network; register it again for another network. CONTRACT_CODE_ON_NETWORK: the address carries contract code on one of its active networks. NO_ADDRESS_FAMILY: the address lives on a single network.",
            "enum": [
              "OWNERSHIP_NOT_PROVEN",
              "EXCHANGE_OR_VASP_HOSTED",
              "CONTRACT_CODE_ON_NETWORK",
              "NO_ADDRESS_FAMILY"
            ],
            "example": "OWNERSHIP_NOT_PROVEN",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "extensible",
          "reason"
        ],
        "type": "object"
      },
      "PartnerMeResponse": {
        "description": "The principal your API key authenticates as, and the sub-client it would act for if you sent x-on-behalf-of.",
        "properties": {
          "clientAccountId": {
            "description": "Your own client account — the root of your tree. Unchanged by x-on-behalf-of.",
            "example": "3a7e5c91-0d24-4b6f-8e13-5c9a2f7b1d04",
            "nullable": true,
            "type": "string"
          },
          "environment": {
            "description": "The environment tag the key was issued under, taken from its prefix: test for sandbox keys, stg for staging keys.",
            "enum": [
              "test",
              "stg"
            ],
            "example": "test",
            "type": "string"
          },
          "keyPrefix": {
            "description": "The first twelve characters of the key. Non-secret: use it to tell which key a running integration is holding, in logs and support requests.",
            "example": "test_A7fQ2xM",
            "type": "string"
          },
          "name": {
            "description": "Your display name as TCB holds it.",
            "example": "Acme Payments",
            "type": "string"
          },
          "partnerId": {
            "description": "Your principal id. Stable for the life of the relationship.",
            "example": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
            "type": "string"
          },
          "principalType": {
            "description": "The principal this request would ACT AS. PARTNER normally; SUB_CLIENT when you sent x-on-behalf-of, in which case subClientId names the node.",
            "enum": [
              "PARTNER",
              "SUB_CLIENT"
            ],
            "example": "PARTNER",
            "type": "string"
          },
          "scopes": {
            "description": "What this key is allowed to do. A route refuses with 403 INSUFFICIENT_SCOPE if the scope it requires is not in this list.",
            "example": [
              "position:read",
              "transaction:read",
              "vault:deposit",
              "vault:withdraw"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "subClientId": {
            "description": "The sub-client this request would act as, or null when you called without x-on-behalf-of.",
            "example": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
            "nullable": true,
            "type": "string"
          },
          "subtreeRestricted": {
            "description": "Whether this key may act for only some of your sub-clients. False — the default — means it may act for any of them.",
            "example": false,
            "type": "boolean"
          }
        },
        "required": [
          "partnerId",
          "name",
          "principalType",
          "environment",
          "scopes",
          "keyPrefix",
          "clientAccountId",
          "subClientId",
          "subtreeRestricted"
        ],
        "type": "object"
      },
      "PartnerNettingAgreementResponse": {
        "description": "A netting agreement between you and one other member, with your open position under it.",
        "properties": {
          "acceptedAt": {
            "format": "date-time",
            "nullable": true,
            "type": "object"
          },
          "counterparty": {
            "$ref": "#/components/schemas/NettingPartyDto"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "currency": {
            "example": "USD",
            "type": "string"
          },
          "declineReason": {
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "declinedAt": {
            "format": "date-time",
            "nullable": true,
            "type": "object"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "endReason": {
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "endedAt": {
            "format": "date-time",
            "nullable": true,
            "type": "object"
          },
          "id": {
            "example": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "type": "string"
          },
          "networkLabel": {
            "example": "CommaNet",
            "type": "string"
          },
          "pendingCutApprovalRequestId": {
            "description": "Set while a cut of this set is waiting on the net payer’s second approver. A cut made with an API key never waits — one the approval rules would hold is refused with SETTLEMENT_REQUIRES_APPROVAL — but a cut made by a person in the organisation does, and the set stays open until it resolves.",
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "position": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NettingPositionDto"
              }
            ],
            "description": "The OPEN set as you read it. All zero unless ACTIVE."
          },
          "proposer": {
            "$ref": "#/components/schemas/NettingPartyDto"
          },
          "rail": {
            "example": "SETTLEMENT",
            "type": "string"
          },
          "role": {
            "description": "Your side of it.",
            "enum": [
              "PROPOSER",
              "COUNTERPARTY"
            ],
            "type": "string"
          },
          "status": {
            "enum": [
              "PROPOSED",
              "ACTIVE",
              "DECLINED",
              "ENDED"
            ],
            "example": "ACTIVE",
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "currency",
          "role",
          "proposer",
          "counterparty",
          "position",
          "pendingCutApprovalRequestId",
          "declineReason",
          "endReason",
          "rail",
          "networkLabel",
          "createdAt",
          "updatedAt",
          "acceptedAt",
          "declinedAt",
          "endedAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerNettingCutOutcomeResponse": {
        "description": "The cut just posted, and the agreement as it now stands.",
        "properties": {
          "agreement": {
            "$ref": "#/components/schemas/PartnerNettingAgreementResponse"
          },
          "cut": {
            "$ref": "#/components/schemas/PartnerNettingCutResponse"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "kind": {
            "description": "Always CUT on this surface: a machine credential cannot hold a cut for approval.",
            "enum": [
              "CUT"
            ],
            "type": "string"
          }
        },
        "required": [
          "kind",
          "cut",
          "agreement",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerNettingCutResponse": {
        "description": "One cut: both gross figures, the net, who paid it, and the settlement it posted as — or none, when the two sides cancelled exactly.",
        "properties": {
          "agreementId": {
            "example": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "type": "string"
          },
          "currency": {
            "example": "USD",
            "type": "string"
          },
          "cutAt": {
            "format": "date-time",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "endToEndId": {
            "description": "The net settlement's reference.",
            "example": "NET-3f8c1d2a5e6b7049a1b2c3d4e5f6071",
            "type": "string"
          },
          "grossCounterpartyOwed": {
            "description": "Σ OPEN the counterparty owed at the cut.",
            "example": "2500.00",
            "type": "string"
          },
          "grossProposerOwed": {
            "description": "Σ OPEN the proposer owed at the cut.",
            "example": "4000.00",
            "type": "string"
          },
          "id": {
            "example": "sncut_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "type": "string"
          },
          "netAmount": {
            "example": "1500.00",
            "type": "string"
          },
          "netPayerClientAccountId": {
            "description": "Who paid the net. null when it was zero.",
            "format": "uuid",
            "nullable": true,
            "type": "object"
          },
          "netSettlementId": {
            "description": "The settlement the net posted as. null when the net was zero.",
            "example": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "nullable": true,
            "type": "object"
          },
          "networkLabel": {
            "example": "CommaNet",
            "type": "string"
          },
          "obligationCount": {
            "example": 3,
            "type": "number"
          },
          "rail": {
            "example": "SETTLEMENT",
            "type": "string"
          }
        },
        "required": [
          "id",
          "agreementId",
          "currency",
          "grossProposerOwed",
          "grossCounterpartyOwed",
          "netAmount",
          "netPayerClientAccountId",
          "netSettlementId",
          "endToEndId",
          "obligationCount",
          "rail",
          "networkLabel",
          "cutAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerNettingObligationResponse": {
        "description": "One obligation under an agreement. OPEN reserves its amount; NETTED names the cut that consumed it.",
        "properties": {
          "agreementId": {
            "example": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "type": "string"
          },
          "amount": {
            "example": "1500.00",
            "type": "string"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "currency": {
            "example": "USD",
            "type": "string"
          },
          "cutId": {
            "description": "The cut that consumed it, once one has.",
            "format": "uuid",
            "nullable": true,
            "type": "object"
          },
          "direction": {
            "description": "OUT = you owe it; IN = it is owed to you.",
            "enum": [
              "IN",
              "OUT"
            ],
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "endToEndId": {
            "example": "ACME-TRADE-2026-0042",
            "type": "string"
          },
          "id": {
            "example": "snob_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "type": "string"
          },
          "networkLabel": {
            "example": "CommaNet",
            "type": "string"
          },
          "payee": {
            "$ref": "#/components/schemas/NettingObligationPartyDto"
          },
          "payer": {
            "$ref": "#/components/schemas/NettingObligationPartyDto"
          },
          "rail": {
            "example": "SETTLEMENT",
            "type": "string"
          },
          "remittance": {
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "replayed": {
            "description": "True when an idempotent replay returned this row.",
            "example": false,
            "type": "boolean"
          },
          "status": {
            "enum": [
              "OPEN",
              "NETTED",
              "WITHDRAWN"
            ],
            "example": "OPEN",
            "type": "string"
          },
          "withdrawReason": {
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "withdrawnAt": {
            "format": "date-time",
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "id",
          "agreementId",
          "status",
          "direction",
          "amount",
          "currency",
          "endToEndId",
          "remittance",
          "payer",
          "payee",
          "cutId",
          "withdrawReason",
          "rail",
          "networkLabel",
          "createdAt",
          "withdrawnAt",
          "replayed",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerNettingReasonDto": {
        "description": "Why, when declining, ending or withdrawing.",
        "properties": {
          "reason": {
            "description": "Why, at most 280 characters.",
            "example": "Relationship ended",
            "type": "string"
          }
        },
        "type": "object"
      },
      "PartnerNetworkScreeningDto": {
        "description": "The screening verdict for the address on one network.",
        "properties": {
          "at": {
            "description": "When the address was screened on this network.",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "result": {
            "description": "The screening verdict for this address on this network: CLEAR, REVIEW (usable, but flagged on an open list), HIT (the destination is blocked) or UNSCREENED.",
            "enum": [
              "UNSCREENED",
              "CLEAR",
              "REVIEW",
              "HIT"
            ],
            "example": "CLEAR",
            "type": "string"
          }
        },
        "required": [
          "result",
          "at"
        ],
        "type": "object"
      },
      "PartnerOwnershipChallengeResponse": {
        "description": "The message the wallet signs to prove the payee controls the address, and when it expires.",
        "properties": {
          "expiresAt": {
            "description": "When the challenge stops being accepted (15 minutes after issue).",
            "format": "date-time",
            "type": "string"
          },
          "message": {
            "description": "The exact text the wallet signs with personal_sign (EIP-191). Sign it unchanged — line breaks included.",
            "example": "Three Comma Bank: I control this wallet and its private key.\nAddress: 0x8Ba1f109551bD432803012645Ac136ddd64DBA72\nPayee method: 1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97\nNonce: 3f9c0a…\nExpires: 2026-10-21T10:30:30.000Z",
            "type": "string"
          },
          "nonce": {
            "description": "The challenge nonce, also inside message.",
            "type": "string"
          }
        },
        "required": [
          "message",
          "nonce",
          "expiresAt"
        ],
        "type": "object"
      },
      "PartnerOwnershipDto": {
        "description": "Whether a signed ownership proof for the wallet address is on file.",
        "properties": {
          "at": {
            "description": "When the proof was verified.",
            "example": null,
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "proven": {
            "description": "True once a signed ownership proof for this address is on file.",
            "example": false,
            "type": "boolean"
          }
        },
        "required": [
          "proven",
          "at"
        ],
        "type": "object"
      },
      "PartnerPayoutCompensation": {
        "description": "How TCB resolved a payout whose rail outcome was initially unknown.",
        "properties": {
          "at": {
            "description": "When TCB resolved it.",
            "type": "string"
          },
          "outcome": {
            "description": "REFUNDED: the rail held no such payout, or reported that it failed, so the debit was refunded. PAID: the rail held it, so the payout completed forward and the money went where it was told.",
            "enum": [
              "REFUNDED",
              "PAID"
            ],
            "type": "string"
          }
        },
        "required": [
          "outcome",
          "at"
        ],
        "type": "object"
      },
      "PartnerPayoutDestination": {
        "description": "The registered destination a payout pays, summarised.",
        "properties": {
          "beneficiaryId": {
            "description": "The destination (payee) id.",
            "type": "string"
          },
          "currency": {
            "description": "The destination's currency.",
            "nullable": true,
            "type": "object"
          },
          "instrumentId": {
            "description": "The instrument id the payout named.",
            "type": "string"
          },
          "kind": {
            "description": "A bank account or a wallet.",
            "enum": [
              "FIAT_BANK",
              "CRYPTO_ADDRESS",
              "INTERNAL_TCB"
            ],
            "type": "string"
          },
          "last4": {
            "description": "The last four characters of the account identifier.",
            "nullable": true,
            "type": "object"
          },
          "name": {
            "description": "The payee's name, as registered.",
            "type": "string"
          },
          "rail": {
            "description": "The rail the destination is reached over.",
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "beneficiaryId",
          "instrumentId",
          "name",
          "kind",
          "currency",
          "rail",
          "last4"
        ],
        "type": "object"
      },
      "PartnerPayoutFee": {
        "description": "The Sending fee charged with a payout, on top of its amount, in the same currency: the per-rail fee for the rail the payout travels.",
        "properties": {
          "amount": {
            "description": "The Sending fee, as a decimal string.",
            "example": "25",
            "type": "string"
          },
          "currency": {
            "example": "EUR",
            "type": "string"
          }
        },
        "required": [
          "amount",
          "currency"
        ],
        "type": "object"
      },
      "PartnerPayoutQuoteFee": {
        "description": "The Sending fee a payout quote holds, and the rail it is priced on.",
        "properties": {
          "amount": {
            "description": "The Sending fee, as a decimal string.",
            "example": "25",
            "type": "string"
          },
          "currency": {
            "example": "EUR",
            "type": "string"
          },
          "rail": {
            "description": "The rail the payout will travel, which the Sending fee is priced on.",
            "example": "SEPA",
            "type": "string"
          }
        },
        "required": [
          "amount",
          "currency",
          "rail"
        ],
        "type": "object"
      },
      "PartnerPayoutQuoteRequestDto": {
        "description": "A payout to quote: the destination, the currency and amount, and the optional source account.",
        "properties": {
          "amount": {
            "description": "Amount to pay, as a decimal string. Never a float. Must not carry more fractional digits than the currency settles at (EUR: 2). Amounts below 0.000001 are refused.",
            "example": "1250.00",
            "type": "string"
          },
          "currency": {
            "description": "The payout currency. Must be the destination's currency — a payout is single-currency — and selects the fiat account the money leaves.",
            "example": "EUR",
            "type": "string"
          },
          "instrumentId": {
            "description": "The destination to pay: the instrumentId of a destination you registered, which must have completed screening, TCB approval and its holding period. There is no way to pass raw bank details here.",
            "example": "1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97",
            "format": "uuid",
            "type": "string"
          },
          "sourceAccountId": {
            "description": "The fiat account the money leaves. Omitted, your single active account in that currency is used. Once you hold more than one account in that currency this field is effectively mandatory — otherwise the payout is refused as ambiguous (409 SOURCE_ACCOUNT_AMBIGUOUS) with nothing charged.",
            "example": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "instrumentId",
          "currency",
          "amount"
        ],
        "type": "object"
      },
      "PartnerPayoutQuoteResponse": {
        "description": "A payout quote: the Sending fee, what leaves your account in total, and until when a payout naming quoteId is charged that fee.",
        "properties": {
          "amount": {
            "description": "The payout amount quoted, as a decimal string.",
            "example": "1250",
            "type": "string"
          },
          "currency": {
            "example": "EUR",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "expiresAt": {
            "description": "When the quote stops being usable. A payout naming it after this is refused with QUOTE_EXPIRED.",
            "example": "2026-10-30T10:16:28.000Z",
            "format": "date-time",
            "type": "string"
          },
          "fee": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerPayoutQuoteFee"
              }
            ],
            "description": "The Sending fee the payout pays, on top of amount, in the same currency and from the same source account. amount \"0\" when the rail carries no fee."
          },
          "quoteId": {
            "description": "Name this as quoteId on POST /payouts to be charged the quoted fee.",
            "example": "0b6f2d84-3c19-4e7a-9a52-6d1e8f4c7b30",
            "format": "uuid",
            "type": "string"
          },
          "requiresApproval": {
            "description": "True when this is the first payment to the destination and it is above your organisation's own first-send cap. The payout is then refused DESTINATION_NOT_USABLE until a member of your organisation makes the first payment to this destination through the app, or your organisation raises or removes its first-send cap. False otherwise. The quote itself records nothing against the destination.",
            "example": false,
            "type": "boolean"
          },
          "total": {
            "description": "What leaves the source account: amount plus the fee, as a decimal string.",
            "example": "1275",
            "type": "string"
          }
        },
        "required": [
          "quoteId",
          "amount",
          "currency",
          "fee",
          "total",
          "expiresAt",
          "requiresApproval",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerPayoutResponse": {
        "description": "A payout in its current state: where it stands on the rail, the destination it pays, and the timestamps of each step.",
        "properties": {
          "amount": {
            "description": "The amount paid, as a decimal string.",
            "example": "1250.00",
            "type": "string"
          },
          "compensation": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerPayoutCompensation"
              }
            ],
            "nullable": true
          },
          "createdAt": {
            "type": "string"
          },
          "currency": {
            "example": "EUR",
            "type": "string"
          },
          "destination": {
            "$ref": "#/components/schemas/PartnerPayoutDestination"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "endToEndId": {
            "description": "The end-to-end identifier TCB gave the rail for this payment — what a receiving bank or a statement line quotes. Null until the payout has been debited.",
            "nullable": true,
            "type": "object"
          },
          "failedAt": {
            "description": "When the payout failed terminally, if it did.",
            "nullable": true,
            "type": "object"
          },
          "fee": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerPayoutFee"
              }
            ],
            "description": "The Sending fee charged with this payout, on top of `amount`, in the same currency and from the same source account: the per-rail fee for the rail the payout travels, the same fee a payment sent from the TCB app pays. `amount` \"0\" when the rail carries no fee. Refunded with the payout whenever the payout is refunded or returned. Null when the payout was refused before anything was charged.",
            "nullable": true
          },
          "idempotencyKey": {
            "description": "Your idempotency key, as you sent it.",
            "type": "string"
          },
          "payoutId": {
            "description": "The payout id. Fetch it back at GET /partner/v1/payouts/{id}.",
            "type": "string"
          },
          "reference": {
            "description": "Your end-to-end reference, as carried to the rail.",
            "type": "string"
          },
          "replayed": {
            "description": "True when this response answered a replayed key. A replay reports the same payout in its CURRENT state — it never starts a second one.",
            "type": "boolean"
          },
          "return": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerPayoutReturn"
              }
            ],
            "nullable": true
          },
          "returnedAt": {
            "description": "When the receiving bank returned it, if it did.",
            "nullable": true,
            "type": "object"
          },
          "settledAt": {
            "description": "When the rail confirmed settlement.",
            "nullable": true,
            "type": "object"
          },
          "sourceAccountId": {
            "description": "The fiat account the money left.",
            "nullable": true,
            "type": "object"
          },
          "status": {
            "description": "PENDING (accepted, nothing debited) → PROCESSING (debited and handed to the rail) → SETTLED | FAILED | FAILED_PENDING_COMPENSATION | COMPENSATED. HELD_FOR_REVIEW: debited and held for review by TCB before it is sent; nothing has left yet. It continues to PROCESSING when released, or ends FAILED with the debit refunded. RETURNED: a settled payout the receiving bank sent back; the money is re-credited.",
            "enum": [
              "PENDING",
              "HELD_FOR_REVIEW",
              "PROCESSING",
              "SETTLED",
              "RETURNED",
              "FAILED",
              "FAILED_PENDING_COMPENSATION",
              "COMPENSATED"
            ],
            "type": "string"
          },
          "submittedAt": {
            "description": "When the rail accepted the payment.",
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "payoutId",
          "status",
          "idempotencyKey",
          "replayed",
          "currency",
          "amount",
          "fee",
          "reference",
          "destination",
          "sourceAccountId",
          "endToEndId",
          "submittedAt",
          "settledAt",
          "failedAt",
          "returnedAt",
          "return",
          "compensation",
          "createdAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerPayoutReturn": {
        "description": "What came back when the receiving bank returned a settled payout.",
        "properties": {
          "reasonCode": {
            "description": "The scheme's return reason code, verbatim, when the rail reported one.",
            "nullable": true,
            "type": "object"
          },
          "recreditedAmount": {
            "description": "The amount re-credited to the source account, as a decimal string.",
            "type": "string"
          },
          "returnedAt": {
            "description": "When the return was applied.",
            "type": "string"
          }
        },
        "required": [
          "reasonCode",
          "recreditedAmount",
          "returnedAt"
        ],
        "type": "object"
      },
      "PartnerPositionResponse": {
        "description": "What you hold in one vault: the totals, and the same figures broken down by sub-account.",
        "properties": {
          "currency": {
            "description": "The currency you asked about.",
            "example": "USD",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "rate": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerVaultRate"
              }
            ],
            "description": "The annual rate the vault pays now, net of fees, read on-chain, with when it took effect and the next scheduled change. The realised rate can be derived from the share-price history."
          },
          "sharePrice": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerPositionSharePrice"
              }
            ],
            "description": "The vault share price every currentValue on this response is valued at: the latest observation, with its block and time, and whether it is stale. Null when no price has been observed.",
            "nullable": true
          },
          "subAccounts": {
            "description": "The same position, broken down by sub-account. Oldest sub-account first.",
            "items": {
              "$ref": "#/components/schemas/PartnerPositionSubAccount"
            },
            "type": "array"
          },
          "totals": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerPositionTotals"
              }
            ],
            "description": "Your whole position in this vault."
          },
          "vault": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerPositionVault"
              }
            ],
            "description": "The vault this position is in."
          }
        },
        "required": [
          "currency",
          "vault",
          "totals",
          "subAccounts",
          "sharePrice",
          "rate",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerPositionSharePrice": {
        "properties": {
          "asOfAt": {
            "description": "When the observation was taken (ISO 8601, UTC).",
            "example": "2026-10-06T00:00:05.000Z",
            "type": "string"
          },
          "asOfBlock": {
            "description": "The chain block the price was read at.",
            "example": "316183526",
            "type": "string"
          },
          "snapshotDate": {
            "description": "The UTC day the observation belongs to.",
            "example": "2026-10-06",
            "type": "string"
          },
          "stale": {
            "description": "True when this observation is more than two days old (see asOfAt). The figures valued at it are still returned; treat them as of that time.",
            "example": false,
            "type": "boolean"
          },
          "value": {
            "description": "The value of one whole vault share in the underlying currency, as observed.",
            "example": "1.002480000000000000",
            "type": "string"
          }
        },
        "required": [
          "value",
          "asOfBlock",
          "asOfAt",
          "snapshotDate",
          "stale"
        ],
        "type": "object"
      },
      "PartnerPositionSubAccount": {
        "description": "What one sub-account holds, and what it has earned.",
        "properties": {
          "accrual": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerSubAccountAccrual"
              }
            ],
            "description": "What this sub-account has earned. Figures that cannot be observed are null, with the reason."
          },
          "availableShares": {
            "description": "settledShares minus reservedShares. A withdrawal naming this sub-account is authorised against this figure alone, never against your whole vault balance.",
            "example": "1024.518330000000000000000000",
            "type": "string"
          },
          "externalRef": {
            "description": "Your own identifier for this sub-account.",
            "example": "acme-fund-002",
            "type": "string"
          },
          "isDefault": {
            "description": "True for the sub-account that deposits and withdrawals land in when none is named.",
            "example": false,
            "type": "boolean"
          },
          "label": {
            "description": "The name you gave this sub-account.",
            "example": "Growth Fund II",
            "type": "string"
          },
          "reservedShares": {
            "description": "Shares held against withdrawals still in flight from this sub-account.",
            "example": "0",
            "type": "string"
          },
          "settledShares": {
            "description": "What this sub-account holds, as a decimal string at the vault's own share scale.",
            "example": "1024.518330000000000000000000",
            "type": "string"
          },
          "subAccountId": {
            "description": "The sub-account this row is about.",
            "example": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395",
            "type": "string"
          }
        },
        "required": [
          "subAccountId",
          "label",
          "externalRef",
          "isDefault",
          "settledShares",
          "reservedShares",
          "availableShares",
          "accrual"
        ],
        "type": "object"
      },
      "PartnerPositionTotals": {
        "description": "Your whole position in this vault: the sum of the sub-accounts below, alongside the share balance of the wallet TCB holds for you.",
        "properties": {
          "accrual": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerSubAccountAccrual"
              }
            ],
            "description": "The sum of the sub-account accrual groups below, never derived separately. A figure is null here when it is null on any sub-account."
          },
          "availableShares": {
            "description": "settledShares minus reservedShares.",
            "example": "1024.518330000000000000000000",
            "type": "string"
          },
          "reservedShares": {
            "description": "Sum of the shares held against withdrawals still in flight.",
            "example": "0",
            "type": "string"
          },
          "settledShares": {
            "description": "Sum of the sub-account settled positions below, as a decimal string at the vault's own share scale.",
            "example": "1024.518330000000000000000000",
            "type": "string"
          },
          "walletShares": {
            "description": "The share balance of the wallet TCB holds for you, read from the vault. Published beside the ledger total so you can see the holding your entitlement is against. While a deposit or withdrawal is in flight the two legitimately differ. Null when the chain read was unavailable.",
            "example": "1024.518330000000000000000000",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "settledShares",
          "reservedShares",
          "availableShares",
          "walletShares",
          "accrual"
        ],
        "type": "object"
      },
      "PartnerPositionVault": {
        "description": "The vault the position is held in.",
        "properties": {
          "address": {
            "description": "The vault contract this position is held in.",
            "example": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
            "type": "string"
          },
          "chain": {
            "description": "The chain that vault is deployed on.",
            "example": "ARBITRUM",
            "type": "string"
          }
        },
        "required": [
          "address",
          "chain"
        ],
        "type": "object"
      },
      "PartnerResolveResponse": {
        "description": "What an address resolves to: the verified legal name, what that member can receive, a verdict on the name you supplied, and a short-lived token to cite when you settle.",
        "properties": {
          "connected": {
            "description": "Whether YOU (the acting node) are on this member's connections list. Under CONNECTED_ONLY a settlement from you is refused when this is false; under ANYONE it is informational.",
            "example": true,
            "type": "boolean"
          },
          "currencies": {
            "description": "Currencies this member has an active account to receive.",
            "example": [
              "EUR",
              "USD"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "handle": {
            "description": "Their handle, or null when they are payable by IBAN but have no profile.",
            "example": "acme-treasury",
            "nullable": true,
            "type": "object"
          },
          "legalName": {
            "description": "The VERIFIED legal name. This is the safety net; the handle is convenience.",
            "example": "Acme Trading Ltd",
            "type": "string"
          },
          "node": {
            "$ref": "#/components/schemas/ResolvedNodeDto"
          },
          "receivePolicy": {
            "enum": [
              "ANYONE",
              "CONNECTED_ONLY"
            ],
            "example": "ANYONE",
            "type": "string"
          },
          "resolveToken": {
            "description": "Cite this on POST /settlements so the member you were SHOWN is the member who is PAID. Opaque, and good for ten minutes.",
            "type": "string"
          },
          "route": {
            "allOf": [
              {
                "$ref": "#/components/schemas/SettlementRouteDto"
              }
            ],
            "description": "How a payment to this member would be carried. Present on every resolved member, because every resolved member is on us."
          },
          "sameRoot": {
            "description": "This member is in YOUR tree. Settling to it is refused — use POST /transfers instead.",
            "example": false,
            "type": "boolean"
          },
          "verdict": {
            "description": "MATCH — the name you supplied is the legal name. CLOSE_MATCH — it is a trading name, or close enough to be a typo. NO_MATCH — it is neither; look again before paying. null — you supplied no name, which is the ABSENCE of a check, not a passed one.",
            "example": "MATCH",
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "node",
          "legalName",
          "handle",
          "receivePolicy",
          "connected",
          "currencies",
          "verdict",
          "resolveToken",
          "sameRoot",
          "route",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerSettlementConnectionDto": {
        "description": "One member allowed to pay you under CONNECTED_ONLY: who they are, the handle you typed, and your own note.",
        "properties": {
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "handle": {
            "description": "Their current handle, or the one you typed if they have since retired it.",
            "example": "acme-treasury",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "legalName": {
            "description": "Their verified legal name.",
            "example": "Acme Trading Ltd",
            "type": "string"
          },
          "memberClientAccountId": {
            "description": "The member allowed to pay you. Cite it on DELETE /network/connections/{id}.",
            "format": "uuid",
            "type": "string"
          },
          "note": {
            "example": "Prime broker — onboarded 2026-09",
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "id",
          "memberClientAccountId",
          "handle",
          "legalName",
          "note",
          "createdAt"
        ],
        "type": "object"
      },
      "PartnerSettlementConnectionResponse": {
        "description": "The connection as it now stands.",
        "properties": {
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "handle": {
            "description": "Their current handle, or the one you typed if they have since retired it.",
            "example": "acme-treasury",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "legalName": {
            "description": "Their verified legal name.",
            "example": "Acme Trading Ltd",
            "type": "string"
          },
          "memberClientAccountId": {
            "description": "The member allowed to pay you. Cite it on DELETE /network/connections/{id}.",
            "format": "uuid",
            "type": "string"
          },
          "note": {
            "example": "Prime broker — onboarded 2026-09",
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "id",
          "memberClientAccountId",
          "handle",
          "legalName",
          "note",
          "createdAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerSettlementConnectionsResponse": {
        "description": "Your connections list, oldest first. Consulted only while receivePolicy is CONNECTED_ONLY.",
        "properties": {
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/PartnerSettlementConnectionDto"
            },
            "type": "array"
          }
        },
        "required": [
          "items",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerSettlementDecisionReasonDto": {
        "description": "The optional reason shown to the other member when you decline something.",
        "properties": {
          "reason": {
            "description": "Why, at most 280 characters. Shown to the other member.",
            "example": "Invoice already paid by bank transfer",
            "type": "string"
          }
        },
        "type": "object"
      },
      "PartnerSettlementHoldReleaseResponse": {
        "description": "The outcome of releasing a hold: the settlement it booked, or the approval a colleague has been asked to release.",
        "properties": {
          "approvalRequestId": {
            "description": "The approval to be voted on, when kind is PENDING_APPROVAL.",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "hold": {
            "$ref": "#/components/schemas/PartnerSettlementHoldResponse"
          },
          "kind": {
            "description": "RELEASED when the money moved, PENDING_APPROVAL when a colleague was asked.",
            "example": "RELEASED",
            "type": "string"
          },
          "settlement": {
            "$ref": "#/components/schemas/PartnerSettlementResponse"
          },
          "transactionId": {
            "description": "The held transaction, when kind is PENDING_APPROVAL.",
            "type": "string"
          }
        },
        "required": [
          "kind",
          "hold",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerSettlementHoldResponse": {
        "description": "A reservation against a named member. ACTIVE means the amount is no longer available to settle elsewhere; it never expires on its own.",
        "properties": {
          "amount": {
            "example": "1500.00",
            "type": "string"
          },
          "beneficiary": {
            "$ref": "#/components/schemas/SettlementHoldPartyDto"
          },
          "cancelReason": {
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "cancelledAt": {
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "createdAt": {
            "example": "2026-09-08T10:15:30.000Z",
            "type": "string"
          },
          "currency": {
            "example": "USD",
            "type": "string"
          },
          "direction": {
            "description": "OUT if you placed it, IN if it is reserved for you.",
            "example": "OUT",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "endToEndId": {
            "example": "ACME-DVP-2026-0042",
            "type": "string"
          },
          "holder": {
            "$ref": "#/components/schemas/SettlementHoldPartyDto"
          },
          "id": {
            "example": "shld_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "type": "string"
          },
          "networkLabel": {
            "example": "CommaNet",
            "type": "string"
          },
          "pendingApprovalRequestId": {
            "description": "Set while your organisation decides a release. The hold stays ACTIVE — and keeps reserving — until the vote.",
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "rail": {
            "example": "SETTLEMENT",
            "type": "string"
          },
          "releasedAt": {
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "remittance": {
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "replayed": {
            "example": false,
            "type": "boolean"
          },
          "resolveVerdict": {
            "example": "MATCH",
            "nullable": true,
            "type": "object"
          },
          "settlementId": {
            "description": "The settlement the release booked, once it has.",
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "status": {
            "description": "ACTIVE, RELEASED or CANCELLED. Never EXPIRED.",
            "example": "ACTIVE",
            "type": "string"
          },
          "updatedAt": {
            "example": "2026-09-08T10:15:30.000Z",
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "direction",
          "amount",
          "currency",
          "endToEndId",
          "remittance",
          "holder",
          "beneficiary",
          "resolveVerdict",
          "settlementId",
          "pendingApprovalRequestId",
          "cancelReason",
          "rail",
          "networkLabel",
          "createdAt",
          "updatedAt",
          "releasedAt",
          "cancelledAt",
          "replayed",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerSettlementProfileResponse": {
        "description": "A member's network profile as it now stands. The handle is set once; everything else stays amendable.",
        "properties": {
          "aliases": {
            "example": [
              "Acme Trading"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "clientAccountId": {
            "description": "The member this profile belongs to.",
            "format": "uuid",
            "type": "string"
          },
          "createdAt": {
            "example": "2026-09-08T10:15:30.000Z",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "discoverable": {
            "description": "Whether it appears in directory search.",
            "example": false,
            "type": "boolean"
          },
          "handle": {
            "description": "The handle this member is paid by.",
            "example": "acme-treasury",
            "type": "string"
          },
          "inboundConversionCurrency": {
            "description": "The currency incoming settlements are converted into on arrival, or null to keep what is paid.",
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "receivePolicy": {
            "enum": [
              "ANYONE",
              "CONNECTED_ONLY"
            ],
            "example": "ANYONE",
            "type": "string"
          },
          "retiredAt": {
            "description": "When the handle was retired by a support-side change. A retired handle stays reserved forever and resolves to nothing.",
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "updatedAt": {
            "example": "2026-09-08T10:15:30.000Z",
            "type": "string"
          }
        },
        "required": [
          "clientAccountId",
          "handle",
          "discoverable",
          "receivePolicy",
          "aliases",
          "inboundConversionCurrency",
          "retiredAt",
          "createdAt",
          "updatedAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerSettlementRequestApprovalResponse": {
        "description": "The outcome of paying a request: the settlement it booked, or the approval a colleague has been asked to release.",
        "properties": {
          "approvalRequestId": {
            "description": "The approval to be voted on, when kind is PENDING_APPROVAL.",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "kind": {
            "description": "SETTLED when the money moved, PENDING_APPROVAL when your organisation requires a second approver and a colleague has been asked.",
            "example": "SETTLED",
            "type": "string"
          },
          "request": {
            "$ref": "#/components/schemas/PartnerSettlementRequestResponse"
          },
          "settlement": {
            "$ref": "#/components/schemas/PartnerSettlementResponse"
          },
          "transactionId": {
            "description": "The held transaction, when kind is PENDING_APPROVAL.",
            "type": "string"
          }
        },
        "required": [
          "kind",
          "request",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerSettlementRequestResponse": {
        "description": "A request to be paid, in its current state. It holds nothing and reserves nothing; what it becomes, if the payer approves, is an ordinary settlement.",
        "properties": {
          "amount": {
            "example": "1500.00",
            "type": "string"
          },
          "createdAt": {
            "example": "2026-09-08T10:15:30.000Z",
            "type": "string"
          },
          "currency": {
            "example": "USD",
            "type": "string"
          },
          "decidedAt": {
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "declineReason": {
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "direction": {
            "description": "OUTBOUND if you raised it, INBOUND if you are the one being asked.",
            "example": "INBOUND",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "dueBy": {
            "example": "2026-10-01T12:00:00.000Z",
            "nullable": true,
            "type": "object"
          },
          "endToEndId": {
            "example": "ACME-INV-2026-0042",
            "type": "string"
          },
          "id": {
            "example": "sreq_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "type": "string"
          },
          "networkLabel": {
            "example": "CommaNet",
            "type": "string"
          },
          "payer": {
            "$ref": "#/components/schemas/SettlementRequestPartyDto"
          },
          "pendingApprovalRequestId": {
            "description": "Set while the payer's organisation is deciding. The request stays OPEN until the vote releases it — a pending approval is not a payment.",
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "rail": {
            "example": "SETTLEMENT",
            "type": "string"
          },
          "remittance": {
            "example": {
              "invoice": "INV-2026-0042"
            },
            "nullable": true,
            "type": "object"
          },
          "replayed": {
            "description": "True when this answer replayed an earlier call under the same idempotency key.",
            "example": false,
            "type": "boolean"
          },
          "requester": {
            "$ref": "#/components/schemas/SettlementRequestPartyDto"
          },
          "settlementId": {
            "description": "The settlement the approval booked, once it has.",
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "status": {
            "description": "OPEN, APPROVED, DECLINED, EXPIRED or CANCELLED.",
            "example": "OPEN",
            "type": "string"
          },
          "updatedAt": {
            "example": "2026-09-08T10:15:30.000Z",
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "direction",
          "amount",
          "currency",
          "endToEndId",
          "remittance",
          "requester",
          "payer",
          "dueBy",
          "settlementId",
          "pendingApprovalRequestId",
          "declineReason",
          "rail",
          "networkLabel",
          "createdAt",
          "updatedAt",
          "decidedAt",
          "replayed",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerSettlementResponse": {
        "description": "A completed settlement, the same row both parties read. Settlements are final on the response — there is no pending state to poll.",
        "properties": {
          "activityId": {
            "description": "Groups this settlement with its four ledger entries on a statement.",
            "example": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
            "type": "string"
          },
          "amount": {
            "example": "1500.00",
            "type": "string"
          },
          "createdAt": {
            "example": "2026-09-08T10:15:30.000Z",
            "type": "string"
          },
          "currency": {
            "example": "USD",
            "type": "string"
          },
          "direction": {
            "description": "OUT if you sent it, IN if you received it. The rest of the row reads the same both ways.",
            "example": "OUT",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "endToEndId": {
            "example": "ACME-INV-2026-0042",
            "type": "string"
          },
          "fee": {
            "$ref": "#/components/schemas/SettlementFeeDto"
          },
          "id": {
            "description": "The settlement id.",
            "example": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "type": "string"
          },
          "networkLabel": {
            "description": "The network name, for display.",
            "example": "CommaNet",
            "type": "string"
          },
          "rail": {
            "example": "SETTLEMENT",
            "type": "string"
          },
          "receipt": {
            "allOf": [
              {
                "$ref": "#/components/schemas/SettlementReceiptDto"
              }
            ],
            "description": "What the RECEIVER holds after its inbound conversion rule ran: the converted amount and currency, and the order that priced it. Only on the receiver's read, and only once the conversion has filled. null means the money sits in the settled currency — no rule, the same currency, or a conversion that could not be priced. The settlement itself is unchanged either way.",
            "example": null,
            "nullable": true
          },
          "receiver": {
            "$ref": "#/components/schemas/SettlementPartyDto"
          },
          "remittance": {
            "example": {
              "invoice": "INV-2026-0042"
            },
            "nullable": true,
            "type": "object"
          },
          "replayed": {
            "description": "True when this answer replayed an earlier call under the same idempotency key.",
            "example": false,
            "type": "boolean"
          },
          "resolveVerdict": {
            "description": "The verdict shown at resolve, frozen beside the names it was about.",
            "example": "MATCH",
            "nullable": true,
            "type": "object"
          },
          "reversalOfId": {
            "description": "The settlement this one REVERSES. Set only on a reversing leg — the row a return of funds or an operator reversal booked. null on an ordinary settlement.",
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "reversedById": {
            "description": "The settlement that reversed this one. Present whenever status is REVERSED, whether the reversal was booked by accepting a return or raised by TCB. Follow it rather than searching for one.",
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "sender": {
            "$ref": "#/components/schemas/SettlementPartyDto"
          },
          "settledAt": {
            "example": "2026-09-08T10:15:30.000Z",
            "type": "string"
          },
          "settlementHoldId": {
            "description": "The shld_ hold whose release booked this settlement, when it came from one.",
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "settlementRequestId": {
            "description": "The sreq_ request this settlement paid, when it came from one.",
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "settlementReturnId": {
            "description": "The sret_ return whose acceptance booked this reversal, on both the reversed settlement and the reversing one. Otherwise, while this settlement is COMPLETED and not itself a reversal, the return request open on it. null in every other case, including when the only return requests were declined or cancelled.",
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "status": {
            "description": "COMPLETED, or REVERSED once a reversal is booked.",
            "example": "COMPLETED",
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "direction",
          "amount",
          "currency",
          "fee",
          "endToEndId",
          "remittance",
          "sender",
          "receiver",
          "resolveVerdict",
          "activityId",
          "rail",
          "networkLabel",
          "settledAt",
          "createdAt",
          "replayed",
          "reversalOfId",
          "reversedById",
          "settlementRequestId",
          "settlementHoldId",
          "settlementReturnId",
          "receipt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerSettlementReturnAcceptanceResponse": {
        "description": "The outcome of accepting a return: the reversing settlement it booked, or the approval a colleague has been asked to release.",
        "properties": {
          "approvalRequestId": {
            "description": "The approval to be voted on, when kind is PENDING_APPROVAL.",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "kind": {
            "description": "ACCEPTED when the money went back, PENDING_APPROVAL when a colleague was asked.",
            "example": "ACCEPTED",
            "type": "string"
          },
          "return": {
            "$ref": "#/components/schemas/PartnerSettlementReturnResponse"
          },
          "reversal": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerSettlementResponse"
              }
            ],
            "description": "The reversing settlement, when kind is ACCEPTED."
          },
          "transactionId": {
            "description": "The held transaction, when kind is PENDING_APPROVAL.",
            "type": "string"
          }
        },
        "required": [
          "kind",
          "return",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerSettlementReturnResponse": {
        "description": "A request for money to be given back. The original settlement stays completed and spendable until the receiver accepts.",
        "properties": {
          "amount": {
            "example": "1500.00",
            "type": "string"
          },
          "counterparty": {
            "$ref": "#/components/schemas/SettlementReturnPartyDto"
          },
          "createdAt": {
            "example": "2026-09-08T10:15:30.000Z",
            "type": "string"
          },
          "currency": {
            "example": "USD",
            "type": "string"
          },
          "decidedAt": {
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "declineReason": {
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "direction": {
            "description": "OUTBOUND if you asked for the money back, INBOUND if you are being asked.",
            "example": "INBOUND",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "id": {
            "example": "sret_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "type": "string"
          },
          "networkLabel": {
            "example": "CommaNet",
            "type": "string"
          },
          "pendingApprovalRequestId": {
            "description": "Set while the accepting organisation decides. The request stays OPEN until the money is actually back.",
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "rail": {
            "example": "SETTLEMENT",
            "type": "string"
          },
          "reason": {
            "example": "Paid twice against the same invoice",
            "nullable": true,
            "type": "object"
          },
          "requestedBy": {
            "$ref": "#/components/schemas/SettlementReturnPartyDto"
          },
          "reversalSettlementId": {
            "description": "The reversing settlement the acceptance booked, once it has.",
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "settlementId": {
            "description": "The settlement being returned.",
            "example": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "type": "string"
          },
          "status": {
            "description": "OPEN, ACCEPTED, DECLINED or CANCELLED.",
            "example": "OPEN",
            "type": "string"
          },
          "updatedAt": {
            "example": "2026-09-08T10:15:30.000Z",
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "direction",
          "settlementId",
          "amount",
          "currency",
          "reason",
          "requestedBy",
          "counterparty",
          "reversalSettlementId",
          "pendingApprovalRequestId",
          "declineReason",
          "rail",
          "networkLabel",
          "createdAt",
          "updatedAt",
          "decidedAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerSharePriceDay": {
        "description": "One day of a vault's share price, or nulls when it was not observed that day.",
        "properties": {
          "asOfAt": {
            "description": "When the observation was taken (ISO 8601, UTC). Null when not observed.",
            "example": "2026-10-06T00:00:05.000Z",
            "nullable": true,
            "type": "string"
          },
          "asOfBlock": {
            "description": "The chain block the price was read at. Null when not observed.",
            "example": "316183526",
            "nullable": true,
            "type": "string"
          },
          "date": {
            "description": "The UTC day.",
            "example": "2026-10-06",
            "type": "string"
          },
          "sharePrice": {
            "description": "The value of one whole vault share that day, as first observed. Null when the share price was not observed that day: a gap is never filled and never zero.",
            "example": "1.002480000000000000",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "date",
          "sharePrice",
          "asOfBlock",
          "asOfAt"
        ],
        "type": "object"
      },
      "PartnerSharePriceHistoryResponse": {
        "description": "A vault's observed share price, one entry per day.",
        "properties": {
          "currency": {
            "description": "The currency you asked about.",
            "example": "USD",
            "type": "string"
          },
          "days": {
            "description": "One entry per day in the range, oldest first, observed or not.",
            "items": {
              "$ref": "#/components/schemas/PartnerSharePriceDay"
            },
            "type": "array"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "from": {
            "description": "First day of the range (UTC, inclusive).",
            "example": "2026-09-08",
            "type": "string"
          },
          "to": {
            "description": "Last day of the range (UTC, inclusive).",
            "example": "2026-10-07",
            "type": "string"
          },
          "vault": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerPositionVault"
              }
            ],
            "description": "The vault the prices are of."
          }
        },
        "required": [
          "currency",
          "vault",
          "from",
          "to",
          "days",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerStatementBodyResponse": {
        "description": "Every sub-account's fold for the period, and the footnotes printed on every statement.",
        "properties": {
          "notes": {
            "description": "Footnotes printed on every statement.",
            "example": [
              "No period-end asset valuation is included in this statement; the ledger records shares and per-entry asset amounts only."
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "subAccounts": {
            "description": "Every sub-account's fold for the period.",
            "items": {
              "$ref": "#/components/schemas/PartnerStatementSubAccountResponse"
            },
            "type": "array"
          }
        },
        "required": [
          "subAccounts",
          "notes"
        ],
        "type": "object"
      },
      "PartnerStatementDetailResponse": {
        "description": "One statement in full: its period, its lineage, and every sub-account it folds.",
        "properties": {
          "id": {
            "description": "The statement id.",
            "format": "uuid",
            "type": "string"
          },
          "issuedAt": {
            "description": "When this statement was issued.",
            "format": "date-time",
            "type": "string"
          },
          "payloadHash": {
            "description": "sha256 of the statement content. Two statements with the same hash are identical.",
            "type": "string"
          },
          "period": {
            "$ref": "#/components/schemas/PartnerStatementPeriodResponse"
          },
          "statement": {
            "$ref": "#/components/schemas/PartnerStatementBodyResponse"
          },
          "supersededById": {
            "description": "The statement that replaced this one.",
            "format": "uuid",
            "nullable": true,
            "type": "object"
          },
          "supersedesId": {
            "description": "The statement this one replaced.",
            "format": "uuid",
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "id",
          "period",
          "issuedAt",
          "payloadHash",
          "supersedesId",
          "supersededById",
          "statement"
        ],
        "type": "object"
      },
      "PartnerStatementEntryResponse": {
        "description": "One settled ledger entry — a deposit, withdrawal or adjustment — with the share balance immediately after it.",
        "properties": {
          "assets": {
            "description": "Decimal string of the underlying asset amount, signed.",
            "example": "100.00",
            "type": "string"
          },
          "currencyCode": {
            "description": "ISO 4217 currency of the asset amount.",
            "example": "USD",
            "type": "string"
          },
          "entryId": {
            "description": "The ledger entry id.",
            "format": "uuid",
            "type": "string"
          },
          "entryType": {
            "description": "The kind of settled movement this line records.",
            "enum": [
              "DEPOSIT",
              "WITHDRAWAL",
              "ADJUSTMENT"
            ],
            "type": "string"
          },
          "intentId": {
            "description": "The money movement that produced this entry.",
            "format": "uuid",
            "nullable": true,
            "type": "object"
          },
          "occurredAt": {
            "description": "When the movement this entry records actually happened.",
            "format": "date-time",
            "type": "string"
          },
          "runningShares": {
            "description": "The share balance immediately after this entry — the opening balance plus every prior line.",
            "example": "100000000000000000000000000",
            "type": "string"
          },
          "shares": {
            "description": "Exact integer share delta as a string, signed.",
            "example": "100000000000000000000000000",
            "type": "string"
          }
        },
        "required": [
          "entryId",
          "entryType",
          "shares",
          "assets",
          "currencyCode",
          "intentId",
          "occurredAt",
          "runningShares"
        ],
        "type": "object"
      },
      "PartnerStatementListItemResponse": {
        "description": "One statement, without its entries. periodStart/periodEnd name the calendar month; formats lists the representations available.",
        "properties": {
          "formats": {
            "description": "Representations available for this statement.",
            "example": [
              "JSON",
              "CSV"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "id": {
            "description": "The statement id.",
            "format": "uuid",
            "type": "string"
          },
          "issuedAt": {
            "description": "When this statement was issued.",
            "format": "date-time",
            "type": "string"
          },
          "payloadHash": {
            "description": "sha256 of the statement content. Two statements with the same hash are identical.",
            "example": "0f4c8b1d92a7e35604fd1c8a37b2905e6417da8c25f0b93e71c6482da05f3b9e",
            "type": "string"
          },
          "periodEnd": {
            "description": "Last day of the statement period (inclusive, UTC).",
            "example": "2026-08-31",
            "type": "string"
          },
          "periodStart": {
            "description": "First day of the statement period (inclusive, UTC).",
            "example": "2026-08-01",
            "type": "string"
          },
          "supersededById": {
            "description": "The statement that replaced this one, when a correction has since been issued.",
            "format": "uuid",
            "nullable": true,
            "type": "object"
          },
          "supersedesId": {
            "description": "The statement this one replaced, when it is a correction.",
            "format": "uuid",
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "id",
          "periodStart",
          "periodEnd",
          "issuedAt",
          "payloadHash",
          "supersedesId",
          "supersededById",
          "formats"
        ],
        "type": "object"
      },
      "PartnerStatementPeriodResponse": {
        "description": "The calendar month a statement covers, inclusive on both ends.",
        "properties": {
          "from": {
            "example": "2026-08-01",
            "type": "string"
          },
          "to": {
            "example": "2026-08-31",
            "type": "string"
          }
        },
        "required": [
          "from",
          "to"
        ],
        "type": "object"
      },
      "PartnerStatementSubAccountResponse": {
        "description": "One sub-account for the period: its opening and closing share balance, and every settled entry in between.",
        "properties": {
          "closingShares": {
            "description": "Exact integer share balance at the end of the period, as a string.",
            "example": "100000000000000000000000000",
            "type": "string"
          },
          "currencyCode": {
            "description": "ISO 4217 currency of the underlying asset.",
            "example": "USD",
            "type": "string"
          },
          "entries": {
            "description": "Every settled entry in the period, in order.",
            "items": {
              "$ref": "#/components/schemas/PartnerStatementEntryResponse"
            },
            "type": "array"
          },
          "externalRef": {
            "description": "Your own reference for the sub-account.",
            "example": "tcb:default",
            "type": "string"
          },
          "openingShares": {
            "description": "Exact integer share balance at the start of the period, as a string.",
            "example": "0",
            "type": "string"
          },
          "subAccountId": {
            "description": "The sub-account id.",
            "format": "uuid",
            "type": "string"
          },
          "vaultAddress": {
            "description": "The vault this sub-account holds a position in.",
            "type": "string"
          }
        },
        "required": [
          "subAccountId",
          "externalRef",
          "vaultAddress",
          "currencyCode",
          "openingShares",
          "closingShares",
          "entries"
        ],
        "type": "object"
      },
      "PartnerSubAccountAccrual": {
        "description": "What a position is worth at the observed share price, what was put in and taken out, and what it has earned: lifetime, unrealised, realised and over a period. A figure that cannot be observed is null, with the reason.",
        "properties": {
          "currentValue": {
            "description": "The position at the latest observed share price, plus movements since that observation at their own amounts: shares settled at the observation are valued at its price, shares deposited since at what was deposited for them. A decimal string in the underlying currency. Null when no observed price exists.",
            "example": "1002.480000",
            "nullable": true,
            "type": "string"
          },
          "deposited": {
            "description": "Everything settled in, in the underlying currency.",
            "example": "1000.000000",
            "nullable": true,
            "type": "string"
          },
          "earnedLifetime": {
            "description": "Everything this position has earned, realised and unrealised: currentValue plus withdrawn minus deposited. Can be negative.",
            "example": "2.480000",
            "nullable": true,
            "type": "string"
          },
          "earnedPeriod": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerEarnedPeriod"
              }
            ],
            "description": "What was earned between periodFrom and periodTo. Null when no period was asked for.",
            "nullable": true
          },
          "earnedRealised": {
            "description": "Earned and locked in by withdrawals: proceeds minus the average cost of the shares withdrawn.",
            "example": "0",
            "nullable": true,
            "type": "string"
          },
          "earnedUnrealised": {
            "description": "Earned on the shares still held: currentValue minus their remaining cost (average cost).",
            "example": "2.480000",
            "nullable": true,
            "type": "string"
          },
          "netContributions": {
            "description": "Net contributed principal: settled deposits minus settled withdrawals.",
            "example": "1000.000000",
            "type": "string"
          },
          "notObserved": {
            "description": "Why a figure on this object is null. NO_PRICED_OBSERVATION: no observed vault share price to value the position at. FLOW_NOT_VALUED: a movement on this sub-account carries no asset figure. PERIOD_ENDPOINT_NOT_OBSERVED: a day bounding the period has no observed share price. EVIDENCE_INCONSISTENT: this sub-account's records disagree and TCB has been alerted; its share figures still stand. HISTORY_TOO_LONG: the sub-account has more ledger entries than one report folds, so its earned figures are withheld; its share figures still stand. Empty when every figure is present. Null always means not observed, never zero.",
            "example": [],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "withdrawn": {
            "description": "Everything settled out, as credited to you, in the underlying currency.",
            "example": "0",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "currentValue",
          "netContributions",
          "deposited",
          "withdrawn",
          "earnedLifetime",
          "earnedUnrealised",
          "earnedRealised",
          "earnedPeriod",
          "notObserved"
        ],
        "type": "object"
      },
      "PartnerSubAccountResponse": {
        "description": "A registry row for one partition of your book. It carries no amounts — read those from the position endpoint.",
        "properties": {
          "createdAt": {
            "description": "When the sub-account was registered.",
            "example": "2026-08-14T08:42:11.000Z",
            "format": "date-time",
            "type": "string"
          },
          "externalRef": {
            "description": "Your own identifier for this sub-account, unique within your principal.",
            "example": "acme-fund-002",
            "type": "string"
          },
          "isDefault": {
            "description": "True for the sub-account a deposit or withdrawal lands in when it names none. Exactly one of your sub-accounts has this set.",
            "example": false,
            "type": "boolean"
          },
          "label": {
            "description": "The name you gave this sub-account.",
            "example": "Growth Fund II",
            "type": "string"
          },
          "subAccountId": {
            "description": "The sub-account id. This is the value you name as subAccountId on a deposit or a withdrawal.",
            "example": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395",
            "type": "string"
          }
        },
        "required": [
          "subAccountId",
          "label",
          "externalRef",
          "isDefault",
          "createdAt"
        ],
        "type": "object"
      },
      "PartnerSubClientCryptoAccountResponse": {
        "description": "A sub-client's crypto account on one network: its address there and what it holds.",
        "properties": {
          "accountId": {
            "description": "The id of the crypto account on this network.",
            "example": "3b9e2f71-0c4d-4a58-9e16-7d2c5a8f1b40",
            "format": "uuid",
            "type": "string"
          },
          "address": {
            "description": "The address this account receives on. Null until the address is ready; an account with no address cannot receive yet.",
            "example": "0x5c1f0a2b3d4e5f60718293a4b5c6d7e8f9012345",
            "nullable": true,
            "type": "string"
          },
          "balances": {
            "description": "What the account holds on this network, one entry per asset.",
            "items": {
              "$ref": "#/components/schemas/PartnerCryptoBalanceResponse"
            },
            "type": "array"
          },
          "chain": {
            "description": "The network this account holds assets on.",
            "example": "ARBITRUM",
            "nullable": true,
            "type": "string"
          },
          "status": {
            "description": "Only an ACTIVE account sends or receives.",
            "enum": [
              "ACTIVE",
              "FROZEN",
              "CLOSED"
            ],
            "example": "ACTIVE",
            "type": "string"
          }
        },
        "required": [
          "accountId",
          "chain",
          "status",
          "address",
          "balances"
        ],
        "type": "object"
      },
      "PartnerSubClientResponse": {
        "description": "An end customer of yours: its identity handles, its verification state and capabilities, its accounts, and the transfer ceilings you set on it.",
        "properties": {
          "accounts": {
            "description": "Every account under this sub-client, with its balance and IBAN.",
            "items": {
              "$ref": "#/components/schemas/PartnerAccountResponse"
            },
            "type": "array"
          },
          "caps": {
            "description": "The within-tree transfer ceilings you set on this sub-client, as decimal strings. Empty means uncapped. Applies to CROSS_OWNER debits from this node only.",
            "example": {
              "USD": {
                "daily": "50000",
                "perTransfer": "10000"
              }
            },
            "type": "object"
          },
          "country": {
            "example": "BH",
            "nullable": true,
            "type": "string"
          },
          "createdAt": {
            "description": "When you created the sub-client.",
            "example": "2026-08-14T08:42:11.000Z",
            "format": "date-time",
            "type": "string"
          },
          "cryptoAccounts": {
            "description": "The sub-client's crypto holdings, one account per network.",
            "items": {
              "$ref": "#/components/schemas/PartnerSubClientCryptoAccountResponse"
            },
            "type": "array"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "externalRef": {
            "description": "Your own identifier for this sub-client, unique within your client account.",
            "example": "acme:cust-04231",
            "type": "string"
          },
          "kind": {
            "description": "Whether this end customer is a natural person or a business. It decides which activation baseline applies.",
            "enum": [
              "person",
              "business"
            ],
            "example": "person",
            "type": "string"
          },
          "lastActivityAt": {
            "example": "2026-09-20T14:12:00.000Z",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "legalName": {
            "description": "The verified legal name. It is the payee name on every IBAN issued for this sub-client.",
            "example": "Fatima Al-Khalifa",
            "type": "string"
          },
          "status": {
            "description": "Closing is irreversible, and retires every IBAN under the sub-client.",
            "enum": [
              "ACTIVE",
              "CLOSED"
            ],
            "example": "ACTIVE",
            "type": "string"
          },
          "subClientId": {
            "description": "The sub-client id. Send it as x-on-behalf-of to act for this sub-client.",
            "example": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
            "format": "uuid",
            "type": "string"
          },
          "totalHeldUsd": {
            "example": "1250.00",
            "type": "string"
          },
          "updatedAt": {
            "description": "When it last changed.",
            "example": "2026-08-28T09:00:00.000Z",
            "format": "date-time",
            "type": "string"
          },
          "verification": {
            "allOf": [
              {
                "$ref": "#/components/schemas/SubClientVerificationDto"
              }
            ],
            "description": "Where this sub-client stands, and what it may do today."
          }
        },
        "required": [
          "subClientId",
          "kind",
          "externalRef",
          "legalName",
          "status",
          "verification",
          "accounts",
          "cryptoAccounts",
          "caps",
          "createdAt",
          "updatedAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerTokenPositionResponse": {
        "description": "The tcbUSD you hold between steps, by sub-account, with the wallet balance.",
        "properties": {
          "asOf": {
            "description": "When the position was read.",
            "format": "date-time",
            "type": "string"
          },
          "currency": {
            "description": "The currency asked for.",
            "example": "USD",
            "type": "string"
          },
          "custody": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerCustodyRef"
              }
            ],
            "description": "Where the tcbUSD is held for you."
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "subAccounts": {
            "description": "One row per sub-account.",
            "items": {
              "$ref": "#/components/schemas/PartnerTokenPositionSubAccount"
            },
            "type": "array"
          },
          "token": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerTokenRef"
              }
            ],
            "description": "The token."
          },
          "totals": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerTokenPositionTotals"
              }
            ],
            "description": "The sum of the rows, and the wallet."
          },
          "yieldNote": {
            "description": "tcbUSD earns nothing on its own: only vault shares carry the yield. This position never carries an accrual.",
            "example": "tcbUSD earns nothing on its own: only vault shares carry the yield.",
            "type": "string"
          }
        },
        "required": [
          "currency",
          "token",
          "custody",
          "subAccounts",
          "totals",
          "yieldNote",
          "asOf",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerTokenPositionSubAccount": {
        "description": "One sub-account's tcbUSD: held, reserved and available.",
        "properties": {
          "available": {
            "description": "held minus reserved. A token redemption or a vault subscription naming this sub-account is authorised against this figure alone, never against the whole wallet.",
            "example": "600",
            "type": "string"
          },
          "externalRef": {
            "description": "Your own identifier for this sub-account.",
            "example": "acme-fund-002",
            "type": "string"
          },
          "held": {
            "description": "The tcbUSD booked to this sub-account, as a decimal string.",
            "example": "600",
            "type": "string"
          },
          "isDefault": {
            "description": "True for the sub-account steps land in when none is named.",
            "example": false,
            "type": "boolean"
          },
          "label": {
            "description": "The name you gave this sub-account.",
            "example": "Growth Fund II",
            "type": "string"
          },
          "reserved": {
            "description": "tcbUSD held against redemptions and subscriptions still in flight from this sub-account.",
            "example": "0",
            "type": "string"
          },
          "subAccountId": {
            "description": "The sub-account this row is about.",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "subAccountId",
          "label",
          "externalRef",
          "isDefault",
          "held",
          "reserved",
          "available"
        ],
        "type": "object"
      },
      "PartnerTokenPositionTotals": {
        "description": "The sum of the sub-account rows, beside the wallet balance.",
        "properties": {
          "available": {
            "description": "The sum of available over every sub-account.",
            "example": "1000",
            "type": "string"
          },
          "held": {
            "description": "The sum of held over every sub-account.",
            "example": "1000",
            "type": "string"
          },
          "reserved": {
            "description": "The sum of reserved over every sub-account.",
            "example": "0",
            "type": "string"
          },
          "walletTokens": {
            "description": "The tcbUSD the TCB wallet assigned to you holds on chain. It can be higher than held: a queued redemption that the vault paid but that is not yet booked, and fractions of a cent left by a fiat withdrawal, sit in the wallet until booked. Null when the chain could not be read.",
            "example": "1000.004",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "held",
          "reserved",
          "available",
          "walletTokens"
        ],
        "type": "object"
      },
      "PartnerTokenRef": {
        "description": "The token a step moves.",
        "properties": {
          "address": {
            "description": "The token contract.",
            "example": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
            "type": "string"
          },
          "chain": {
            "description": "The chain the token lives on.",
            "example": "ARBITRUM",
            "type": "string"
          },
          "symbol": {
            "description": "The token symbol.",
            "example": "tcbUSD",
            "type": "string"
          }
        },
        "required": [
          "symbol",
          "address",
          "chain"
        ],
        "type": "object"
      },
      "PartnerTransferResponse": {
        "description": "A completed within-tree transfer. Transfers are terminal on the response — there is no pending state to poll.",
        "properties": {
          "amount": {
            "description": "What moved, as a decimal string.",
            "example": "250.00",
            "type": "string"
          },
          "currency": {
            "description": "The currency of both accounts.",
            "example": "USD",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "executedAt": {
            "description": "When the transfer posted to both accounts.",
            "example": "2026-09-02T10:15:30.000Z",
            "format": "date-time",
            "type": "string"
          },
          "from": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TransferPartyDto"
              }
            ],
            "description": "The debited side."
          },
          "ownership": {
            "description": "SAME_OWNER when from and to share an ownerId, CROSS_OWNER otherwise (still within one tree). A movement between two TREES is not a transfer and is refused with TRANSFER_NOT_WITHIN_TREE.",
            "enum": [
              "SAME_OWNER",
              "CROSS_OWNER"
            ],
            "type": "string"
          },
          "reference": {
            "description": "The note you sent, or null.",
            "example": "Invoice 2026-0412",
            "nullable": true,
            "type": "object"
          },
          "replayed": {
            "description": "True when this response is the replay of an earlier call under the same idempotency key. Money moved once.",
            "example": false,
            "type": "boolean"
          },
          "status": {
            "description": "Always COMPLETED. A within-tree transfer is terminal on the response — there is no pending state to poll and no later state to wait for.",
            "enum": [
              "COMPLETED"
            ],
            "example": "COMPLETED",
            "type": "string"
          },
          "to": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TransferPartyDto"
              }
            ],
            "description": "The credited side."
          },
          "transferId": {
            "description": "The transfer id. Fetch it again with GET /transfers/{id}.",
            "example": "0c93a6e1-58fb-4d27-9a04-7e1b3c5d8f26",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "transferId",
          "status",
          "ownership",
          "from",
          "to",
          "amount",
          "currency",
          "reference",
          "executedAt",
          "replayed",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerVaultDepositListItem": {
        "description": "One vault deposit, as listed.",
        "properties": {
          "createdAt": {
            "description": "When you made the request (ISO 8601, UTC).",
            "example": "2026-10-06T09:12:44.000Z",
            "type": "string"
          },
          "currency": {
            "description": "The currency deposited (ISO 4217).",
            "example": "USD",
            "type": "string"
          },
          "depositId": {
            "description": "The deposit id.",
            "example": "2f6c9a41-3e58-4b70-9d12-6a8f0c3e5b71",
            "type": "string"
          },
          "requestedAmount": {
            "description": "The amount you asked to deposit, as a decimal string.",
            "example": "1000",
            "type": "string"
          },
          "settledAt": {
            "description": "When it settled (ISO 8601, UTC). Null until then.",
            "example": "2026-10-06T09:12:51.000Z",
            "nullable": true,
            "type": "string"
          },
          "shares": {
            "description": "Vault shares the deposit received, at the vault's own share scale. Null until it has settled.",
            "example": "999.876543210000000000000000",
            "nullable": true,
            "type": "string"
          },
          "status": {
            "description": "Where the movement stands, on the one status vocabulary every TCB surface uses. QUEUED: accepted, nothing irreversible has happened yet. PROCESSING: in flight. CREDIT_PENDING: the vault leg is done and money is owed to you (a withdrawal's proceeds, or a deposit's refund) that has not landed yet; TCB is resolving it, do not retry. COMPLETED, FAILED (nothing moved), REFUNDED (money moved and was returned) and CANCELLED are final.",
            "enum": [
              "QUEUED",
              "PROCESSING",
              "CREDIT_PENDING",
              "COMPLETED",
              "FAILED",
              "REFUNDED",
              "CANCELLED"
            ],
            "example": "COMPLETED",
            "type": "string"
          },
          "subAccountId": {
            "description": "The vault sub-account the deposit was booked to.",
            "example": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395",
            "type": "string"
          }
        },
        "required": [
          "depositId",
          "status",
          "subAccountId",
          "currency",
          "requestedAmount",
          "shares",
          "createdAt",
          "settledAt"
        ],
        "type": "object"
      },
      "PartnerVaultRate": {
        "description": "The annual rate a vault pays now, net of fees, read on-chain, with when it took effect and the next scheduled change.",
        "properties": {
          "apyBps": {
            "description": "The annual rate the vault pays now, in basis points, net of fees: read from the vault's strategy on-chain. Variable: it follows the vault's rate schedule. Null when it could not be read; see unavailableReason.",
            "example": 400,
            "nullable": true,
            "type": "number"
          },
          "asOf": {
            "description": "When apyBps was read (ISO 8601, UTC). If the latest read failed, this is the time of the last successful one and stale is true. Null when it has never been read.",
            "example": "2026-10-09T12:00:00.000Z",
            "nullable": true,
            "type": "string"
          },
          "effectiveFrom": {
            "description": "When the rate in apyBps took effect (ISO 8601, UTC). Null when apyBps is null, or when a scheduled change has not reached the vault yet (see pendingChange).",
            "example": "2026-09-01T00:00:00.000Z",
            "nullable": true,
            "type": "string"
          },
          "nextChange": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerVaultRateChange"
              }
            ],
            "description": "The next scheduled change to the rate. Null when none is scheduled.",
            "nullable": true
          },
          "pendingChange": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerVaultRateChange"
              }
            ],
            "description": "A scheduled change whose date has passed but which the vault does not pay yet: apyBps is still the previous rate. Null otherwise.",
            "nullable": true
          },
          "stale": {
            "description": "True when apyBps is the last successful read, not a current one.",
            "example": false,
            "type": "boolean"
          },
          "unavailableReason": {
            "description": "Why apyBps is null: VAULT_NOT_REGISTERED, NO_OVERNIGHT_STRATEGY or ONCHAIN_READ_FAILED. Null when a rate is returned.",
            "example": null,
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "apyBps",
          "asOf",
          "stale",
          "effectiveFrom",
          "pendingChange",
          "nextChange",
          "unavailableReason"
        ],
        "type": "object"
      },
      "PartnerVaultRateChange": {
        "description": "A scheduled change to a vault rate: the new rate and when it takes effect.",
        "properties": {
          "apyBps": {
            "description": "The scheduled annual rate, in basis points, net of fees.",
            "example": 375,
            "type": "number"
          },
          "effectiveFrom": {
            "description": "When it takes effect (ISO 8601, UTC).",
            "example": "2026-11-01T00:00:00.000Z",
            "type": "string"
          }
        },
        "required": [
          "apyBps",
          "effectiveFrom"
        ],
        "type": "object"
      },
      "PartnerVaultRef": {
        "description": "The vault a deposit or withdrawal was executed against.",
        "properties": {
          "address": {
            "description": "The vault contract the shares live in.",
            "example": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
            "type": "string"
          },
          "chain": {
            "description": "The chain that vault is deployed on.",
            "example": "ARBITRUM",
            "type": "string"
          }
        },
        "required": [
          "address",
          "chain"
        ],
        "type": "object"
      },
      "PartnerVaultWithdrawalListItem": {
        "description": "One vault withdrawal, as listed: what you asked for and what was credited.",
        "properties": {
          "createdAt": {
            "description": "When you made the request (ISO 8601, UTC).",
            "example": "2026-10-06T10:02:05.000Z",
            "type": "string"
          },
          "creditedAmount": {
            "description": "What was credited to you, rounded down to the currency's precision. Null until the withdrawal is COMPLETED; while it is CREDIT_PENDING the amount is owed, not yet credited.",
            "example": "249.99",
            "nullable": true,
            "type": "string"
          },
          "currency": {
            "description": "The currency withdrawn (ISO 4217).",
            "example": "USD",
            "type": "string"
          },
          "estimatedAvailableAt": {
            "description": "When the money is, or became, available to you (ISO 8601, UTC). A vault withdrawal is executed at once or refused; it is never queued, so a COMPLETED withdrawal carries the time it was credited and any other status carries null: no estimate is published for money in flight.",
            "example": "2026-10-06T10:02:13.000Z",
            "nullable": true,
            "type": "string"
          },
          "requestedAmount": {
            "description": "The amount you asked to withdraw, as a decimal string.",
            "example": "250",
            "type": "string"
          },
          "settledAt": {
            "description": "When it settled (ISO 8601, UTC). Null until then.",
            "example": "2026-10-06T10:02:13.000Z",
            "nullable": true,
            "type": "string"
          },
          "shares": {
            "description": "Vault shares the withdrawal redeemed, at the vault's own share scale. Null until the vault leg is done.",
            "example": "249.380000000000000000000000",
            "nullable": true,
            "type": "string"
          },
          "status": {
            "description": "Where the movement stands, on the one status vocabulary every TCB surface uses. QUEUED: accepted, nothing irreversible has happened yet. PROCESSING: in flight. CREDIT_PENDING: the vault leg is done and money is owed to you (a withdrawal's proceeds, or a deposit's refund) that has not landed yet; TCB is resolving it, do not retry. COMPLETED, FAILED (nothing moved), REFUNDED (money moved and was returned) and CANCELLED are final.",
            "enum": [
              "QUEUED",
              "PROCESSING",
              "CREDIT_PENDING",
              "COMPLETED",
              "FAILED",
              "REFUNDED",
              "CANCELLED"
            ],
            "example": "COMPLETED",
            "type": "string"
          },
          "subAccountId": {
            "description": "The vault sub-account the withdrawal was taken from.",
            "example": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395",
            "type": "string"
          },
          "withdrawalId": {
            "description": "The withdrawal id.",
            "example": "7a1d0c55-91e2-4f36-8b0a-2e64c9d8f173",
            "type": "string"
          }
        },
        "required": [
          "withdrawalId",
          "status",
          "subAccountId",
          "currency",
          "requestedAmount",
          "creditedAmount",
          "shares",
          "estimatedAvailableAt",
          "createdAt",
          "settledAt"
        ],
        "type": "object"
      },
      "PartnerWebhookResponse": {
        "description": "A webhook subscription. The full signing secret appears only on the response that minted it; reads show a preview instead.",
        "properties": {
          "createdAt": {
            "description": "When the endpoint was registered.",
            "example": "2026-08-14T08:42:11.000Z",
            "format": "date-time",
            "type": "string"
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "events": {
            "description": "The event types this endpoint receives.",
            "example": [
              "deposit.settled",
              "withdrawal.settled"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "previousSecretExpiresAt": {
            "description": "While this is set and in the future, every delivery is signed with BOTH the new secret and the previous one, so either verifies while you cut over. Null when no rotation is in flight.",
            "example": "2026-09-03T10:15:30.000Z",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "secret": {
            "description": "The full signing secret. Present only on the call that minted it — registering the endpoint, or rotating the secret. Store it: it is never shown again.",
            "example": "whsec_k3vJ9aQ2mR7xL0pT4wZ8nB1yC6dF5gH2jK9sV3eA7u",
            "type": "string"
          },
          "secretPreview": {
            "description": "The opening characters of the secret currently in force, so you can tell which one you hold without the API disclosing it again.",
            "example": "whsec_k3vJ9aQ2…",
            "type": "string"
          },
          "status": {
            "description": "ACTIVE while deliveries are attempted. DISABLED after you delete it — the subscription and its delivery history are kept, but nothing more is sent.",
            "enum": [
              "ACTIVE",
              "DISABLED"
            ],
            "example": "ACTIVE",
            "type": "string"
          },
          "url": {
            "description": "The URL events are POSTed to.",
            "example": "https://partner.example.com/tcb/webhooks",
            "type": "string"
          },
          "webhookId": {
            "description": "The subscription id.",
            "example": "4e8b1d70-a35c-4692-b0f1-9d2c6a4e73b8",
            "type": "string"
          }
        },
        "required": [
          "webhookId",
          "url",
          "events",
          "status",
          "secretPreview",
          "previousSecretExpiresAt",
          "createdAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerWithdrawalOnchain": {
        "description": "The transactions behind the withdrawal, once each leg has landed.",
        "properties": {
          "burnTxHash": {
            "description": "The transaction that burned the underlying and credited your fiat. Its presence is what proves the fiat leg landed — settledAmount alone does not.",
            "example": "0xb31d0f6a29c85e470132d9af6058c7be24913f5d7ea0c86241b09fd35c7a1e64",
            "nullable": true,
            "type": "string"
          },
          "withdrawTxHash": {
            "description": "The transaction that released the assets from the vault. Null until it lands.",
            "example": "0x6c58e2af017d94b3182fa0e7c53d69b148027ea5f31c8d60947b25e0fa1c3d78",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "withdrawTxHash",
          "burnTxHash"
        ],
        "type": "object"
      },
      "PartnerWithdrawalResponse": {
        "description": "A withdrawal in its current state. What you asked for and what settles can differ by the rounding to the currency precision — both figures are on the object.",
        "properties": {
          "amount": {
            "description": "What you asked for, as a decimal string. Normalised, not echoed verbatim: a submitted '250.00' comes back as '250'.",
            "example": "250",
            "type": "string"
          },
          "createdAt": {
            "description": "When you submitted the withdrawal.",
            "example": "2026-09-02T10:15:28.000Z",
            "format": "date-time",
            "type": "string"
          },
          "currency": {
            "description": "The currency withdrawn.",
            "example": "USD",
            "type": "string"
          },
          "custody": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerCustodyRef"
              }
            ],
            "description": "Where the shares are held for you."
          },
          "disclosure": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerDisclosureDto"
              }
            ],
            "description": "The pilot disclosure."
          },
          "idempotencyKey": {
            "description": "The idempotency key you sent, echoed back.",
            "example": "acme-withdrawal-2026-08-30-0001",
            "type": "string"
          },
          "onchain": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerWithdrawalOnchain"
              }
            ],
            "description": "The transactions behind the withdrawal."
          },
          "precisionResidue": {
            "description": "What the vault returned above settledAmount, left in your own sub-account wallet. It is your money that this call did not move, not a deduction. Null until the vault leg lands.",
            "example": "0.004821",
            "nullable": true,
            "type": "string"
          },
          "replayed": {
            "description": "True when this body is the stored result of an earlier call under the same key. Money moved once.",
            "example": false,
            "type": "boolean"
          },
          "settledAmount": {
            "description": "What the rounding to the currency precision determined is owed, as a decimal string. Null until the vault leg lands. It is what is OWED, not proof of delivery — pair it with onchain.burnTxHash for that.",
            "example": "250",
            "nullable": true,
            "type": "string"
          },
          "settledAt": {
            "description": "When the withdrawal settled. Null until it does.",
            "example": "2026-09-02T10:15:41.000Z",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "shares": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerWithdrawalShares"
              }
            ],
            "description": "Your share position after this withdrawal."
          },
          "status": {
            "description": "Where the withdrawal stands. SETTLED means the fiat was credited. FAILED means nothing moved. FAILED_PENDING_COMPENSATION and COMPENSATED mean shares left the vault and a TCB operator is resolving it — do not retry with a new key.",
            "enum": [
              "PENDING",
              "EXECUTING_ONCHAIN",
              "SETTLED",
              "FAILED",
              "FAILED_PENDING_COMPENSATION",
              "COMPENSATED"
            ],
            "example": "SETTLED",
            "type": "string"
          },
          "vault": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PartnerVaultRef"
              }
            ],
            "description": "The vault the shares were redeemed from."
          },
          "withdrawalId": {
            "description": "The withdrawal id. Fetch this withdrawal again with GET /withdrawals/{id}.",
            "example": "8c1e7b25-4a93-4f06-b83d-2e5c9017a4f6",
            "type": "string"
          }
        },
        "required": [
          "withdrawalId",
          "status",
          "idempotencyKey",
          "replayed",
          "currency",
          "amount",
          "settledAmount",
          "precisionResidue",
          "vault",
          "custody",
          "shares",
          "onchain",
          "settledAt",
          "createdAt",
          "disclosure"
        ],
        "type": "object"
      },
      "PartnerWithdrawalShares": {
        "description": "Your share position after the withdrawal.",
        "properties": {
          "balance": {
            "description": "The sub-account's remaining share balance after this withdrawal, as a decimal string at the vault's own share scale. Null when the balance could not be read — a settled withdrawal is never failed over an unavailable read.",
            "example": "774.518330000000000000000000",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "balance"
        ],
        "type": "object"
      },
      "ProposePartnerNettingAgreementDto": {
        "description": "An offer to net with another member: one currency, and the account of yours a cut will debit or credit.",
        "properties": {
          "counterpartyClientAccountId": {
            "description": "The member to net with, by node id.",
            "format": "uuid",
            "type": "string"
          },
          "counterpartyHandle": {
            "description": "The member to net with, by handle. Exactly one of counterpartyHandle or counterpartyClientAccountId.",
            "example": "orbital-advisory",
            "type": "string"
          },
          "currency": {
            "description": "The one currency this agreement nets. ISO 4217.",
            "example": "USD",
            "type": "string"
          },
          "fromAccountId": {
            "description": "Your account under the agreement — debited when you owe the net, credited when you are owed it. Must belong to the acting node, be ACTIVE, fiat and in this currency.",
            "example": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "fromAccountId",
          "currency"
        ],
        "type": "object"
      },
      "ResolvedNodeDto": {
        "description": "The member an address resolved to.",
        "properties": {
          "clientAccountId": {
            "format": "uuid",
            "type": "string"
          },
          "kind": {
            "description": "CLIENT for a client of the bank, SUBCLIENT for one of its sub-clients.",
            "example": "CLIENT",
            "type": "string"
          }
        },
        "required": [
          "clientAccountId",
          "kind"
        ],
        "type": "object"
      },
      "SettlementFeeDto": {
        "description": "What the sender paid to settle. Zero throughout this pilot.",
        "properties": {
          "amount": {
            "description": "Zero on every settlement in this pilot.",
            "example": "0",
            "type": "string"
          },
          "currency": {
            "example": "USD",
            "type": "string"
          }
        },
        "required": [
          "amount",
          "currency"
        ],
        "type": "object"
      },
      "SettlementHoldPartyDto": {
        "description": "One side of a hold: the member, the account, and the legal name frozen when it was placed.",
        "properties": {
          "accountId": {
            "format": "uuid",
            "type": "string"
          },
          "clientAccountId": {
            "format": "uuid",
            "type": "string"
          },
          "legalName": {
            "example": "Acme Trading Ltd",
            "type": "string"
          }
        },
        "required": [
          "clientAccountId",
          "accountId",
          "legalName"
        ],
        "type": "object"
      },
      "SettlementPartyDto": {
        "description": "One side of a settlement: the member, the account, and the legal name frozen at the moment it settled.",
        "properties": {
          "accountId": {
            "format": "uuid",
            "type": "string"
          },
          "clientAccountId": {
            "format": "uuid",
            "type": "string"
          },
          "legalName": {
            "description": "The verified legal name, FROZEN at settlement. For a sub-client this is the sub-client, never the client operating for it.",
            "example": "Acme Trading Ltd",
            "type": "string"
          }
        },
        "required": [
          "clientAccountId",
          "accountId",
          "legalName"
        ],
        "type": "object"
      },
      "SettlementReceiptDto": {
        "description": "What the receiver holds after its inbound conversion rule ran. On the receiver's read only, and only once the conversion has filled; the settlement itself is unchanged.",
        "properties": {
          "amount": {
            "description": "What landed after conversion, as a decimal string.",
            "example": "1381.25",
            "type": "string"
          },
          "conversionOrderId": {
            "description": "The trade order that priced the conversion.",
            "example": "5c1e9a2b-3d4f-4e6a-8b7c-9d0e1f2a3b4c",
            "format": "uuid",
            "nullable": true,
            "type": "object"
          },
          "currency": {
            "description": "The currency it landed in — the receiver's rule.",
            "example": "EUR",
            "type": "string"
          }
        },
        "required": [
          "amount",
          "currency",
          "conversionOrderId"
        ],
        "type": "object"
      },
      "SettlementRequestPartyDto": {
        "description": "One side of a request: the member, its legal name frozen when the request was raised, and — on the requester — the account to be credited.",
        "properties": {
          "accountId": {
            "description": "The account to be credited. Present on the requester only.",
            "format": "uuid",
            "type": "string"
          },
          "clientAccountId": {
            "format": "uuid",
            "type": "string"
          },
          "legalName": {
            "description": "The verified legal name, FROZEN when the request was raised.",
            "example": "Acme Trading Ltd",
            "type": "string"
          }
        },
        "required": [
          "clientAccountId",
          "legalName"
        ],
        "type": "object"
      },
      "SettlementReturnPartyDto": {
        "description": "One side of a return request.",
        "properties": {
          "clientAccountId": {
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "clientAccountId"
        ],
        "type": "object"
      },
      "SettlementRouteDto": {
        "description": "How a payment to this member would be carried. Branch on `rail` — COMMANET is a settlement to another client, INTERNAL is a move inside your own tree and belongs on POST /transfers — and render `label` rather than parsing it. Both rails are on us, instant and free.",
        "properties": {
          "arrival": {
            "enum": [
              "INSTANT"
            ],
            "example": "INSTANT",
            "type": "string"
          },
          "fee": {
            "allOf": [
              {
                "$ref": "#/components/schemas/SettlementFeeDto"
              }
            ],
            "description": "Zero, and published as zero (§1b.26)."
          },
          "label": {
            "description": "Ready-to-render copy. Never parse it; branch on rail.",
            "example": "via CommaNet · instant · no fee",
            "type": "string"
          },
          "onUs": {
            "description": "Always true here: an off-us payment carries no route.",
            "example": true,
            "type": "boolean"
          },
          "rail": {
            "description": "COMMANET — a settlement to another root client. INTERNAL — a move inside your own tree, which is POST /transfers, not this rail. Both are on us, instant and free.",
            "enum": [
              "COMMANET",
              "INTERNAL"
            ],
            "example": "COMMANET",
            "type": "string"
          }
        },
        "required": [
          "rail",
          "onUs",
          "fee",
          "arrival",
          "label"
        ],
        "type": "object"
      },
      "SubClientRequirementsDto": {
        "description": "What is still needed before this sub-client is verified, split by urgency.",
        "properties": {
          "currentlyDue": {
            "description": "What is needed now. Send it to move the sub-client on. The one value you cannot send is \"screening\" — TCB's own sanctions and PEP check, which only TCB clears.",
            "example": [
              "identity.person.dateOfBirth",
              "attestation",
              "screening"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "disabledReason": {
            "description": "Why the sub-client is restricted, when it is. Null otherwise.",
            "example": null,
            "nullable": true,
            "type": "object"
          },
          "eventuallyDue": {
            "description": "What will be needed later, but is not blocking anything today.",
            "example": [],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "pastDue": {
            "description": "What was due and is now overdue. Capabilities are already restricted.",
            "example": [],
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "currentlyDue",
          "pastDue",
          "eventuallyDue",
          "disabledReason"
        ],
        "type": "object"
      },
      "SubClientVerificationDto": {
        "description": "Where a sub-client stands in verification: its level, its status, what is still outstanding and what it may do today.",
        "properties": {
          "attestedAt": {
            "description": "When you last attested for this sub-client. Null if you never have.",
            "example": "2026-08-28T09:00:00.000Z",
            "format": "date-time",
            "nullable": true,
            "type": "object"
          },
          "capabilities": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapabilitiesFlagsDto"
              }
            ],
            "description": "What this sub-client may do today, given the status above."
          },
          "level": {
            "description": "The verification level this sub-client is held at. RELIANCE means you performed the due diligence under your own regulated programme, under a reliance agreement with TCB, and TCB records it, screens the sub-client itself, and samples and tests your files. TCB grants the level per client account at your own onboarding.",
            "enum": [
              "RELIANCE"
            ],
            "example": "RELIANCE",
            "type": "string"
          },
          "requirements": {
            "allOf": [
              {
                "$ref": "#/components/schemas/SubClientRequirementsDto"
              }
            ],
            "description": "What is still outstanding, split by urgency."
          },
          "status": {
            "description": "Where the sub-client stands. Only VERIFIED carries any capability at all: NOT_STARTED and REQUIREMENTS_DUE carry none and their IBANs accept no funds, and RESTRICTED is a compliance hold that withdraws every capability — an existing balance is held, not returned.",
            "enum": [
              "NOT_STARTED",
              "REQUIREMENTS_DUE",
              "VERIFIED",
              "RESTRICTED"
            ],
            "example": "VERIFIED",
            "type": "string"
          },
          "verifiedAt": {
            "description": "When the sub-client last became fully verified. Null while it is not.",
            "example": "2026-08-28T09:00:00.000Z",
            "format": "date-time",
            "nullable": true,
            "type": "object"
          }
        },
        "required": [
          "level",
          "status",
          "requirements",
          "capabilities",
          "attestedAt",
          "verifiedAt"
        ],
        "type": "object"
      },
      "SubmitPartnerNettingObligationDto": {
        "description": "An amount you owe the other member under an agreement. Reserved in full until the set is cut.",
        "properties": {
          "amount": {
            "description": "What you owe, as a decimal string.",
            "example": "1500.00",
            "type": "string"
          },
          "endToEndId": {
            "description": "Your reference for this obligation. ISO 20022 shape, at most 35 characters.",
            "example": "ACME-TRADE-2026-0042",
            "type": "string"
          },
          "idempotencyKey": {
            "description": "Your key for this obligation. Replaying it returns the original. Or send Idempotency-Key.",
            "example": "acme-obl-2026-09-16-0001",
            "type": "string"
          },
          "remittance": {
            "description": "Optional structured remittance, at most 1 KB of JSON.",
            "type": "object"
          }
        },
        "required": [
          "amount",
          "endToEndId"
        ],
        "type": "object"
      },
      "SubmitPartnerOwnershipProofDto": {
        "description": "The challenge message and the wallet's signature of it.",
        "properties": {
          "message": {
            "description": "The challenge message, exactly as GET …/ownership-proof/challenge returned it.",
            "type": "string"
          },
          "signature": {
            "description": "The 0x-prefixed personal_sign (EIP-191) signature of message by the address's key.",
            "example": "0x4f6c…1b",
            "type": "string"
          }
        },
        "required": [
          "message",
          "signature"
        ],
        "type": "object"
      },
      "TransferPartyDto": {
        "description": "One side of a transfer: the account and the owner it belongs to.",
        "properties": {
          "accountId": {
            "description": "The account on this side of the transfer.",
            "example": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
            "format": "uuid",
            "type": "string"
          },
          "ownerId": {
            "description": "The owner of that account.",
            "example": "3a7e5c91-0d24-4b6f-8e13-5c9a2f7b1d04",
            "format": "uuid",
            "type": "string"
          },
          "ownerType": {
            "description": "CLIENT when the account is your own, SUB_CLIENT when it belongs to a sub-client.",
            "enum": [
              "CLIENT",
              "SUB_CLIENT"
            ],
            "example": "CLIENT",
            "type": "string"
          }
        },
        "required": [
          "accountId",
          "ownerType",
          "ownerId"
        ],
        "type": "object"
      },
      "TravelRuleDto": {
        "description": "Required for a wallet destination: whether it is self-hosted, and — when it is held at an exchange — the name of the institution holding it.",
        "properties": {
          "selfHosted": {
            "description": "true = the wallet is self-hosted (your own, or another person’s). false = it is held at an exchange/VASP.",
            "type": "boolean"
          },
          "vaspLei": {
            "type": "string"
          },
          "vaspName": {
            "description": "Required when selfHosted is false.",
            "type": "string"
          }
        },
        "required": [
          "selfHosted"
        ],
        "type": "object"
      },
      "UpdatePartnerSettlementProfileDto": {
        "description": "How this member is addressed on the network: the handle it is paid by, whether it is listed in search, whether it accepts settlements from anyone, the trading names it is also known by, and whether what it receives is converted into one currency on arrival.",
        "properties": {
          "aliases": {
            "description": "Trading names this member is also known by, at most 5 of at most 64 characters. A payer naming one of these resolves CLOSE_MATCH rather than NO_MATCH — a legal-versus-trading name mismatch is the commonest false alarm in confirmation of payee.",
            "example": [
              "Acme Trading"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "discoverable": {
            "description": "Whether this member appears in GET /network/search. Off by default — being payable by exact handle or IBAN is not the same as being listed.",
            "example": false,
            "type": "boolean"
          },
          "handle": {
            "description": "The handle this member is paid by, chosen ONCE. Lowercase letters, digits and single internal hyphens, 3-32 characters per part. Under x-on-behalf-of it is namespaced under your own handle: acme/zayn-retail. Uniqueness is decided on a form that folds characters a human reads alike, so a handle that merely looks like one already taken is refused too.",
            "example": "acme-treasury",
            "type": "string"
          },
          "inboundConversionCurrency": {
            "description": "Convert what you receive. When set, a settlement paid to this member in any other currency is converted into this one as soon as it lands, on its own accounts, priced as its conversions normally are. The settlement is unchanged and final in the currency the sender chose; the receiver then reads what landed in `receipt`. Refused with 422 INBOUND_CONVERSION_CURRENCY_UNAVAILABLE unless the member holds an active fiat account in this currency. null clears the rule.",
            "example": "EUR",
            "nullable": true,
            "type": "object"
          },
          "receivePolicy": {
            "description": "ANYONE accepts settlements from any member. CONNECTED_ONLY is recorded but refuses every incoming settlement with 422 RECEIVE_POLICY_REFUSED unless the sending node is on your connections list (GET /network/connections). An empty list refuses everyone.",
            "enum": [
              "ANYONE",
              "CONNECTED_ONLY"
            ],
            "example": "ANYONE",
            "type": "string"
          }
        },
        "type": "object"
      },
      "UpdateSubClientDto": {
        "description": "Fields to change on an existing sub-client. Everything is optional; only what you send is applied.",
        "properties": {
          "caps": {
            "description": "Per-currency within-tree transfer ceilings for this sub-client, e.g. {\"USD\":{\"perTransfer\":\"10000\",\"daily\":\"50000\"}}. Decimal STRINGS, never JSON numbers. Applied to this node's CROSS_OWNER debits only — a move between its own accounts is never capped. Sent whole: the object REPLACES the stored one, so {} removes every cap. Nothing else caps a within-tree transfer.",
            "example": {
              "USD": {
                "daily": "50000",
                "perTransfer": "10000"
              }
            },
            "type": "object"
          },
          "identity": {
            "description": "Partial identity record, merged field by field into the stored one.",
            "example": {
              "address": {
                "city": "Manama",
                "country": "BH",
                "line1": "9 Road 3812"
              }
            },
            "type": "object"
          },
          "legalName": {
            "description": "A change on a VERIFIED sub-client moves status back to REQUIREMENTS_DUE with \"attestation\" in currentlyDue, and DEACTIVATES its IBANs until it is verified again. Nothing is re-issued: the same coordinates reactivate, carrying the corrected payee name.",
            "example": "Fatima Al-Khalifa",
            "type": "string"
          },
          "metadata": {
            "description": "Free-form, yours. Sent whole: it REPLACES the stored object.",
            "example": {
              "segment": "priority"
            },
            "type": "object"
          }
        },
        "type": "object"
      }
    },
    "securitySchemes": {
      "bearer": {
        "bearerFormat": "API key",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "contact": {},
    "description": "The TCB client API: vault deposits, withdrawals, conversions, the\nsub-account ledger (positions and accrual), and the outbound webhook registry.\n\nThe version is the `/partner/v1` path segment. Changes within v1 are additive\nonly; a breaking change is a new path segment. Every response payload carries\nthe `disclosure` block below verbatim — identical everywhere it appears.\n\nHuman-readable documentation with worked examples:\nhttps://docs.threecommabank.com/docs\n\n**Disclosure (version 2026-10-27).** This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.\n\n- ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.\n- YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.\n- FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.\n- CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.\n- CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.\n- CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.\n- INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment.",
    "title": "TCB Client API",
    "version": "v1"
  },
  "openapi": "3.0.0",
  "paths": {
    "/api/partner/v1/accounts": {
      "get": {
        "description": "The acting principal's own partitions — yours, or, with x-on-behalf-of, that sub-client's. Balances live only on accounts; a sub-client's balances are never folded into your own totals.",
        "operationId": "list-accounts",
        "parameters": [
          {
            "description": "Return only accounts in this currency — an ISO 4217 code for a fiat account, or the asset symbol for a crypto one (for example USDC).",
            "example": "EUR",
            "in": "query",
            "name": "currency",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "MAIN is the owner's account for that currency; SUB is any account beside it.",
            "in": "query",
            "name": "role",
            "required": false,
            "schema": {
              "enum": [
                "MAIN",
                "SUB"
              ],
              "type": "string"
            }
          },
          {
            "description": "Defaults to returning both.",
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "ACTIVE",
                "CLOSED"
              ],
              "type": "string"
            }
          },
          {
            "description": "The nextCursor from the previous page. Omit it for the first page. Treat it as opaque.",
            "example": "f39b0c74-51ae-4d82-9b06-3c7e2a5d1f80",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Rows per page, 1-100. Defaults to 25.",
            "example": 25,
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "items": [
                      {
                        "accountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                        "balance": {
                          "available": "1000.00",
                          "reserved": "0.00",
                          "total": "1000.00"
                        },
                        "capabilities": {
                          "holdCrypto": true,
                          "holdSavings": false,
                          "receive": true,
                          "sendCrypto": true,
                          "sendExternal": false,
                          "sendInternal": true
                        },
                        "createdAt": "2026-08-14T08:42:11.000Z",
                        "currency": "EUR",
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "externalRef": "acme:payroll-eur",
                        "iban": {
                          "active": false,
                          "bic": "TCBKBHBMXXX",
                          "holderName": "Fatima Al-Khalifa",
                          "iban": "BH29TCBK00001234567890"
                        },
                        "label": "Payroll reserve",
                        "localRails": [
                          {
                            "active": false,
                            "bankAddress": "Wiesenstrasse 17, 8952 Schlieren, Switzerland",
                            "bankName": "InCore Bank AG",
                            "beneficiaryName": "Fatima Al-Khalifa",
                            "bic": "INCOCHZZ",
                            "currency": "EUR",
                            "iban": "CH0508799123456789012",
                            "paymentReference": "TCB-7K2M9QXA",
                            "rail": "SEPA / SEPA Instant"
                          }
                        ],
                        "ownerId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                        "ownerType": "SUB_CLIENT",
                        "role": "MAIN",
                        "status": "ACTIVE"
                      }
                    ],
                    "nextCursor": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfAccountsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of accounts"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/accounts",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/accounts",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/accounts",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/accounts",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List accounts",
        "tags": [
          "Accounts"
        ]
      },
      "post": {
        "description": "An account holds one currency account per currency. Opens the owner's account in `currency` if it holds none (201), or returns the one it already holds (200) — calling it twice never opens a second. To hold the same currency separately, open another account. `label` and `externalRef` apply only to an account this call opens. There is no role field; sending one fails with ACCOUNT_MAIN_EXISTS.",
        "operationId": "create-account",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. A key is remembered for 24 hours from the first call; after that it is forgotten and reusing it starts a new request.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "currency": "EUR",
                "externalRef": "acme:payroll-eur",
                "idempotencyKey": "acme-2026-09-02-0001",
                "label": "Payroll reserve",
                "requestIban": true
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerAccountDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "accountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                    "balance": {
                      "available": "1000.00",
                      "reserved": "0.00",
                      "total": "1000.00"
                    },
                    "capabilities": {
                      "holdCrypto": true,
                      "holdSavings": false,
                      "receive": true,
                      "sendCrypto": true,
                      "sendExternal": false,
                      "sendInternal": true
                    },
                    "createdAt": "2026-08-14T08:42:11.000Z",
                    "currency": "EUR",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "externalRef": "acme:payroll-eur",
                    "iban": {
                      "active": false,
                      "bic": "TCBKBHBMXXX",
                      "holderName": "Fatima Al-Khalifa",
                      "iban": "BH29TCBK00001234567890"
                    },
                    "label": "Payroll reserve",
                    "localRails": [
                      {
                        "active": false,
                        "bankAddress": "Wiesenstrasse 17, 8952 Schlieren, Switzerland",
                        "bankName": "InCore Bank AG",
                        "beneficiaryName": "Fatima Al-Khalifa",
                        "bic": "INCOCHZZ",
                        "currency": "EUR",
                        "iban": "CH0508799123456789012",
                        "paymentReference": "TCB-7K2M9QXA",
                        "rail": "SEPA / SEPA Instant"
                      }
                    ],
                    "ownerId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                    "ownerType": "SUB_CLIENT",
                    "role": "MAIN",
                    "status": "ACTIVE"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerAccountResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The owner already holds this currency; that account, unchanged"
          },
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "accountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                    "balance": {
                      "available": "1000.00",
                      "reserved": "0.00",
                      "total": "1000.00"
                    },
                    "capabilities": {
                      "holdCrypto": true,
                      "holdSavings": false,
                      "receive": true,
                      "sendCrypto": true,
                      "sendExternal": false,
                      "sendInternal": true
                    },
                    "createdAt": "2026-08-14T08:42:11.000Z",
                    "currency": "EUR",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "externalRef": "acme:payroll-eur",
                    "iban": {
                      "active": false,
                      "bic": "TCBKBHBMXXX",
                      "holderName": "Fatima Al-Khalifa",
                      "iban": "BH29TCBK00001234567890"
                    },
                    "label": "Payroll reserve",
                    "localRails": [
                      {
                        "active": false,
                        "bankAddress": "Wiesenstrasse 17, 8952 Schlieren, Switzerland",
                        "bankName": "InCore Bank AG",
                        "beneficiaryName": "Fatima Al-Khalifa",
                        "bic": "INCOCHZZ",
                        "currency": "EUR",
                        "iban": "CH0508799123456789012",
                        "paymentReference": "TCB-7K2M9QXA",
                        "rail": "SEPA / SEPA Instant"
                      }
                    ],
                    "ownerId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                    "ownerType": "SUB_CLIENT",
                    "role": "MAIN",
                    "status": "ACTIVE"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerAccountResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Account opened"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/accounts",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "CURRENCY_NOT_SUPPORTED"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/accounts",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/accounts",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/accounts",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "ACCOUNT_EXTERNAL_REF_TAKEN or ACCOUNT_MAIN_EXISTS"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/accounts",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Open an account in a currency",
        "tags": [
          "Accounts"
        ]
      }
    },
    "/api/partner/v1/accounts/{id}": {
      "get": {
        "description": "One of the acting principal's own accounts, with its balance, its IBAN if it has one, and what may be done with it today. An account belonging to any other tree — or to a sub-client you are not acting for — answers 404 rather than 403, so an id cannot be probed for existence.",
        "operationId": "get-account",
        "parameters": [
          {
            "description": "The account id, as returned by GET /accounts.",
            "example": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "accountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                    "balance": {
                      "available": "1000.00",
                      "reserved": "0.00",
                      "total": "1000.00"
                    },
                    "capabilities": {
                      "holdCrypto": true,
                      "holdSavings": false,
                      "receive": true,
                      "sendCrypto": true,
                      "sendExternal": false,
                      "sendInternal": true
                    },
                    "createdAt": "2026-08-14T08:42:11.000Z",
                    "currency": "EUR",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "externalRef": "acme:payroll-eur",
                    "iban": {
                      "active": false,
                      "bic": "TCBKBHBMXXX",
                      "holderName": "Fatima Al-Khalifa",
                      "iban": "BH29TCBK00001234567890"
                    },
                    "label": "Payroll reserve",
                    "localRails": [
                      {
                        "active": false,
                        "bankAddress": "Wiesenstrasse 17, 8952 Schlieren, Switzerland",
                        "bankName": "InCore Bank AG",
                        "beneficiaryName": "Fatima Al-Khalifa",
                        "bic": "INCOCHZZ",
                        "currency": "EUR",
                        "iban": "CH0508799123456789012",
                        "paymentReference": "TCB-7K2M9QXA",
                        "rail": "SEPA / SEPA Instant"
                      }
                    ],
                    "ownerId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                    "ownerType": "SUB_CLIENT",
                    "role": "MAIN",
                    "status": "ACTIVE"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerAccountResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The account"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/accounts/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/accounts/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/accounts/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "ACCOUNT_NOT_FOUND"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/accounts/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one account by id",
        "tags": [
          "Accounts"
        ]
      }
    },
    "/api/partner/v1/accounts/{id}/close": {
      "post": {
        "description": "Requires a zero balance. A MAIN cannot close while any SUB in that currency is open, or while its owner is still active — close the sub-client instead. Your own MAIN cannot be closed through this route at all.",
        "operationId": "close-account",
        "parameters": [
          {
            "description": "The account id.",
            "example": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Your own key for this request, 1-100 characters. Required: this route takes no body, so the header is the only place to send it. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. A key is remembered for 24 hours from the first call; after that it is forgotten and reusing it starts a new request.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "accountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                    "balance": {
                      "available": "1000.00",
                      "reserved": "0.00",
                      "total": "1000.00"
                    },
                    "capabilities": {
                      "holdCrypto": true,
                      "holdSavings": false,
                      "receive": true,
                      "sendCrypto": true,
                      "sendExternal": false,
                      "sendInternal": true
                    },
                    "createdAt": "2026-08-14T08:42:11.000Z",
                    "currency": "EUR",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "externalRef": "acme:payroll-eur",
                    "iban": {
                      "active": false,
                      "bic": "TCBKBHBMXXX",
                      "holderName": "Fatima Al-Khalifa",
                      "iban": "BH29TCBK00001234567890"
                    },
                    "label": "Payroll reserve",
                    "localRails": [
                      {
                        "active": false,
                        "bankAddress": "Wiesenstrasse 17, 8952 Schlieren, Switzerland",
                        "bankName": "InCore Bank AG",
                        "beneficiaryName": "Fatima Al-Khalifa",
                        "bic": "INCOCHZZ",
                        "currency": "EUR",
                        "iban": "CH0508799123456789012",
                        "paymentReference": "TCB-7K2M9QXA",
                        "rail": "SEPA / SEPA Instant"
                      }
                    ],
                    "ownerId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                    "ownerType": "SUB_CLIENT",
                    "role": "MAIN",
                    "status": "ACTIVE"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerAccountResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Account closed"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/accounts/{id}/close",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/accounts/{id}/close",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/accounts/{id}/close",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/accounts/{id}/close",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "ACCOUNT_HAS_BALANCE, ACCOUNT_HAS_OPEN_SUBS or ACCOUNT_MAIN_NOT_CLOSABLE"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/accounts/{id}/close",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Close an account",
        "tags": [
          "Accounts"
        ]
      }
    },
    "/api/partner/v1/accounts/{id}/iban": {
      "post": {
        "description": "Every account receives on an IBAN from the moment it is opened, so this returns the account with its IBAN, issuing one only if the account somehow has none. Calling it again returns the same IBAN. The holder name is always the owner's verified legal name, never the account label.",
        "operationId": "issue-iban",
        "parameters": [
          {
            "description": "The account id.",
            "example": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Your own key for this request, 1-100 characters. Required: this route takes no body, so the header is the only place to send it. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. A key is remembered for 24 hours from the first call; after that it is forgotten and reusing it starts a new request.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "accountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                    "balance": {
                      "available": "1000.00",
                      "reserved": "0.00",
                      "total": "1000.00"
                    },
                    "capabilities": {
                      "holdCrypto": true,
                      "holdSavings": false,
                      "receive": true,
                      "sendCrypto": true,
                      "sendExternal": false,
                      "sendInternal": true
                    },
                    "createdAt": "2026-08-14T08:42:11.000Z",
                    "currency": "EUR",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "externalRef": "acme:payroll-eur",
                    "iban": {
                      "active": false,
                      "bic": "TCBKBHBMXXX",
                      "holderName": "Fatima Al-Khalifa",
                      "iban": "BH29TCBK00001234567890"
                    },
                    "label": "Payroll reserve",
                    "localRails": [
                      {
                        "active": false,
                        "bankAddress": "Wiesenstrasse 17, 8952 Schlieren, Switzerland",
                        "bankName": "InCore Bank AG",
                        "beneficiaryName": "Fatima Al-Khalifa",
                        "bic": "INCOCHZZ",
                        "currency": "EUR",
                        "iban": "CH0508799123456789012",
                        "paymentReference": "TCB-7K2M9QXA",
                        "rail": "SEPA / SEPA Instant"
                      }
                    ],
                    "ownerId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                    "ownerType": "SUB_CLIENT",
                    "role": "MAIN",
                    "status": "ACTIVE"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerAccountResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The account, with its IBAN"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/accounts/{id}/iban",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/accounts/{id}/iban",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/accounts/{id}/iban",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/accounts/{id}/iban",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "IDEMPOTENCY_KEY_REUSED or IDEMPOTENT_REQUEST_IN_PROGRESS. ACCOUNT_ALREADY_HAS_IBAN is no longer returned."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/accounts/{id}/iban",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Return an account's IBAN",
        "tags": [
          "Accounts"
        ]
      }
    },
    "/api/partner/v1/beneficiaries": {
      "get": {
        "description": "Your registered destinations, oldest first. Removed destinations are not listed — fetch one by id to read it back after removal.",
        "operationId": "list-beneficiaries",
        "parameters": [
          {
            "description": "Return only destinations currently in this lifecycle state.",
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "PENDING_VERIFICATION",
                "PENDING_APPROVAL",
                "HOLD",
                "BLOCKED"
              ],
              "type": "string"
            }
          },
          {
            "description": "The nextCursor from the previous page. Omit it for the first page. Treat it as opaque.",
            "example": "9b3e5c17-2a80-4f64-b1d9-6c0e8a4f2d53",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Rows per page, 1-100. Defaults to 25.",
            "example": 25,
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "items": [
                      {
                        "addressFamily": "EVM",
                        "beneficiaryId": "9b3e5c17-2a80-4f64-b1d9-6c0e8a4f2d53",
                        "chain": null,
                        "createdAt": "2026-09-03T10:15:30.000Z",
                        "currency": "EUR",
                        "deletedAt": null,
                        "details": {
                          "bicSwift": "COBADEFFXXX",
                          "iban": "DE89370400440532013000"
                        },
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "extensibility": {
                          "extensible": false,
                          "reason": "OWNERSHIP_NOT_PROVEN"
                        },
                        "extensible": false,
                        "instrumentId": "1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97",
                        "kind": "FIAT_BANK",
                        "last4": "3000",
                        "name": "Acme Supplies GmbH",
                        "networks": [
                          {
                            "addedAt": "2026-10-21T10:15:30.000Z",
                            "chain": "ARBITRUM",
                            "id": "4f0c2a91-7d3e-4b58-9a16-2e8d5c7b0f34",
                            "screening": {
                              "at": "2026-09-02T10:15:30.000Z",
                              "result": "CLEAR"
                            },
                            "status": "ACTIVE"
                          }
                        ],
                        "ownership": {
                          "at": null,
                          "proven": false
                        },
                        "rail": "SEPA",
                        "reachableChains": [
                          "ETHEREUM",
                          "POLYGON",
                          "ARBITRUM"
                        ],
                        "screening": {
                          "status": "CLEAR"
                        },
                        "status": "PENDING_APPROVAL",
                        "usable": false,
                        "usableAt": null
                      }
                    ]
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfBeneficiariesResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of destinations"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List destinations",
        "tags": [
          "Destinations"
        ]
      },
      "post": {
        "description": "One call registers the payee and the destination itself — a bank account or a wallet. A destination is NEVER usable at registration: it must clear screening, TCB approval, and a holding period first. The response tells you where it stands; poll GET /beneficiaries/{id} or subscribe to the beneficiary.activated event for the moment it becomes usable. A wallet destination additionally requires the travelRule capture. Registering details you already hold live is refused with DUPLICATE_INSTRUMENT rather than saved twice.",
        "operationId": "register-beneficiary",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. A key is remembered for 24 hours from the first call; after that it is forgotten and reusing it starts a new request.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "entityType": "INDIVIDUAL",
                "idempotencyKey": "acme-payee-2026-09-03-0001",
                "instrument": {
                  "chain": "ETHEREUM",
                  "details": {},
                  "kind": "FIAT_BANK",
                  "networks": [
                    "ETHEREUM"
                  ],
                  "rail": "SEPA",
                  "travelRule": {}
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerBeneficiaryDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "addressFamily": "EVM",
                    "beneficiaryId": "9b3e5c17-2a80-4f64-b1d9-6c0e8a4f2d53",
                    "chain": null,
                    "createdAt": "2026-09-03T10:15:30.000Z",
                    "currency": "EUR",
                    "deletedAt": null,
                    "details": {
                      "bicSwift": "COBADEFFXXX",
                      "iban": "DE89370400440532013000"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "extensibility": {
                      "extensible": false,
                      "reason": "OWNERSHIP_NOT_PROVEN"
                    },
                    "extensible": false,
                    "instrumentId": "1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97",
                    "kind": "FIAT_BANK",
                    "last4": "3000",
                    "name": "Acme Supplies GmbH",
                    "networks": [
                      {
                        "addedAt": "2026-10-21T10:15:30.000Z",
                        "chain": "ARBITRUM",
                        "id": "4f0c2a91-7d3e-4b58-9a16-2e8d5c7b0f34",
                        "screening": {
                          "at": "2026-09-02T10:15:30.000Z",
                          "result": "CLEAR"
                        },
                        "status": "ACTIVE"
                      }
                    ],
                    "ownership": {
                      "at": null,
                      "proven": false
                    },
                    "rail": "SEPA",
                    "reachableChains": [
                      "ETHEREUM",
                      "POLYGON",
                      "ARBITRUM"
                    ],
                    "screening": {
                      "status": "CLEAR"
                    },
                    "status": "PENDING_APPROVAL",
                    "usable": false,
                    "usableAt": null,
                    "warnings": [
                      {
                        "code": "LOOKALIKE"
                      }
                    ]
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerBeneficiaryCreatedResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Destination registered — pending its controls"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Validation failed (registry refusal, missing travelRule, or INTERNAL_TCB kind)"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "DUPLICATE_INSTRUMENT, IDEMPOTENCY_KEY_REUSED or IDEMPOTENT_REQUEST_IN_PROGRESS"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Register a payout destination",
        "tags": [
          "Destinations"
        ]
      }
    },
    "/api/partner/v1/beneficiaries/address-info": {
      "get": {
        "description": "What an address is before you register it: its family, every network its format is valid on, the networks TCB sends on (the ones instrument.networks may name), and the networks where it carries contract code. Saves nothing.",
        "operationId": "get-address-info",
        "parameters": [
          {
            "description": "The wallet address to classify.",
            "example": "0x8Ba1f109551bD432803012645Ac136ddd64DBA72",
            "in": "query",
            "name": "address",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "The memo or tag, for a network that carries one.",
            "in": "query",
            "name": "memo",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "checksumAddress": "0x8Ba1f109551bD432803012645Ac136ddd64DBA72",
                    "contractOn": [
                      "ETHEREUM"
                    ],
                    "family": "EVM",
                    "reachableChains": [
                      "ETHEREUM"
                    ],
                    "unknownOn": [
                      "ETHEREUM"
                    ],
                    "validChains": [
                      "ETHEREUM"
                    ]
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerAddressInfoResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The address facts"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries/address-info",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "address missing or too long"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries/address-info",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries/address-info",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries/address-info",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Classify a wallet address",
        "tags": [
          "Destinations"
        ]
      }
    },
    "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/networks": {
      "post": {
        "description": "Makes a registered wallet destination payable on one more network of its address family. The destination must be extensible — a self-hosted wallet with its ownership proven and no contract code — and the network must be one of its reachableChains. The network lands PENDING_APPROVAL and becomes ACTIVE once TCB approves it; the destination itself keeps its status, and no new holding period starts.",
        "operationId": "add-beneficiary-network",
        "parameters": [
          {
            "description": "The destination id.",
            "in": "path",
            "name": "beneficiaryId",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "The instrumentId of the wallet destination.",
            "in": "path",
            "name": "iid",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "chain": "BASE"
              },
              "schema": {
                "$ref": "#/components/schemas/AddPartnerBeneficiaryNetworkDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "addressFamily": "EVM",
                    "beneficiaryId": "9b3e5c17-2a80-4f64-b1d9-6c0e8a4f2d53",
                    "chain": null,
                    "createdAt": "2026-09-03T10:15:30.000Z",
                    "currency": "EUR",
                    "deletedAt": null,
                    "details": {
                      "bicSwift": "COBADEFFXXX",
                      "iban": "DE89370400440532013000"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "extensibility": {
                      "extensible": false,
                      "reason": "OWNERSHIP_NOT_PROVEN"
                    },
                    "extensible": false,
                    "instrumentId": "1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97",
                    "kind": "FIAT_BANK",
                    "last4": "3000",
                    "name": "Acme Supplies GmbH",
                    "network": {
                      "chain": "BASE",
                      "status": "PENDING_APPROVAL"
                    },
                    "networks": [
                      {
                        "addedAt": "2026-10-21T10:15:30.000Z",
                        "chain": "ARBITRUM",
                        "id": "4f0c2a91-7d3e-4b58-9a16-2e8d5c7b0f34",
                        "screening": {
                          "at": "2026-09-02T10:15:30.000Z",
                          "result": "CLEAR"
                        },
                        "status": "ACTIVE"
                      }
                    ],
                    "ownership": {
                      "at": null,
                      "proven": false
                    },
                    "rail": "SEPA",
                    "reachableChains": [
                      "ETHEREUM",
                      "POLYGON",
                      "ARBITRUM"
                    ],
                    "screening": {
                      "status": "CLEAR"
                    },
                    "status": "PENDING_APPROVAL",
                    "usable": false,
                    "usableAt": null
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerBeneficiaryNetworkAddedResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Network added, awaiting TCB approval"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/networks",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "NETWORK_NOT_EXTENSIBLE (network outside the address family) or NETWORK_NOT_REACHABLE"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/networks",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/networks",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/networks",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "BENEFICIARY_NOT_FOUND"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/networks",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "NETWORK_NOT_EXTENSIBLE, NETWORK_NOT_REACHABLE (contract code on that network), NETWORK_ALREADY_ACTIVE, NETWORK_PENDING_APPROVAL, NETWORK_NOT_ADDED, DUPLICATE_INSTRUMENT (another wallet of this destination already pays the address on that network) or INSTRUMENT_NOT_MUTABLE (the wallet is blocked, superseded or removed)"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/networks",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Add a network to a wallet destination",
        "tags": [
          "Destinations"
        ]
      }
    },
    "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/networks/{chain}": {
      "delete": {
        "description": "Stops payouts on one network of a wallet destination. The network row is kept, with status RETIRED, and can be added again later. The last ACTIVE network cannot be retired: remove the destination instead.",
        "operationId": "retire-beneficiary-network",
        "parameters": [
          {
            "description": "The destination id.",
            "in": "path",
            "name": "beneficiaryId",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "The instrumentId of the wallet destination.",
            "in": "path",
            "name": "iid",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "The network to retire.",
            "in": "path",
            "name": "chain",
            "required": true,
            "schema": {
              "enum": [
                "ETHEREUM",
                "BITCOIN",
                "SOLANA",
                "POLYGON",
                "AVALANCHE",
                "ARBITRUM",
                "OPTIMISM",
                "BASE"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "addressFamily": "EVM",
                    "beneficiaryId": "9b3e5c17-2a80-4f64-b1d9-6c0e8a4f2d53",
                    "chain": null,
                    "createdAt": "2026-09-03T10:15:30.000Z",
                    "currency": "EUR",
                    "deletedAt": null,
                    "details": {
                      "bicSwift": "COBADEFFXXX",
                      "iban": "DE89370400440532013000"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "extensibility": {
                      "extensible": false,
                      "reason": "OWNERSHIP_NOT_PROVEN"
                    },
                    "extensible": false,
                    "instrumentId": "1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97",
                    "kind": "FIAT_BANK",
                    "last4": "3000",
                    "name": "Acme Supplies GmbH",
                    "networks": [
                      {
                        "addedAt": "2026-10-21T10:15:30.000Z",
                        "chain": "ARBITRUM",
                        "id": "4f0c2a91-7d3e-4b58-9a16-2e8d5c7b0f34",
                        "screening": {
                          "at": "2026-09-02T10:15:30.000Z",
                          "result": "CLEAR"
                        },
                        "status": "ACTIVE"
                      }
                    ],
                    "ownership": {
                      "at": null,
                      "proven": false
                    },
                    "rail": "SEPA",
                    "reachableChains": [
                      "ETHEREUM",
                      "POLYGON",
                      "ARBITRUM"
                    ],
                    "screening": {
                      "status": "CLEAR"
                    },
                    "status": "PENDING_APPROVAL",
                    "usable": false,
                    "usableAt": null
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerBeneficiaryResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Network retired"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/networks/{chain}",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Unknown network"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/networks/{chain}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/networks/{chain}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/networks/{chain}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "BENEFICIARY_NOT_FOUND, or the destination has no such network"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/networks/{chain}",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "LAST_NETWORK, NETWORK_ALREADY_RETIRED or INSTRUMENT_NOT_MUTABLE"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/networks/{chain}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Retire a network of a wallet destination",
        "tags": [
          "Destinations"
        ]
      }
    },
    "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/ownership-proof": {
      "post": {
        "description": "Send the challenge message and the wallet's signature of it. A valid proof sets ownership.proven and recomputes extensible.",
        "operationId": "submit-ownership-proof",
        "parameters": [
          {
            "description": "The destination id.",
            "in": "path",
            "name": "beneficiaryId",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "The instrumentId of the wallet destination.",
            "in": "path",
            "name": "iid",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "signature": "0x4f6c…1b"
              },
              "schema": {
                "$ref": "#/components/schemas/SubmitPartnerOwnershipProofDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "addressFamily": "EVM",
                    "beneficiaryId": "9b3e5c17-2a80-4f64-b1d9-6c0e8a4f2d53",
                    "chain": null,
                    "createdAt": "2026-09-03T10:15:30.000Z",
                    "currency": "EUR",
                    "deletedAt": null,
                    "details": {
                      "bicSwift": "COBADEFFXXX",
                      "iban": "DE89370400440532013000"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "extensibility": {
                      "extensible": false,
                      "reason": "OWNERSHIP_NOT_PROVEN"
                    },
                    "extensible": false,
                    "instrumentId": "1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97",
                    "kind": "FIAT_BANK",
                    "last4": "3000",
                    "name": "Acme Supplies GmbH",
                    "networks": [
                      {
                        "addedAt": "2026-10-21T10:15:30.000Z",
                        "chain": "ARBITRUM",
                        "id": "4f0c2a91-7d3e-4b58-9a16-2e8d5c7b0f34",
                        "screening": {
                          "at": "2026-09-02T10:15:30.000Z",
                          "result": "CLEAR"
                        },
                        "status": "ACTIVE"
                      }
                    ],
                    "ownership": {
                      "at": null,
                      "proven": false
                    },
                    "rail": "SEPA",
                    "reachableChains": [
                      "ETHEREUM",
                      "POLYGON",
                      "ARBITRUM"
                    ],
                    "screening": {
                      "status": "CLEAR"
                    },
                    "status": "PENDING_APPROVAL",
                    "usable": false,
                    "usableAt": null
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerBeneficiaryResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Proof accepted"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/ownership-proof",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "OWNERSHIP_PROOF_INVALID (expired or foreign challenge, or a signature by another key), or NETWORK_NOT_EXTENSIBLE"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/ownership-proof",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/ownership-proof",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/ownership-proof",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "BENEFICIARY_NOT_FOUND"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/ownership-proof",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "INSTRUMENT_NOT_MUTABLE: the destination is blocked, superseded or removed"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/ownership-proof",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Submit an ownership proof",
        "tags": [
          "Destinations"
        ]
      }
    },
    "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/ownership-proof/challenge": {
      "get": {
        "description": "The message the wallet's key signs (personal_sign, EIP-191) to prove the payee controls the address. Valid for 15 minutes and only for this destination. Offered for a wallet whose address is shared by several networks (addressFamily set).",
        "operationId": "get-ownership-proof-challenge",
        "parameters": [
          {
            "description": "The destination id.",
            "in": "path",
            "name": "beneficiaryId",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "The instrumentId of the wallet destination.",
            "in": "path",
            "name": "iid",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "expiresAt": "2026-09-02T10:15:30.000Z",
                    "message": "Three Comma Bank: I control this wallet and its private key.\nAddress: 0x8Ba1f109551bD432803012645Ac136ddd64DBA72\nPayee method: 1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97\nNonce: 3f9c0a…\nExpires: 2026-10-21T10:30:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerOwnershipChallengeResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The challenge"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/ownership-proof/challenge",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "NETWORK_NOT_EXTENSIBLE (a single-network address), or not a wallet destination"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/ownership-proof/challenge",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/ownership-proof/challenge",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/ownership-proof/challenge",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "BENEFICIARY_NOT_FOUND"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/ownership-proof/challenge",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "INSTRUMENT_NOT_MUTABLE: the destination is blocked, superseded or removed"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries/{beneficiaryId}/instruments/{iid}/ownership-proof/challenge",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch an ownership-proof challenge",
        "tags": [
          "Destinations"
        ]
      }
    },
    "/api/partner/v1/beneficiaries/{id}": {
      "delete": {
        "description": "Takes the destination out of use. The record is kept — the response and later reads show it with deletedAt set — and nothing can be sent to it once removed. Removing an already-removed destination answers its current state, so a retry is safe.",
        "operationId": "remove-beneficiary",
        "parameters": [
          {
            "description": "The destination id, as returned by POST /beneficiaries.",
            "example": "9b3e5c17-2a80-4f64-b1d9-6c0e8a4f2d53",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "addressFamily": "EVM",
                    "beneficiaryId": "9b3e5c17-2a80-4f64-b1d9-6c0e8a4f2d53",
                    "chain": null,
                    "createdAt": "2026-09-03T10:15:30.000Z",
                    "currency": "EUR",
                    "deletedAt": null,
                    "details": {
                      "bicSwift": "COBADEFFXXX",
                      "iban": "DE89370400440532013000"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "extensibility": {
                      "extensible": false,
                      "reason": "OWNERSHIP_NOT_PROVEN"
                    },
                    "extensible": false,
                    "instrumentId": "1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97",
                    "kind": "FIAT_BANK",
                    "last4": "3000",
                    "name": "Acme Supplies GmbH",
                    "networks": [
                      {
                        "addedAt": "2026-10-21T10:15:30.000Z",
                        "chain": "ARBITRUM",
                        "id": "4f0c2a91-7d3e-4b58-9a16-2e8d5c7b0f34",
                        "screening": {
                          "at": "2026-09-02T10:15:30.000Z",
                          "result": "CLEAR"
                        },
                        "status": "ACTIVE"
                      }
                    ],
                    "ownership": {
                      "at": null,
                      "proven": false
                    },
                    "rail": "SEPA",
                    "reachableChains": [
                      "ETHEREUM",
                      "POLYGON",
                      "ARBITRUM"
                    ],
                    "screening": {
                      "status": "CLEAR"
                    },
                    "status": "PENDING_APPROVAL",
                    "usable": false,
                    "usableAt": null
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerBeneficiaryResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Destination removed"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/beneficiaries/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/beneficiaries/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/beneficiaries/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "BENEFICIARY_NOT_FOUND"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/beneficiaries/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Remove a destination",
        "tags": [
          "Destinations"
        ]
      },
      "get": {
        "description": "The destination in its current state — where it stands in the lifecycle, and whether a payout may name it right now (usable). A destination belonging to any other principal answers 404 rather than 403, so an id cannot be probed for existence. Removed destinations stay readable, with deletedAt set.",
        "operationId": "get-beneficiary",
        "parameters": [
          {
            "description": "The destination id, as returned by POST /beneficiaries.",
            "example": "9b3e5c17-2a80-4f64-b1d9-6c0e8a4f2d53",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "addressFamily": "EVM",
                    "beneficiaryId": "9b3e5c17-2a80-4f64-b1d9-6c0e8a4f2d53",
                    "chain": null,
                    "createdAt": "2026-09-03T10:15:30.000Z",
                    "currency": "EUR",
                    "deletedAt": null,
                    "details": {
                      "bicSwift": "COBADEFFXXX",
                      "iban": "DE89370400440532013000"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "extensibility": {
                      "extensible": false,
                      "reason": "OWNERSHIP_NOT_PROVEN"
                    },
                    "extensible": false,
                    "instrumentId": "1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97",
                    "kind": "FIAT_BANK",
                    "last4": "3000",
                    "name": "Acme Supplies GmbH",
                    "networks": [
                      {
                        "addedAt": "2026-10-21T10:15:30.000Z",
                        "chain": "ARBITRUM",
                        "id": "4f0c2a91-7d3e-4b58-9a16-2e8d5c7b0f34",
                        "screening": {
                          "at": "2026-09-02T10:15:30.000Z",
                          "result": "CLEAR"
                        },
                        "status": "ACTIVE"
                      }
                    ],
                    "ownership": {
                      "at": null,
                      "proven": false
                    },
                    "rail": "SEPA",
                    "reachableChains": [
                      "ETHEREUM",
                      "POLYGON",
                      "ARBITRUM"
                    ],
                    "screening": {
                      "status": "CLEAR"
                    },
                    "status": "PENDING_APPROVAL",
                    "usable": false,
                    "usableAt": null
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerBeneficiaryResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The destination"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "BENEFICIARY_NOT_FOUND"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/beneficiaries/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one destination by id",
        "tags": [
          "Destinations"
        ]
      }
    },
    "/api/partner/v1/conversions": {
      "post": {
        "description": "Sells an exact amount of fromCurrency for toCurrency between two accounts you already hold, executed by TCB's trading pipeline. It is a stage in its own right, not something the deposit or withdrawal endpoints do for you: convert first, read the rate you got, then deposit or withdraw. An idempotency key is MANDATORY: send it as the Idempotency-Key header or as the idempotencyKey body field. Replaying a key returns the original result without re-executing; reusing one with different parameters is rejected with IDEMPOTENCY_KEY_REUSED. The rate comes only from an external venue that prices independently of TCB. When no such venue can price the pair, the request is refused with 503 PRICING_UNAVAILABLE and nothing is converted — TCB never prices a conversion from an internal table instead. READ rate.pricingModel ON EVERY RESPONSE: MARKET means a venue quoted it; any other value (SIMULATED appears only on conversions settled before 2026-09-06) is not a market rate and must never be presented or reported as one. Every response also carries the pilot disclosure. Converting into a currency and straight back out is priced twice. A shared trading risk check limits order rate, size and daily volume, scoped to your client principal — every sub-account shares one bucket. A refusal is 400 CONVERSION_RISK_REJECTED with details.reasons listing the failed checks. Name toAccountId to end the conversion in another account of your tree: one of your own fiat accounts in toCurrency, or a sub-client's. Into a sub-client's account the converted amount lands in your own account first and moves on in the same step that settles the conversion; transferId names that move. A key naming toAccountId needs transfer:execute as well as trade:execute. To see the rate and the commission before you convert, quote the conversion first (POST /conversions/quote) and name the quoteId here: the conversion then executes at that quote and is never re-quoted. Every response states the commission charged (commission) and networkFee, which is always null: TCB covers any network cost.",
        "operationId": "create-conversion",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. The key is remembered permanently: it is recorded against the movement it created, so a replay years later still resolves to that one movement.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "1000.00",
                "fromCurrency": "USDC",
                "idempotencyKey": "acme-conversion-2026-08-31-0001",
                "quoteId": "5e2c9a17-8b40-4d63-a1f8-3c7e0b9d2f46",
                "sourceAccountId": "4d80f3b6-9a17-4c25-8e93-0b6d1f7a3c58",
                "targetAccountId": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
                "toAccountId": "9c3e5a1f-2b7d-4e60-8a94-6f1d0c2b7e35",
                "toCurrency": "USD"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerConversionDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "commission": {
                      "amount": "2.5",
                      "currency": "USD"
                    },
                    "conversionId": "6a4d0f38-7c15-42be-9038-4b7e1c6a2d59",
                    "createdAt": "2026-09-02T10:15:28.000Z",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "from": {
                      "currency": "USDC",
                      "filledAmount": "1000",
                      "requestedAmount": "1000",
                      "unfilledAmount": "0"
                    },
                    "idempotencyKey": "acme-conversion-2026-08-31-0001",
                    "networkFee": null,
                    "rate": {
                      "executed": "0.9998",
                      "note": "This rate came from a venue that prices independently of TCB.",
                      "pricingModel": "MARKET",
                      "quoted": "0.9999",
                      "quotedExpiresAt": "2026-09-02T10:15:58.000Z"
                    },
                    "replayed": false,
                    "settledAt": "2026-09-02T10:15:33.000Z",
                    "status": "SETTLED",
                    "to": {
                      "amount": "999.80",
                      "currency": "USD"
                    },
                    "toAccountId": "9c3e5a1f-2b7d-4e60-8a94-6f1d0c2b7e35",
                    "tradeOrderId": "e5c17a03-9d42-4b68-8f31-0a7c2e6b4d95",
                    "transferId": "2f8b6d14-7a3c-4e91-b5d0-8c1e4f7a9b26"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerConversionResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Conversion settled, or the original result replayed"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/conversions",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Missing/invalid idempotency key, same currency both sides, an amount finer than the currency settles at or not exactly representable in the order contract, insufficient balance, a trading risk refusal, or CONVERSION_CAP_EXCEEDED — the conversion would cross a money cap set for your account on the sell side (details name the ceiling and the figure). Or CONVERSION_DESTINATION_NOT_SUPPORTED — toAccountId is not a fiat account. Nothing was converted and the key stays usable."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/conversions",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/conversions",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Account not usable, or INSUFFICIENT_SCOPE — the key lacks trade:execute, or names toAccountId without transfer:execute."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/conversions",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No usable source or target account of yours. The account your crypto deposit address credits is one of yours and resolves here; an account in another client's tree, or a personal account of your operating user, does not. The same answer for a toAccountId that is not in your tree. QUOTE_NOT_FOUND: no conversion quote with that quoteId."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/conversions",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Key reused with different parameters, still in flight, an account is ambiguous (CONVERSION_ACCOUNT_AMBIGUOUS: you hold more than one active account in that currency — details.accountIds names each of them; name one), a currency is not configured, or no enabled venue is configured for the pair (a provisioning gap — retrying will not change it). Or CONVERSION_DESTINATION_CONFLICT — toAccountId is one of your own accounts and targetAccountId names another. Or SUB_CLIENT_CAPABILITY_UNAVAILABLE — the sub-client named by toAccountId cannot receive. With a quoteId: QUOTE_EXPIRED, QUOTE_ALREADY_USED, QUOTE_MISMATCH (details.fields names what differs from the quoted request) or QUOTE_TERMS_CHANGED (the commission terms changed since the quote). Nothing was converted."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/conversions",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          },
          "500": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTERNAL_ERROR",
                  "error": "Internal Server Error",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/conversions",
                  "statusCode": 500,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "CONVERSION_FAILED — nothing moved, safe to retry. Or CONVERSION_FAILED_PENDING_COMPENSATION — the order moved money (including a partial fill) and the outcome could not be completed or established. Or CONVERSION_SETTLEMENT_NOT_RECORDED — it DID complete and only the record of it failed. On the latter two an OPERATOR resolves it; NOTHING RESOLVES IT AUTOMATICALLY, and do NOT retry with a new key, which would place a second order. Polling this key will not change the answer until an operator has acted."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "code": "CHAIN_UNAVAILABLE",
                  "error": "Service Unavailable",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/conversions",
                  "statusCode": 503,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "PRICING_UNAVAILABLE — no market venue returned a usable quote right now, and TCB does not price a conversion from an internal table instead (details.pair names the pair). Or CONVERSION_QUOTE_EXPIRED — the quote lapsed and re-quoting did not produce a usable price (or the quote you named lapsed in the moment before execution; a quoted conversion is never re-quoted), so no order was placed. Nothing was converted; both are safe to retry."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Convert one currency you hold into another",
        "tags": [
          "Conversions"
        ]
      }
    },
    "/api/partner/v1/conversions/quote": {
      "post": {
        "description": "Prices the conversion you are about to make, without making it: the rate a market venue quotes for it, the commission it will be charged at that rate, and what it would credit. Nothing is converted and no idempotency key is needed. The request is checked exactly as the conversion would be (both accounts, your money cap, the trading risk check), so a refusal here is the refusal the conversion would get. The quote holds until expiresAt: the venue's own quote window, and never more than 60 seconds. Name its quoteId on POST /conversions to execute at this quote: the conversion must repeat the quoted request and can use the quote once, and it is never re-quoted. Quoting first is optional and recommended: it is how you see the rate and the commission before you commit. A quote reserves nothing: your balance and the risk check are checked again when you convert. Like every conversion rate, the quoted one comes only from a venue that prices independently of TCB (rate.pricingModel MARKET).",
        "operationId": "quote-conversion",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "1000.00",
                "fromCurrency": "USDC",
                "sourceAccountId": "4d80f3b6-9a17-4c25-8e93-0b6d1f7a3c58",
                "targetAccountId": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
                "toAccountId": "9c3e5a1f-2b7d-4e60-8a94-6f1d0c2b7e35",
                "toCurrency": "USD"
              },
              "schema": {
                "$ref": "#/components/schemas/PartnerConversionQuoteRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "commission": {
                      "amount": "2.5",
                      "currency": "USD"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "expiresAt": "2026-10-30T10:15:58.000Z",
                    "from": {
                      "amount": "1000",
                      "currency": "USDC"
                    },
                    "networkFee": null,
                    "quoteId": "5e2c9a17-8b40-4d63-a1f8-3c7e0b9d2f46",
                    "rate": {
                      "note": "This rate came from a venue that prices independently of TCB.",
                      "pricingModel": "MARKET",
                      "quoted": "0.9999"
                    },
                    "receiveAmount": "997.40",
                    "toCurrency": "USD"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerConversionQuoteResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The conversion quoted: its rate, its commission, what it credits and until when"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/conversions/quote",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The refusals POST /conversions gives before converting: same currency both sides, an amount finer than the currency settles at or not exactly representable, insufficient balance, a trading risk refusal, CONVERSION_CAP_EXCEEDED, or CONVERSION_DESTINATION_NOT_SUPPORTED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/conversions/quote",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/conversions/quote",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Account not usable, or INSUFFICIENT_SCOPE (trade:execute; with toAccountId, transfer:execute too)."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/conversions/quote",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No usable source or target account of yours, or toAccountId not in your tree."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/conversions/quote",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "CONVERSION_ACCOUNT_AMBIGUOUS, a currency not configured, no enabled venue for the pair, CONVERSION_DESTINATION_CONFLICT or SUB_CLIENT_CAPABILITY_UNAVAILABLE."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/conversions/quote",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "code": "CHAIN_UNAVAILABLE",
                  "error": "Service Unavailable",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/conversions/quote",
                  "statusCode": 503,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "PRICING_UNAVAILABLE — no market venue returned a usable quote right now. Safe to retry."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Quote a conversion before making it",
        "tags": [
          "Conversions"
        ]
      }
    },
    "/api/partner/v1/conversions/{id}": {
      "get": {
        "description": "The conversion in its CURRENT state, whatever that is — including a terminal failure, reported here as the object rather than as an error. This is the fetch half of the thin webhook payloads (a *.settled / *.failed event carries only a resource pointer) and the poll surface the money errors point at.",
        "operationId": "get-conversion",
        "parameters": [
          {
            "description": "The conversionId returned when you created it, or carried by the event's resource pointer.",
            "example": "6a4d0f38-7c15-42be-9038-4b7e1c6a2d59",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "commission": {
                      "amount": "2.5",
                      "currency": "USD"
                    },
                    "conversionId": "6a4d0f38-7c15-42be-9038-4b7e1c6a2d59",
                    "createdAt": "2026-09-02T10:15:28.000Z",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "from": {
                      "currency": "USDC",
                      "filledAmount": "1000",
                      "requestedAmount": "1000",
                      "unfilledAmount": "0"
                    },
                    "idempotencyKey": "acme-conversion-2026-08-31-0001",
                    "networkFee": null,
                    "rate": {
                      "executed": "0.9998",
                      "note": "This rate came from a venue that prices independently of TCB.",
                      "pricingModel": "MARKET",
                      "quoted": "0.9999",
                      "quotedExpiresAt": "2026-09-02T10:15:58.000Z"
                    },
                    "replayed": false,
                    "settledAt": "2026-09-02T10:15:33.000Z",
                    "status": "SETTLED",
                    "to": {
                      "amount": "999.80",
                      "currency": "USD"
                    },
                    "toAccountId": "9c3e5a1f-2b7d-4e60-8a94-6f1d0c2b7e35",
                    "tradeOrderId": "e5c17a03-9d42-4b68-8f31-0a7c2e6b4d95",
                    "transferId": "2f8b6d14-7a3c-4e91-b5d0-8c1e4f7a9b26"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerConversionResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The conversion"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/conversions/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/conversions/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/conversions/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No conversion with that id in your scope"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/conversions/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one conversion by id",
        "tags": [
          "Conversions"
        ]
      }
    },
    "/api/partner/v1/crypto-deposit-addresses": {
      "post": {
        "description": "Issues the deposit address for one asset on one chain, creating the account arrivals are credited to at the same time. The address is static: calling this again for the same asset and chain returns the same address, whatever idempotency key the call carries. A confirmed on-chain transfer to it is credited to that account and announced by a crypto_deposit.credited webhook — see the crypto deposits guide for what happens to anything else that arrives.",
        "operationId": "create-crypto-deposit-address",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. A key is remembered for 24 hours from the first call; after that it is forgotten and reusing it starts a new request.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "asset": "USDC",
                "chain": "ARBITRUM",
                "idempotencyKey": "acme-crypto-address-0001"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerCryptoDepositAddressDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "accountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                    "address": "0x5c1f0a2b3d4e5f60718293a4b5c6d7e8f9012345",
                    "addressId": "9d2c6a4e-73b8-4e8b-a35c-4692b0f11d70",
                    "asset": "USDC",
                    "chain": "ARBITRUM",
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerCryptoDepositAddressResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The address, newly issued or already held"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/crypto-deposit-addresses",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/crypto-deposit-addresses",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/crypto-deposit-addresses",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/crypto-deposit-addresses",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "ASSET_NOT_SUPPORTED or CHAIN_NOT_SUPPORTED"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/crypto-deposit-addresses",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Get your deposit address",
        "tags": [
          "Crypto deposits"
        ]
      }
    },
    "/api/partner/v1/crypto-deposits": {
      "get": {
        "description": "Every recorded arrival at your deposit addresses, newest first — credited deposits and FAILED records alike. A deposit appears here the moment it is recorded; there is no POST, because a crypto deposit is initiated on-chain and the transfer itself is the request.",
        "operationId": "list-crypto-deposits",
        "parameters": [
          {
            "description": "The nextCursor from the previous page. Omit it for the first page. Treat it as opaque.",
            "example": "2b7e1c6a-2d59-46a4-8f38-7c1542be9038",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Rows per page, 1-100. Defaults to 25.",
            "example": 25,
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "items": [
                      {
                        "amount": "1000",
                        "asset": "USDC",
                        "chain": "ARBITRUM",
                        "creditedAccountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                        "creditedAt": {},
                        "cryptoDepositId": "2b7e1c6a-2d59-46a4-8f38-7c1542be9038",
                        "detectedAt": "2026-09-02T10:15:30.000Z",
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "status": "CREDITED",
                        "transferIndex": "2",
                        "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                      }
                    ],
                    "nextCursor": null
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfCryptoDepositsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of crypto deposits"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/crypto-deposits",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/crypto-deposits",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/crypto-deposits",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/crypto-deposits",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List crypto deposits",
        "tags": [
          "Crypto deposits"
        ]
      }
    },
    "/api/partner/v1/crypto-deposits/{id}": {
      "get": {
        "description": "The deposit in its current state, including a FAILED record, which is reported as the object rather than as an error. This is the fetch half of the thin crypto_deposit.credited webhook payload. The id is stable across replays of the same on-chain transfer.",
        "operationId": "get-crypto-deposit",
        "parameters": [
          {
            "description": "The cryptoDepositId from the list, or carried by the event's resource pointer.",
            "example": "2b7e1c6a-2d59-46a4-8f38-7c1542be9038",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1000",
                    "asset": "USDC",
                    "chain": "ARBITRUM",
                    "creditedAccountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                    "creditedAt": {},
                    "cryptoDepositId": "2b7e1c6a-2d59-46a4-8f38-7c1542be9038",
                    "detectedAt": "2026-09-02T10:15:30.000Z",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "status": "CREDITED",
                    "transferIndex": "2",
                    "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerCryptoDepositResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The deposit"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/crypto-deposits/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/crypto-deposits/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/crypto-deposits/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "CRYPTO_DEPOSIT_NOT_FOUND"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/crypto-deposits/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one crypto deposit by id",
        "tags": [
          "Crypto deposits"
        ]
      }
    },
    "/api/partner/v1/deposits": {
      "get": {
        "description": "Your vault deposits, newest first, each with its status on the one savings status vocabulary (QUEUED, PROCESSING, CREDIT_PENDING, COMPLETED, FAILED, REFUNDED, CANCELLED). Filter by status. Fetch one in full with GET /deposits/{id}.",
        "operationId": "list-deposits",
        "parameters": [
          {
            "description": "The nextCursor from the previous page. Omit it for the first page. Treat it as opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Rows per page, 1-100. Defaults to 25.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100,
              "type": "integer"
            }
          },
          {
            "description": "Only deposits in this status.",
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "QUEUED",
                "PROCESSING",
                "CREDIT_PENDING",
                "COMPLETED",
                "FAILED",
                "REFUNDED",
                "CANCELLED"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "items": [
                      {
                        "createdAt": "2026-10-06T09:12:44.000Z",
                        "currency": "USD",
                        "depositId": "2f6c9a41-3e58-4b70-9d12-6a8f0c3e5b71",
                        "requestedAmount": "1000",
                        "settledAt": "2026-10-06T09:12:51.000Z",
                        "shares": "999.876543210000000000000000",
                        "status": "COMPLETED",
                        "subAccountId": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395"
                      }
                    ]
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfPartnerVaultDepositsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of deposits"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/deposits",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "limit or status malformed (INVALID_AMOUNT)"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/deposits",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/deposits",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/deposits",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "code": "CHAIN_UNAVAILABLE",
                  "error": "Service Unavailable",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/deposits",
                  "statusCode": 503,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Chain read unavailable (CHAIN_UNAVAILABLE). Retry."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List your vault deposits",
        "tags": [
          "Deposits"
        ]
      },
      "post": {
        "description": "Converts your fiat into vault shares held in your vault sub-account. An idempotency key is MANDATORY: send it as the Idempotency-Key header or as the idempotencyKey body field. Replaying a key returns the original result without re-executing; reusing one with different parameters is rejected with IDEMPOTENCY_KEY_REUSED. Every response carries the pilot disclosure: the environment is a testnet and the yield is simulated, not earned.",
        "operationId": "create-deposit",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. The key is remembered permanently: it is recorded against the movement it created, so a replay years later still resolves to that one movement.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "1000.00",
                "currency": "USD",
                "idempotencyKey": "acme-deposit-2026-08-27-0001",
                "sourceAccountId": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
                "subAccountId": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerDepositDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1000",
                    "createdAt": "2026-09-02T10:15:28.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "depositId": "2f6c9a41-3e58-4b70-9d12-6a8f0c3e5b71",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "idempotencyKey": "acme-deposit-2026-08-27-0001",
                    "onchain": {
                      "depositTxHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396",
                      "mintTxHash": "0x9d20b7e548c1f36a0742e9bd35c108af62d497130ba85e6c2f9d40718ac35be2"
                    },
                    "replayed": false,
                    "settledAt": "2026-09-02T10:15:34.000Z",
                    "shares": {
                      "balance": "1024.518330000000000000000000",
                      "minted": "999.876543210000000000000000"
                    },
                    "status": "SETTLED",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerDepositResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Deposit settled, or the original result replayed"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/deposits",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Missing/invalid idempotency key, invalid request, SOURCE_ACCOUNT_NOT_USABLE — the named account is not a fiat account in that currency (the account your crypto deposit address credits is refused here by name: convert the balance first, then deposit the fiat) — or DEPOSIT_CAP_EXCEEDED — the deposit would cross a money cap set for your account (details name the ceiling and the figure). Nothing was charged and the key stays usable."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/deposits",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/deposits",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Wallet not allowlisted, or key lacks vault:deposit"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/deposits",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Key reused with different parameters, still in flight, custody records inconsistent, or TOKEN_ISSUANCE_PAUSED — TCB has paused issuance of this token. Nothing was charged either way; `details.idempotencyKeySpent` says whether your key survived. False: refused up front, nothing recorded, the same key is still good. True: the pause landed while the deposit was executing, so it is terminal FAILED and the next attempt needs a new key. A deposit submitted while the pause stands is refused again. Withdrawals and redemptions are not affected."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/deposits",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          },
          "500": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTERNAL_ERROR",
                  "error": "Internal Server Error",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/deposits",
                  "statusCode": 500,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "DEPOSIT_FAILED — nothing was charged, safe to retry. Or DEPOSIT_FAILED_PENDING_COMPENSATION — funds had moved and the unwind is unconfirmed. Or DEPOSIT_SETTLEMENT_NOT_RECORDED — it DID complete, your shares were minted, and only the record of it failed. On the latter two the intent is recorded for resolution — the compensation sweeper completes it automatically where the outcome can be proven, and escalates it to an operator otherwise. Do NOT retry with a new key, which would start a second deposit. Polling this key will not change the answer until it has been resolved: a compensable intent keeps returning this same failure, and a settlement-not-recorded one keeps returning 409 IDEMPOTENT_REQUEST_IN_PROGRESS even though the deposit completed."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "code": "CHAIN_UNAVAILABLE",
                  "error": "Service Unavailable",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/deposits",
                  "statusCode": 503,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Chain or gas pre-flight unavailable, or PARTNER_WALLET_PROVISIONING_FAILED — your custody wallet is created on your first deposit and that did not complete. Nothing charged and the idempotency key was not claimed: resend with the same key or a new one, parameters may change."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Deposit fiat into a curated vault",
        "tags": [
          "Deposits"
        ]
      }
    },
    "/api/partner/v1/deposits/{id}": {
      "get": {
        "description": "The deposit in its CURRENT state, whatever that is — including a terminal failure, reported here as the object rather than as an error. This is the fetch half of the thin webhook payloads (a *.settled / *.failed event carries only a resource pointer) and the poll surface the money errors point at.",
        "operationId": "get-deposit",
        "parameters": [
          {
            "description": "The depositId returned when you created it, or carried by the event's resource pointer.",
            "example": "2f6c9a41-3e58-4b70-9d12-6a8f0c3e5b71",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1000",
                    "createdAt": "2026-09-02T10:15:28.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "depositId": "2f6c9a41-3e58-4b70-9d12-6a8f0c3e5b71",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "idempotencyKey": "acme-deposit-2026-08-27-0001",
                    "onchain": {
                      "depositTxHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396",
                      "mintTxHash": "0x9d20b7e548c1f36a0742e9bd35c108af62d497130ba85e6c2f9d40718ac35be2"
                    },
                    "replayed": false,
                    "settledAt": "2026-09-02T10:15:34.000Z",
                    "shares": {
                      "balance": "1024.518330000000000000000000",
                      "minted": "999.876543210000000000000000"
                    },
                    "status": "SETTLED",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerDepositResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The deposit"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/deposits/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/deposits/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/deposits/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No deposit with that id in your scope"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/deposits/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one deposit by id",
        "tags": [
          "Deposits"
        ]
      }
    },
    "/api/partner/v1/me": {
      "get": {
        "description": "Identifies the authenticated principal — the integration smoke test. Your API key is the only credential: no browser session and no other headers are involved. Called with x-on-behalf-of it answers principalType SUB_CLIENT with that sub-client id, alongside your unchanged root clientAccountId. subtreeRestricted reports whether the key may act for every one of your sub-clients or only a subset.",
        "operationId": "get-me",
        "parameters": [
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "clientAccountId": "3a7e5c91-0d24-4b6f-8e13-5c9a2f7b1d04",
                    "environment": "test",
                    "keyPrefix": "test_A7fQ2xM",
                    "name": "Acme Payments",
                    "partnerId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "principalType": "PARTNER",
                    "scopes": [
                      "position:read",
                      "transaction:read",
                      "vault:deposit",
                      "vault:withdraw"
                    ],
                    "subClientId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                    "subtreeRestricted": false
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerMeResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Authenticated client identity"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/me",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Missing/invalid/revoked/expired key"
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/me",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Key lacks position:read scope"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/me",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Per-principal rate limit exceeded"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Identify the authenticated client principal",
        "tags": [
          "Identity"
        ]
      }
    },
    "/api/partner/v1/netting/agreements": {
      "get": {
        "description": "Agreements the acting node proposed or was proposed, newest first.",
        "operationId": "list-netting-agreements",
        "parameters": [
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "PROPOSED",
                "ACTIVE",
                "DECLINED",
                "ENDED"
              ],
              "type": "string"
            }
          },
          {
            "description": "Treat it as opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 50
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "items": [
                      {
                        "acceptedAt": {},
                        "counterparty": {
                          "accountId": {},
                          "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "legalName": "Acme Trading Ltd"
                        },
                        "createdAt": "2026-09-02T10:15:30.000Z",
                        "currency": "USD",
                        "declineReason": null,
                        "declinedAt": {},
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "endReason": null,
                        "endedAt": {},
                        "id": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                        "networkLabel": "CommaNet",
                        "pendingCutApprovalRequestId": null,
                        "position": {
                          "netAmount": "1500.00",
                          "netPayerClientAccountId": {},
                          "openObligations": 3,
                          "owedToYou": "2500.00",
                          "youCut": true,
                          "youOwe": "4000.00"
                        },
                        "proposer": {
                          "accountId": {},
                          "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "legalName": "Acme Trading Ltd"
                        },
                        "rail": "SETTLEMENT",
                        "role": "PROPOSER",
                        "status": "ACTIVE",
                        "updatedAt": "2026-09-02T10:15:30.000Z"
                      }
                    ],
                    "nextCursor": null
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfNettingAgreementsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List netting agreements",
        "tags": [
          "Settlement netting"
        ]
      },
      "post": {
        "description": "One currency, one account each side. The other member accepts by naming its own account. Nothing moves until obligations are submitted and the set is cut.",
        "operationId": "propose-netting-agreement",
        "parameters": [
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "counterpartyClientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                "counterpartyHandle": "orbital-advisory",
                "currency": "USD",
                "fromAccountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74"
              },
              "schema": {
                "$ref": "#/components/schemas/ProposePartnerNettingAgreementDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "acceptedAt": {},
                    "counterparty": {
                      "accountId": {},
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "declineReason": null,
                    "declinedAt": {},
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "endReason": null,
                    "endedAt": {},
                    "id": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "pendingCutApprovalRequestId": null,
                    "position": {
                      "netAmount": "1500.00",
                      "netPayerClientAccountId": {},
                      "openObligations": 3,
                      "owedToYou": "2500.00",
                      "youCut": true,
                      "youOwe": "4000.00"
                    },
                    "proposer": {
                      "accountId": {},
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "rail": "SETTLEMENT",
                    "role": "PROPOSER",
                    "status": "ACTIVE",
                    "updatedAt": "2026-09-02T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerNettingAgreementResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "NOT_ON_NETWORK — the same answer for every unreachable member."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "NETTING_AGREEMENT_EXISTS — you already net this currency with this member."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "code": "TRANSFER_NOT_WITHIN_TREE",
                  "error": "Unprocessable Entity",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements",
                  "statusCode": 422,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_NOT_CROSS_TREE, SETTLEMENT_FIAT_ONLY or NETTING_INVALID."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Propose to net with a member",
        "tags": [
          "Settlement netting"
        ]
      }
    },
    "/api/partner/v1/netting/agreements/{id}": {
      "get": {
        "operationId": "get-netting-agreement",
        "parameters": [
          {
            "description": "The netting agreement id.",
            "example": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "acceptedAt": {},
                    "counterparty": {
                      "accountId": {},
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "declineReason": null,
                    "declinedAt": {},
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "endReason": null,
                    "endedAt": {},
                    "id": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "pendingCutApprovalRequestId": null,
                    "position": {
                      "netAmount": "1500.00",
                      "netPayerClientAccountId": {},
                      "openObligations": 3,
                      "owedToYou": "2500.00",
                      "youCut": true,
                      "youOwe": "4000.00"
                    },
                    "proposer": {
                      "accountId": {},
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "rail": "SETTLEMENT",
                    "role": "PROPOSER",
                    "status": "ACTIVE",
                    "updatedAt": "2026-09-02T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerNettingAgreementResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": ""
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "NETTING_AGREEMENT_NOT_FOUND — also for an agreement you are not a party to."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "One agreement, with the open position as you read it",
        "tags": [
          "Settlement netting"
        ]
      }
    },
    "/api/partner/v1/netting/agreements/{id}/accept": {
      "post": {
        "operationId": "accept-netting-agreement",
        "parameters": [
          {
            "description": "The netting agreement id.",
            "example": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "accountId": "a1c93e6f-52b7-4d08-8e51-6b2f0c9d3a47"
              },
              "schema": {
                "$ref": "#/components/schemas/AcceptPartnerNettingAgreementDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "acceptedAt": {},
                    "counterparty": {
                      "accountId": {},
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "declineReason": null,
                    "declinedAt": {},
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "endReason": null,
                    "endedAt": {},
                    "id": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "pendingCutApprovalRequestId": null,
                    "position": {
                      "netAmount": "1500.00",
                      "netPayerClientAccountId": {},
                      "openObligations": 3,
                      "owedToYou": "2500.00",
                      "youCut": true,
                      "youOwe": "4000.00"
                    },
                    "proposer": {
                      "accountId": {},
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "rail": "SETTLEMENT",
                    "role": "PROPOSER",
                    "status": "ACTIVE",
                    "updatedAt": "2026-09-02T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerNettingAgreementResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/accept",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/accept",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/accept",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "NETTING_NOT_YOURS — only the member it was proposed to accepts."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/accept",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "NETTING_AGREEMENT_NOT_OPEN — no longer PROPOSED."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/accept",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Accept a proposed agreement, naming your account under it",
        "tags": [
          "Settlement netting"
        ]
      }
    },
    "/api/partner/v1/netting/agreements/{id}/cut": {
      "post": {
        "description": "The member that OWES the net cuts; when the net is zero either may. One ordinary settlement posts for the net (none when zero) and every open obligation is netted in the same transaction. The net counts against your WITHDRAWAL cap.",
        "operationId": "cut-netting-agreement",
        "parameters": [
          {
            "description": "The netting agreement id.",
            "example": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "agreement": {
                      "acceptedAt": {},
                      "counterparty": {
                        "accountId": {},
                        "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "legalName": "Acme Trading Ltd"
                      },
                      "createdAt": "2026-09-02T10:15:30.000Z",
                      "currency": "USD",
                      "declineReason": null,
                      "declinedAt": {},
                      "disclosure": {
                        "items": [
                          "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                          "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                          "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                          "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                          "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                          "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                          "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                        ],
                        "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                        "version": "2026-10-27"
                      },
                      "endReason": null,
                      "endedAt": {},
                      "id": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                      "networkLabel": "CommaNet",
                      "pendingCutApprovalRequestId": null,
                      "position": {
                        "netAmount": "1500.00",
                        "netPayerClientAccountId": {},
                        "openObligations": 3,
                        "owedToYou": "2500.00",
                        "youCut": true,
                        "youOwe": "4000.00"
                      },
                      "proposer": {
                        "accountId": {},
                        "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "legalName": "Acme Trading Ltd"
                      },
                      "rail": "SETTLEMENT",
                      "role": "PROPOSER",
                      "status": "ACTIVE",
                      "updatedAt": "2026-09-02T10:15:30.000Z"
                    },
                    "cut": {
                      "agreementId": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                      "currency": "USD",
                      "cutAt": "2026-09-02T10:15:30.000Z",
                      "disclosure": {
                        "items": [
                          "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                          "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                          "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                          "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                          "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                          "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                          "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                        ],
                        "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                        "version": "2026-10-27"
                      },
                      "endToEndId": "NET-3f8c1d2a5e6b7049a1b2c3d4e5f6071",
                      "grossCounterpartyOwed": "2500.00",
                      "grossProposerOwed": "4000.00",
                      "id": "sncut_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                      "netAmount": "1500.00",
                      "netPayerClientAccountId": {},
                      "netSettlementId": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                      "networkLabel": "CommaNet",
                      "obligationCount": 3,
                      "rail": "SETTLEMENT"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "kind": "CUT"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerNettingCutOutcomeResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": ""
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/cut",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/cut",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "NETTING_CUT_NOT_NET_PAYER — the other side owes the net."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/cut",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "NETTING_NOTHING_TO_CUT, INSUFFICIENT_BALANCE, SETTLEMENT_REQUIRES_APPROVAL or SETTLEMENT_CONFLICT (the set changed under the cut; nothing was written — cut again)."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/cut",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Offset every open obligation both ways and settle the net",
        "tags": [
          "Settlement netting"
        ]
      }
    },
    "/api/partner/v1/netting/agreements/{id}/cuts": {
      "get": {
        "operationId": "list-netting-cuts",
        "parameters": [
          {
            "description": "The netting agreement id.",
            "example": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Treat it as opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 50
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "items": [
                      {
                        "agreementId": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                        "currency": "USD",
                        "cutAt": "2026-09-02T10:15:30.000Z",
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "endToEndId": "NET-3f8c1d2a5e6b7049a1b2c3d4e5f6071",
                        "grossCounterpartyOwed": "2500.00",
                        "grossProposerOwed": "4000.00",
                        "id": "sncut_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                        "netAmount": "1500.00",
                        "netPayerClientAccountId": {},
                        "netSettlementId": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                        "networkLabel": "CommaNet",
                        "obligationCount": 3,
                        "rail": "SETTLEMENT"
                      }
                    ],
                    "nextCursor": null
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfNettingCutsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements/{id}/cuts",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements/{id}/cuts",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements/{id}/cuts",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements/{id}/cuts",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Past cuts of an agreement, newest first",
        "tags": [
          "Settlement netting"
        ]
      }
    },
    "/api/partner/v1/netting/agreements/{id}/decline": {
      "post": {
        "operationId": "decline-netting-agreement",
        "parameters": [
          {
            "description": "The netting agreement id.",
            "example": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "reason": "Relationship ended"
              },
              "schema": {
                "$ref": "#/components/schemas/PartnerNettingReasonDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "acceptedAt": {},
                    "counterparty": {
                      "accountId": {},
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "declineReason": null,
                    "declinedAt": {},
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "endReason": null,
                    "endedAt": {},
                    "id": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "pendingCutApprovalRequestId": null,
                    "position": {
                      "netAmount": "1500.00",
                      "netPayerClientAccountId": {},
                      "openObligations": 3,
                      "owedToYou": "2500.00",
                      "youCut": true,
                      "youOwe": "4000.00"
                    },
                    "proposer": {
                      "accountId": {},
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "rail": "SETTLEMENT",
                    "role": "PROPOSER",
                    "status": "ACTIVE",
                    "updatedAt": "2026-09-02T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerNettingAgreementResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/decline",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/decline",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/decline",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/decline",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Decline a proposed agreement",
        "tags": [
          "Settlement netting"
        ]
      }
    },
    "/api/partner/v1/netting/agreements/{id}/end": {
      "post": {
        "description": "Either party, once nothing is OPEN under it. 409 NETTING_HAS_OPEN_OBLIGATIONS otherwise.",
        "operationId": "end-netting-agreement",
        "parameters": [
          {
            "description": "The netting agreement id.",
            "example": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "reason": "Relationship ended"
              },
              "schema": {
                "$ref": "#/components/schemas/PartnerNettingReasonDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "acceptedAt": {},
                    "counterparty": {
                      "accountId": {},
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "declineReason": null,
                    "declinedAt": {},
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "endReason": null,
                    "endedAt": {},
                    "id": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "pendingCutApprovalRequestId": null,
                    "position": {
                      "netAmount": "1500.00",
                      "netPayerClientAccountId": {},
                      "openObligations": 3,
                      "owedToYou": "2500.00",
                      "youCut": true,
                      "youOwe": "4000.00"
                    },
                    "proposer": {
                      "accountId": {},
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "rail": "SETTLEMENT",
                    "role": "PROPOSER",
                    "status": "ACTIVE",
                    "updatedAt": "2026-09-02T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerNettingAgreementResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/end",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/end",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/end",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/end",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "End an agreement",
        "tags": [
          "Settlement netting"
        ]
      }
    },
    "/api/partner/v1/netting/agreements/{id}/obligations": {
      "get": {
        "operationId": "list-netting-obligations",
        "parameters": [
          {
            "description": "The netting agreement id.",
            "example": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "OPEN",
                "NETTED",
                "WITHDRAWN"
              ],
              "type": "string"
            }
          },
          {
            "description": "Treat it as opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 50
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "items": [
                      {
                        "agreementId": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                        "amount": "1500.00",
                        "createdAt": "2026-09-02T10:15:30.000Z",
                        "currency": "USD",
                        "cutId": {},
                        "direction": "IN",
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "endToEndId": "ACME-TRADE-2026-0042",
                        "id": "snob_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                        "networkLabel": "CommaNet",
                        "payee": {
                          "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "legalName": "Acme Trading Ltd"
                        },
                        "payer": {
                          "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "legalName": "Acme Trading Ltd"
                        },
                        "rail": "SETTLEMENT",
                        "remittance": null,
                        "replayed": false,
                        "status": "OPEN",
                        "withdrawReason": null,
                        "withdrawnAt": {}
                      }
                    ],
                    "nextCursor": null
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfNettingObligationsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements/{id}/obligations",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements/{id}/obligations",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements/{id}/obligations",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/agreements/{id}/obligations",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Obligations under an agreement, newest first",
        "tags": [
          "Settlement netting"
        ]
      },
      "post": {
        "description": "Reserves the full amount on your agreement account until the set is cut: available is balance minus your ACTIVE holds and OPEN obligations, and netting never extends credit. The amount is counted against your WITHDRAWAL cap when the NET settles, not here.",
        "operationId": "submit-netting-obligation",
        "parameters": [
          {
            "description": "The netting agreement id.",
            "example": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. The key is remembered permanently: it is recorded against the movement it created, so a replay years later still resolves to that one movement.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "1500.00",
                "endToEndId": "ACME-TRADE-2026-0042",
                "idempotencyKey": "acme-obl-2026-09-16-0001",
                "remittance": {}
              },
              "schema": {
                "$ref": "#/components/schemas/SubmitPartnerNettingObligationDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "agreementId": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "amount": "1500.00",
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "cutId": {},
                    "direction": "IN",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "endToEndId": "ACME-TRADE-2026-0042",
                    "id": "snob_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "payee": {
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "payer": {
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "rail": "SETTLEMENT",
                    "remittance": null,
                    "replayed": false,
                    "status": "OPEN",
                    "withdrawReason": null,
                    "withdrawnAt": {}
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerNettingObligationResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Reserved, or the original replayed"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/obligations",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/obligations",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/obligations",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/obligations",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "INSUFFICIENT_BALANCE, NETTING_AGREEMENT_NOT_OPEN or IDEMPOTENCY_MISMATCH."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/agreements/{id}/obligations",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Owe the other member an amount under this agreement",
        "tags": [
          "Settlement netting"
        ]
      }
    },
    "/api/partner/v1/netting/obligations/{id}": {
      "get": {
        "operationId": "get-netting-obligation",
        "parameters": [
          {
            "description": "The netting obligation id.",
            "example": "snob_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "agreementId": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "amount": "1500.00",
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "cutId": {},
                    "direction": "IN",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "endToEndId": "ACME-TRADE-2026-0042",
                    "id": "snob_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "payee": {
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "payer": {
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "rail": "SETTLEMENT",
                    "remittance": null,
                    "replayed": false,
                    "status": "OPEN",
                    "withdrawReason": null,
                    "withdrawnAt": {}
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerNettingObligationResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": ""
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/obligations/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/obligations/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/netting/obligations/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "One obligation, by its snob_ id",
        "tags": [
          "Settlement netting"
        ]
      }
    },
    "/api/partner/v1/netting/obligations/{id}/withdraw": {
      "post": {
        "operationId": "withdraw-netting-obligation",
        "parameters": [
          {
            "description": "The netting obligation id.",
            "example": "snob_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "reason": "Relationship ended"
              },
              "schema": {
                "$ref": "#/components/schemas/PartnerNettingReasonDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "agreementId": "snag_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "amount": "1500.00",
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "cutId": {},
                    "direction": "IN",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "endToEndId": "ACME-TRADE-2026-0042",
                    "id": "snob_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "payee": {
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "payer": {
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "rail": "SETTLEMENT",
                    "remittance": null,
                    "replayed": false,
                    "status": "OPEN",
                    "withdrawReason": null,
                    "withdrawnAt": {}
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerNettingObligationResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": ""
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/obligations/{id}/withdraw",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/obligations/{id}/withdraw",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/obligations/{id}/withdraw",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/obligations/{id}/withdraw",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "NETTING_OBLIGATION_NOT_OPEN — already netted or withdrawn."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/netting/obligations/{id}/withdraw",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Withdraw an OPEN obligation you owe, releasing its reserve",
        "tags": [
          "Settlement netting"
        ]
      }
    },
    "/api/partner/v1/network/connections": {
      "get": {
        "description": "Your allowlist, oldest first — or with x-on-behalf-of, that sub-client's. It is consulted only while receivePolicy is CONNECTED_ONLY, but you may build it beforehand. Nothing is asked of the members on it and they are not told they are listed.",
        "operationId": "list-network-connections",
        "parameters": [
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "items": [
                      {
                        "createdAt": "2026-09-02T10:15:30.000Z",
                        "handle": "acme-treasury",
                        "id": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "legalName": "Acme Trading Ltd",
                        "memberClientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "note": "Prime broker — onboarded 2026-09"
                      }
                    ]
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementConnectionsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The allowlist"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/network/connections",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/network/connections",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/network/connections",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "The members allowed to pay you under CONNECTED_ONLY",
        "tags": [
          "Settlement network"
        ]
      },
      "post": {
        "description": "By their exact handle. Takes effect on the next settlement to you; nothing is asked of them. Adding a member already listed returns the existing row unchanged, so a retry is safe without an idempotency key.",
        "operationId": "add-network-connection",
        "parameters": [
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "handle": "acme-treasury",
                "note": "Prime broker — onboarded 2026-09"
              },
              "schema": {
                "$ref": "#/components/schemas/AddPartnerSettlementConnectionDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "handle": "acme-treasury",
                    "id": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "legalName": "Acme Trading Ltd",
                    "memberClientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "note": "Prime broker — onboarded 2026-09"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementConnectionResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The connection"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/network/connections",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/network/connections",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/network/connections",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/network/connections",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "NOT_ON_NETWORK — nothing that can be paid answers to that handle."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "code": "TRANSFER_NOT_WITHIN_TREE",
                  "error": "Unprocessable Entity",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/network/connections",
                  "statusCode": 422,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "CONNECTION_INVALID — the handle is your own, or a node inside your own tree. Money moves to those as a transfer, never a settlement, so there is nothing for the list to admit."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/network/connections",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Allow a member to pay you",
        "tags": [
          "Settlement network"
        ]
      }
    },
    "/api/partner/v1/network/connections/{memberClientAccountId}": {
      "delete": {
        "description": "Takes effect on the next settlement. Nothing already settled is affected: the list is policy for what may be paid, never a record of what was.",
        "operationId": "remove-network-connection",
        "parameters": [
          {
            "description": "The connected member id.",
            "example": "9c1f7a20-1a3b-4c8d-9e2f-0b5a6c7d8e9f",
            "in": "path",
            "name": "memberClientAccountId",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Removed"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/network/connections/{memberClientAccountId}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/network/connections/{memberClientAccountId}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/network/connections/{memberClientAccountId}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "CONNECTION_NOT_FOUND — that member was not listed."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/network/connections/{memberClientAccountId}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Stop allowing a member to pay you",
        "tags": [
          "Settlement network"
        ]
      }
    },
    "/api/partner/v1/network/profile": {
      "get": {
        "description": "Your own, or — with x-on-behalf-of — that sub-client's. null when the node has not joined the network yet.",
        "operationId": "get-network-profile",
        "parameters": [
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "aliases": [
                      "Acme Trading"
                    ],
                    "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "createdAt": "2026-09-08T10:15:30.000Z",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "discoverable": false,
                    "handle": "acme-treasury",
                    "inboundConversionCurrency": null,
                    "receivePolicy": "ANYONE",
                    "retiredAt": null,
                    "updatedAt": "2026-09-08T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementProfileResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The profile, or null"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/network/profile",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/network/profile",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/network/profile",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Read the network profile",
        "tags": [
          "Settlement network"
        ]
      },
      "put": {
        "description": "The handle is set once. Sending a different handle later is refused with 409 HANDLE_IMMUTABLE — changing one is a support action, because a handle that could be re-issued is one a payer's saved payee could silently start pointing at somebody else. With x-on-behalf-of the profile is that sub-client's, and its handle is namespaced under yours: acme/zayn-retail.",
        "operationId": "update-network-profile",
        "parameters": [
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "aliases": [
                  "Acme Trading"
                ],
                "discoverable": false,
                "handle": "acme-treasury",
                "inboundConversionCurrency": "EUR",
                "receivePolicy": "ANYONE"
              },
              "schema": {
                "$ref": "#/components/schemas/UpdatePartnerSettlementProfileDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "aliases": [
                      "Acme Trading"
                    ],
                    "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "createdAt": "2026-09-08T10:15:30.000Z",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "discoverable": false,
                    "handle": "acme-treasury",
                    "inboundConversionCurrency": null,
                    "receivePolicy": "ANYONE",
                    "retiredAt": null,
                    "updatedAt": "2026-09-08T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementProfileResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The profile as it now stands"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "PUT",
                  "path": "/api/partner/v1/network/profile",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "HANDLE_INVALID (shape or length), HANDLE_RESERVED, HANDLE_NAMESPACE_MISMATCH (a sub-client handle that does not begin with its root's), or ALIASES_INVALID."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "PUT",
                  "path": "/api/partner/v1/network/profile",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "PUT",
                  "path": "/api/partner/v1/network/profile",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "PUT",
                  "path": "/api/partner/v1/network/profile",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "HANDLE_TAKEN (somebody holds it, or a handle that looks the same to a human), HANDLE_IMMUTABLE, or ROOT_HANDLE_REQUIRED (choose your own handle before your sub-clients')."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "PUT",
                  "path": "/api/partner/v1/network/profile",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Create or amend the network profile",
        "tags": [
          "Settlement network"
        ]
      }
    },
    "/api/partner/v1/network/resolve": {
      "get": {
        "description": "Supply exactly one of handle or iban, and optionally the name you believe you are paying. The answer carries the verified legal name, the currencies that member can receive, and a verdict on your name: MATCH is the legal name exactly, CLOSE_MATCH is a trading name or a near miss, NO_MATCH is neither, and null means you supplied no name to check. Cite resolveToken on POST /settlements so what you were shown is what you pay; it lasts ten minutes.",
        "operationId": "resolve-network-member",
        "parameters": [
          {
            "example": "acme-treasury",
            "in": "query",
            "name": "handle",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "example": "BH29TCBB00000000123456",
            "in": "query",
            "name": "iban",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "The name you believe you are paying.",
            "example": "Acme Trading Ltd",
            "in": "query",
            "name": "name",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "connected": true,
                    "currencies": [
                      "EUR",
                      "USD"
                    ],
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "handle": "acme-treasury",
                    "legalName": "Acme Trading Ltd",
                    "node": {
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "kind": "CLIENT"
                    },
                    "receivePolicy": "ANYONE",
                    "route": {
                      "arrival": "INSTANT",
                      "fee": {
                        "amount": "0",
                        "currency": "USD"
                      },
                      "label": "via CommaNet · instant · no fee",
                      "onUs": true,
                      "rail": "COMMANET"
                    },
                    "sameRoot": false,
                    "verdict": "MATCH"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerResolveResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The member"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/network/resolve",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Neither or both of handle and iban."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/network/resolve",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/network/resolve",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/network/resolve",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "NOT_ON_NETWORK — nothing that can be paid answers to that address. One answer for a member that does not exist, one that is not verified and one that is frozen."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/network/resolve",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Resolve a handle or a TCB IBAN to a member",
        "tags": [
          "Settlement network"
        ]
      }
    },
    "/api/partner/v1/network/search": {
      "get": {
        "description": "Prefix match on handle, legal name and trading names, over members who turned discoverability on. At least two characters, at most 20 rows, cursor-paginated. It never returns IBANs, never a member who is not discoverable, and never your own tree. An exact handle or IBAN resolves anyone regardless of discoverability — use GET /network/resolve.",
        "operationId": "search-network-members",
        "parameters": [
          {
            "example": "acme",
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Treat it as opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 20
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "items": [
                      {
                        "handle": "acme-treasury",
                        "kind": "CLIENT",
                        "legalName": "Acme Trading Ltd"
                      }
                    ],
                    "nextCursor": null
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfDirectoryHitsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of members"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/network/search",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "q shorter than two characters, or a bad limit."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/network/search",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/network/search",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/network/search",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Search the member directory",
        "tags": [
          "Settlement network"
        ]
      }
    },
    "/api/partner/v1/payouts": {
      "post": {
        "description": "Sends fiat from one of your accounts to a destination you registered and that has completed screening, TCB approval and its holding period. The request names the destination by instrumentId — there is no way to pass raw bank details. Before anything is charged the payout is checked against your money caps, your balance, and the destination's current state; it is checked again immediately before the money leaves. The payout pays the Sending fee for the rail it travels (the destination's rail), the same per-rail fee a payment sent from the TCB app pays: on top of amount, in the same currency, from the same source account, so the account must cover both. The response states it as fee. Money caps count amount alone. To see the fee before you pay, quote the payout first (POST /payouts/quote) and name the quoteId here: the payout is then charged the quoted fee. The fee is refunded with the payout whenever the payout is refunded or returned. The response is PROCESSING once the rail has accepted the payment; settlement arrives as the payout.settled webhook, or on GET /partner/v1/payouts/{id}. An idempotency key is MANDATORY: send it as the Idempotency-Key header or as the idempotencyKey body field. Replaying a key returns the same payout in its current state without paying again; reusing one with different parameters is rejected with IDEMPOTENCY_KEY_REUSED. Every response carries the pilot disclosure: the fiat rail is mocked, so no real money moves. Send x-on-behalf-of to pay with one of your sub-clients' money: the payment then leaves that sub-client's own account and carries its own name and account details as the sending party, never yours. The destination is still one from YOUR registry, and a destination you filed for a different sub-client is not payable from this one. The sub-client needs the sendExternal capability. The header is part of the payment: the same idempotency key with and without it is rejected as reused.",
        "operationId": "create-payout",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. The key is remembered permanently: it is recorded against the movement it created, so a replay years later still resolves to that one movement.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "1250.00",
                "currency": "EUR",
                "idempotencyKey": "acme-payout-2026-09-06-0001",
                "instrumentId": "1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97",
                "quoteId": "0b6f2d84-3c19-4e7a-9a52-6d1e8f4c7b30",
                "reference": "INV-2026-0042",
                "sourceAccountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerPayoutDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1250.00",
                    "compensation": {
                      "outcome": "REFUNDED"
                    },
                    "currency": "EUR",
                    "destination": {
                      "currency": {},
                      "kind": "FIAT_BANK",
                      "last4": {},
                      "rail": {}
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "endToEndId": {},
                    "failedAt": {},
                    "fee": {
                      "amount": "25",
                      "currency": "EUR"
                    },
                    "return": {
                      "reasonCode": {}
                    },
                    "returnedAt": {},
                    "settledAt": {},
                    "sourceAccountId": {},
                    "status": "PENDING",
                    "submittedAt": {}
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerPayoutResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The payout accepted by the rail (PROCESSING), or the same payout replayed"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/payouts",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Missing/invalid idempotency key, invalid or over-precise amount, insufficient balance for the amount plus its Sending fee (INSUFFICIENT_BALANCE, details.required and details.fee), a destination that is a wallet (DESTINATION_KIND_NOT_SUPPORTED), in another currency (DESTINATION_CURRENCY_MISMATCH) or without an account identifier (DESTINATION_INCOMPLETE), or PAYOUT_CAP_EXCEEDED — the payout would cross a money cap set for your account. Nothing charged and the key stays usable."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/payouts",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/payouts",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "DESTINATION_NOT_USABLE (awaiting approval, still in its holding period, removed or superseded — details.usableAt says when a hold ends), DESTINATION_BLOCKED (screening or a TCB operator blocked it), the source account is not active, or the key lacks payment:execute. Nothing charged."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/payouts",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "BENEFICIARY_NOT_FOUND — no destination with that instrumentId in your registry, or one you filed for a different sub-client — SOURCE_ACCOUNT_NOT_FOUND — no fiat account with that sourceAccountId in your scope, which includes naming your own account while acting for a sub-client — ON_BEHALF_OF_NOT_FOUND, or QUOTE_NOT_FOUND (no payout quote with that quoteId). Nothing charged."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/payouts",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Key reused with different parameters, the original request still starting, the currency not configured (CURRENCY_NOT_CONFIGURED), SOURCE_ACCOUNT_AMBIGUOUS (you hold more than one active fiat account in that currency — name one as sourceAccountId), FIAT_ACCOUNT_NOT_PROVISIONED (the source account has no account in the fiat ledger of record, which naming another source account may clear — else contact TCB), no rail connected to your account tree for that currency (PAYOUT_RAIL_NOT_AVAILABLE), no Sending fee configured for the rail the payout would travel, or a destination whose rail is not enabled for payouts in that currency (SENDING_FEE_UNPRICEABLE), PARTNER_RAIL_FROZEN — payouts are suspended for your account until a person lifts the freeze — or PAYOUT_FAILED on a replay of a key whose payout already failed (submit a new payout under a new key). With a quoteId: QUOTE_EXPIRED, QUOTE_ALREADY_USED, QUOTE_MISMATCH (details.fields names what differs from the quoted request) or QUOTE_TERMS_CHANGED (the payout would now travel a different rail than the one quoted). Acting for a sub-client adds SUB_CLIENT_CAPABILITY_UNAVAILABLE (the sub-client is not cleared to send money out), SUB_CLIENT_RAIL_COORDINATE_MISSING (it has no account details of its own in that currency to pay from), SUB_CLIENT_SWIFT_ROUTE_UNAVAILABLE (it has no local rail in that currency, and SWIFT, which its account IBAN pays over, cannot carry it) and ON_BEHALF_OF_SUB_CLIENT_CLOSED. Nothing charged."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/payouts",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          },
          "500": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTERNAL_ERROR",
                  "error": "Internal Server Error",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/payouts",
                  "statusCode": 500,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "PAYOUT_FAILED — the rail refused the payment; nothing left your account, the debit was refunded, and a new payout under a new key is safe once the cause is fixed. Or PAYOUT_FAILED_PENDING_COMPENSATION — the payment was handed to the rail and its outcome could not be established: money may have left. Do NOT retry with a new key, which could pay twice. TCB asks the rail about this payment and refunds the debit where the rail did not take it or reports it failed, completes it forward where the rail holds it, and escalates to an operator in every other case. Poll this key or the payout id; the answer changes only when it has been resolved."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "code": "CHAIN_UNAVAILABLE",
                  "error": "Service Unavailable",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/payouts",
                  "statusCode": 503,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SCREENING_UNAVAILABLE — screening could not run and this destination fails closed. Nothing charged."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Pay a registered destination",
        "tags": [
          "Payouts"
        ]
      }
    },
    "/api/partner/v1/payouts/quote": {
      "post": {
        "description": "Prices the payout you are about to make, without making it: the Sending fee for the rail it will travel, and what leaves your account in total. Nothing is charged and no idempotency key is needed. The request is checked exactly as the payout would be (your money caps, your balance against amount plus fee, the destination's current state, the rail), so a refusal here is the refusal the payout would get. The quote is held for 60 seconds (expiresAt). Name its quoteId on POST /payouts to be charged the quoted fee; the payout must repeat the quoted request (instrumentId, currency, amount, sourceAccountId and the x-on-behalf-of header) and can use the quote once. Quoting first is optional and recommended: it is how you see the fee before you commit. A quote reserves nothing: your balance, caps and the destination are checked again when you pay. Send x-on-behalf-of to quote a payout of one of your sub-clients' money.",
        "operationId": "quote-payout",
        "parameters": [
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "1250.00",
                "currency": "EUR",
                "instrumentId": "1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97",
                "sourceAccountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74"
              },
              "schema": {
                "$ref": "#/components/schemas/PartnerPayoutQuoteRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1250",
                    "currency": "EUR",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "expiresAt": "2026-10-30T10:16:28.000Z",
                    "fee": {
                      "amount": "25",
                      "currency": "EUR",
                      "rail": "SEPA"
                    },
                    "quoteId": "0b6f2d84-3c19-4e7a-9a52-6d1e8f4c7b30",
                    "requiresApproval": false,
                    "total": "1275"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerPayoutQuoteResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The payout quoted: its fee, its total and until when the quote holds"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/payouts/quote",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The refusals POST /payouts gives before charging: an invalid or over-precise amount, INSUFFICIENT_BALANCE for the amount plus its Sending fee, a destination that is a wallet, in another currency or incomplete, or PAYOUT_CAP_EXCEEDED."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/payouts/quote",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/payouts/quote",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "DESTINATION_NOT_USABLE, DESTINATION_BLOCKED, the source account is not active, or the key lacks payment:execute."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/payouts/quote",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "BENEFICIARY_NOT_FOUND, SOURCE_ACCOUNT_NOT_FOUND or ON_BEHALF_OF_NOT_FOUND."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/payouts/quote",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The 409 refusals POST /payouts gives before charging: SOURCE_ACCOUNT_AMBIGUOUS, CURRENCY_NOT_CONFIGURED, FIAT_ACCOUNT_NOT_PROVISIONED, PAYOUT_RAIL_NOT_AVAILABLE, SENDING_FEE_UNPRICEABLE, PARTNER_RAIL_FROZEN, and the sub-client refusals."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/payouts/quote",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "code": "CHAIN_UNAVAILABLE",
                  "error": "Service Unavailable",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/payouts/quote",
                  "statusCode": 503,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SCREENING_UNAVAILABLE — screening could not run and this destination fails closed."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Quote a payout before making it",
        "tags": [
          "Payouts"
        ]
      }
    },
    "/api/partner/v1/payouts/{id}": {
      "get": {
        "description": "The payout in its CURRENT state, whatever that is — including a terminal failure, reported here as the object rather than as an error, and a return (RETURNED, with the re-credit) after settlement. This is the fetch half of the thin webhook payloads (a payout.* event carries only a resource pointer) and the poll surface the money errors point at. A payout you made for a sub-client is fetched by sending the same x-on-behalf-of header; its webhook carries that sub-client id so you know which one.",
        "operationId": "get-payout",
        "parameters": [
          {
            "description": "The payoutId returned when you created it, or carried by the event's resource pointer.",
            "example": "a1c4e7f0-2b5d-4e8a-9c3f-6d1b0e4a7c29",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1250.00",
                    "compensation": {
                      "outcome": "REFUNDED"
                    },
                    "currency": "EUR",
                    "destination": {
                      "currency": {},
                      "kind": "FIAT_BANK",
                      "last4": {},
                      "rail": {}
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "endToEndId": {},
                    "failedAt": {},
                    "fee": {
                      "amount": "25",
                      "currency": "EUR"
                    },
                    "return": {
                      "reasonCode": {}
                    },
                    "returnedAt": {},
                    "settledAt": {},
                    "sourceAccountId": {},
                    "status": "PENDING",
                    "submittedAt": {}
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerPayoutResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The payout"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/payouts/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/payouts/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/payouts/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No payout with that id in your scope — which includes a payout made for a sub-client when the header is absent or names a different one."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/payouts/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one payout by id",
        "tags": [
          "Payouts"
        ]
      }
    },
    "/api/partner/v1/positions": {
      "get": {
        "description": "The ledger fold: what each sub-account holds, what is reserved against withdrawals in flight, and what is available. The totals are the SUM of the sub-accounts, alongside the share balance of the omnibus wallet TCB holds for you. Share amounts are decimal strings at the vault's own share scale. Each row carries what it has earned — lifetime, unrealised, realised and, when you name a period, over that period — valued at the vault's latest observed share price, which is returned with its block and time. rate is the annual rate the vault pays now, net of fees, read on-chain, with when it took effect and the next scheduled change. A figure that cannot be observed is null with the reason in notObserved; it is never zero.",
        "operationId": "get-position",
        "parameters": [
          {
            "description": "The vault's currency (ISO 4217). Required: a share balance with no vault named is a number nobody can act on.",
            "example": "USD",
            "in": "query",
            "name": "currency",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "First day (UTC, YYYY-MM-DD, inclusive) of earnedPeriod. Send with periodTo.",
            "example": "2026-10-01",
            "in": "query",
            "name": "periodFrom",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Last day (UTC, YYYY-MM-DD, inclusive) of earnedPeriod, at most 366 days after periodFrom. A period is closed by the next day's share-price observation, so one ending today is null until tomorrow.",
            "example": "2026-10-07",
            "in": "query",
            "name": "periodTo",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "currency": "USD",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "rate": {
                      "apyBps": 400,
                      "asOf": "2026-10-09T12:00:00.000Z",
                      "effectiveFrom": "2026-09-01T00:00:00.000Z",
                      "nextChange": {
                        "apyBps": 375,
                        "effectiveFrom": "2026-11-01T00:00:00.000Z"
                      },
                      "pendingChange": {
                        "apyBps": 375,
                        "effectiveFrom": "2026-11-01T00:00:00.000Z"
                      },
                      "stale": false,
                      "unavailableReason": null
                    },
                    "sharePrice": {
                      "asOfAt": "2026-10-06T00:00:05.000Z",
                      "asOfBlock": "316183526",
                      "snapshotDate": "2026-10-06",
                      "stale": false,
                      "value": "1.002480000000000000"
                    },
                    "subAccounts": [
                      {
                        "accrual": {
                          "currentValue": "1002.480000",
                          "deposited": "1000.000000",
                          "earnedLifetime": "2.480000",
                          "earnedPeriod": {
                            "deposited": "0",
                            "earned": "0.810000",
                            "from": "2026-10-01",
                            "notObserved": [],
                            "to": "2026-10-07",
                            "withdrawn": "0"
                          },
                          "earnedRealised": "0",
                          "earnedUnrealised": "2.480000",
                          "netContributions": "1000.000000",
                          "notObserved": [],
                          "withdrawn": "0"
                        },
                        "availableShares": "1024.518330000000000000000000",
                        "externalRef": "acme-fund-002",
                        "isDefault": false,
                        "label": "Growth Fund II",
                        "reservedShares": "0",
                        "settledShares": "1024.518330000000000000000000",
                        "subAccountId": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395"
                      }
                    ],
                    "totals": {
                      "accrual": {
                        "currentValue": "1002.480000",
                        "deposited": "1000.000000",
                        "earnedLifetime": "2.480000",
                        "earnedPeriod": {
                          "deposited": "0",
                          "earned": "0.810000",
                          "from": "2026-10-01",
                          "notObserved": [],
                          "to": "2026-10-07",
                          "withdrawn": "0"
                        },
                        "earnedRealised": "0",
                        "earnedUnrealised": "2.480000",
                        "netContributions": "1000.000000",
                        "notObserved": [],
                        "withdrawn": "0"
                      },
                      "availableShares": "1024.518330000000000000000000",
                      "reservedShares": "0",
                      "settledShares": "1024.518330000000000000000000",
                      "walletShares": "1024.518330000000000000000000"
                    },
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerPositionResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Position by sub-account"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "periodFrom / periodTo malformed (INVALID_AMOUNT)"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No active vault for that currency"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "code": "CHAIN_UNAVAILABLE",
                  "error": "Service Unavailable",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions",
                  "statusCode": 503,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Chain read unavailable (CHAIN_UNAVAILABLE). Retry."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Your position in a vault, decomposed by sub-account, with what it has earned",
        "tags": [
          "Positions"
        ]
      }
    },
    "/api/partner/v1/positions/share-price-history": {
      "get": {
        "description": "One entry per UTC day in the range, oldest first: the share price as first observed that day, with the chain block it was read at and when. A day the price was not observed is returned with nulls, never a zero and never filled from a neighbouring day.",
        "operationId": "get-share-price-history",
        "parameters": [
          {
            "description": "The vault's currency (ISO 4217).",
            "example": "USD",
            "in": "query",
            "name": "currency",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "First day (UTC, YYYY-MM-DD, inclusive). Send with to. Omit both for the 30 days ending yesterday.",
            "example": "2026-09-08",
            "in": "query",
            "name": "from",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Last day (UTC, YYYY-MM-DD, inclusive), at most 366 days after from.",
            "example": "2026-10-07",
            "in": "query",
            "name": "to",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "currency": "USD",
                    "days": [
                      {
                        "asOfAt": "2026-10-06T00:00:05.000Z",
                        "asOfBlock": "316183526",
                        "date": "2026-10-06",
                        "sharePrice": "1.002480000000000000"
                      }
                    ],
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "from": "2026-09-08",
                    "to": "2026-10-07",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSharePriceHistoryResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Share price by day"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions/share-price-history",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "from / to malformed (INVALID_AMOUNT)"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions/share-price-history",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions/share-price-history",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions/share-price-history",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No active vault for that currency"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions/share-price-history",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "A vault's observed share price, day by day",
        "tags": [
          "Positions"
        ]
      }
    },
    "/api/partner/v1/positions/tokens": {
      "get": {
        "description": "The tcbUSD booked to each sub-account — held, reserved by steps in flight, and available — with the totals and the balance of the TCB wallet assigned to you. Your vault shares are on GET /positions.",
        "operationId": "get-token-position",
        "parameters": [
          {
            "description": "The currency of the token (ISO 4217).",
            "example": "USD",
            "in": "query",
            "name": "currency",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "asOf": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "subAccounts": [
                      {
                        "available": "600",
                        "externalRef": "acme-fund-002",
                        "held": "600",
                        "isDefault": false,
                        "label": "Growth Fund II",
                        "reserved": "0",
                        "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13"
                      }
                    ],
                    "token": {
                      "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                      "chain": "ARBITRUM",
                      "symbol": "tcbUSD"
                    },
                    "totals": {
                      "available": "1000",
                      "held": "1000",
                      "reserved": "0",
                      "walletTokens": "1000.004"
                    },
                    "yieldNote": "tcbUSD earns nothing on its own: only vault shares carry the yield."
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerTokenPositionResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "tcbUSD by sub-account"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions/tokens",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions/tokens",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions/tokens",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions/tokens",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "TOKEN_CONFIG_NOT_AVAILABLE — no active token for that currency"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/positions/tokens",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Your tcbUSD, decomposed by sub-account",
        "tags": [
          "Positions"
        ]
      }
    },
    "/api/partner/v1/settlement-holds": {
      "get": {
        "description": "Holds the ACTING node placed or is named on, newest first.",
        "operationId": "list-settlement-holds",
        "parameters": [
          {
            "in": "query",
            "name": "direction",
            "required": false,
            "schema": {
              "enum": [
                "IN",
                "OUT"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "ACTIVE",
                "RELEASED",
                "CANCELLED"
              ],
              "type": "string"
            }
          },
          {
            "description": "Treat it as opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 50
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "items": [
                      {
                        "amount": "1500.00",
                        "beneficiary": {
                          "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "legalName": "Acme Trading Ltd"
                        },
                        "cancelReason": null,
                        "cancelledAt": null,
                        "createdAt": "2026-09-08T10:15:30.000Z",
                        "currency": "USD",
                        "direction": "OUT",
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "endToEndId": "ACME-DVP-2026-0042",
                        "holder": {
                          "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "legalName": "Acme Trading Ltd"
                        },
                        "id": "shld_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                        "networkLabel": "CommaNet",
                        "pendingApprovalRequestId": null,
                        "rail": "SETTLEMENT",
                        "releasedAt": null,
                        "remittance": null,
                        "replayed": false,
                        "resolveVerdict": "MATCH",
                        "settlementId": null,
                        "status": "ACTIVE",
                        "updatedAt": "2026-09-08T10:15:30.000Z"
                      }
                    ],
                    "nextCursor": null
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfSettlementHoldsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of holds"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-holds",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-holds",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-holds",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-holds",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List settlement holds",
        "tags": [
          "Settlements"
        ]
      },
      "post": {
        "description": "Reserves and moves nothing: the balance is unchanged and the amount simply stops being available on this rail. Release it to settle, or cancel it to give the reserve back. It NEVER expires — there is no TTL and no sweeper, so a hold you forget stays reserved.",
        "operationId": "create-settlement-hold",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. The key is remembered permanently: it is recorded against the movement it created, so a replay years later still resolves to that one movement.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "1500.00",
                "currency": "USD",
                "endToEndId": "ACME-DVP-2026-0042",
                "fromAccountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                "idempotencyKey": "acme-hold-2026-09-08-0001",
                "remittance": {}
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerSettlementHoldDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1500.00",
                    "beneficiary": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "cancelReason": null,
                    "cancelledAt": null,
                    "createdAt": "2026-09-08T10:15:30.000Z",
                    "currency": "USD",
                    "direction": "OUT",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "endToEndId": "ACME-DVP-2026-0042",
                    "holder": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "id": "shld_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "pendingApprovalRequestId": null,
                    "rail": "SETTLEMENT",
                    "releasedAt": null,
                    "remittance": null,
                    "replayed": false,
                    "resolveVerdict": "MATCH",
                    "settlementId": null,
                    "status": "ACTIVE",
                    "updatedAt": "2026-09-08T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementHoldResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Reserved, or the original replayed"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_INVALID or RESOLVE_TOKEN_INVALID. An idempotency key may not begin stl:, shld:, sreq:, sret: or ret: — those namespaces belong to the rail itself."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "INSUFFICIENT_BALANCE (available is balance minus your own ACTIVE holds), SOURCE_ACCOUNT_NOT_USABLE or IDEMPOTENCY_MISMATCH."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "code": "TRANSFER_NOT_WITHIN_TREE",
                  "error": "Unprocessable Entity",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds",
                  "statusCode": 422,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_NOT_CROSS_TREE, SETTLEMENT_FIAT_ONLY, SETTLEMENT_TARGET_UNREACHABLE, RECEIVER_HAS_NO_ACCOUNT or RECEIVE_POLICY_REFUSED."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Reserve funds against a network member",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlement-holds/{id}": {
      "get": {
        "operationId": "get-settlement-hold",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1500.00",
                    "beneficiary": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "cancelReason": null,
                    "cancelledAt": null,
                    "createdAt": "2026-09-08T10:15:30.000Z",
                    "currency": "USD",
                    "direction": "OUT",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "endToEndId": "ACME-DVP-2026-0042",
                    "holder": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "id": "shld_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "pendingApprovalRequestId": null,
                    "rail": "SETTLEMENT",
                    "releasedAt": null,
                    "remittance": null,
                    "replayed": false,
                    "resolveVerdict": "MATCH",
                    "settlementId": null,
                    "status": "ACTIVE",
                    "updatedAt": "2026-09-08T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementHoldResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The hold"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-holds/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-holds/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-holds/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_HOLD_NOT_FOUND."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-holds/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one hold by its shld_ id",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlement-holds/{id}/cancel": {
      "post": {
        "operationId": "cancel-settlement-hold",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "reason": "Invoice already paid by bank transfer"
              },
              "schema": {
                "$ref": "#/components/schemas/PartnerSettlementDecisionReasonDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1500.00",
                    "beneficiary": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "cancelReason": null,
                    "cancelledAt": null,
                    "createdAt": "2026-09-08T10:15:30.000Z",
                    "currency": "USD",
                    "direction": "OUT",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "endToEndId": "ACME-DVP-2026-0042",
                    "holder": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "id": "shld_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "pendingApprovalRequestId": null,
                    "rail": "SETTLEMENT",
                    "releasedAt": null,
                    "remittance": null,
                    "replayed": false,
                    "resolveVerdict": "MATCH",
                    "settlementId": null,
                    "status": "ACTIVE",
                    "updatedAt": "2026-09-08T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementHoldResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The cancelled hold"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds/{id}/cancel",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds/{id}/cancel",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds/{id}/cancel",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds/{id}/cancel",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_HOLD_NOT_ACTIVE."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds/{id}/cancel",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Give the reserve back",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlement-holds/{id}/release": {
      "post": {
        "description": "The reserve is consumed by the settlement inside one transaction, so a hold cannot be released twice and a released hold cannot be cancelled. The beneficiary is re-validated now, not as it was when you reserved.",
        "operationId": "release-settlement-hold",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "hold": {
                      "amount": "1500.00",
                      "beneficiary": {
                        "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "legalName": "Acme Trading Ltd"
                      },
                      "cancelReason": null,
                      "cancelledAt": null,
                      "createdAt": "2026-09-08T10:15:30.000Z",
                      "currency": "USD",
                      "direction": "OUT",
                      "disclosure": {
                        "items": [
                          "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                          "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                          "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                          "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                          "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                          "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                          "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                        ],
                        "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                        "version": "2026-10-27"
                      },
                      "endToEndId": "ACME-DVP-2026-0042",
                      "holder": {
                        "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "legalName": "Acme Trading Ltd"
                      },
                      "id": "shld_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                      "networkLabel": "CommaNet",
                      "pendingApprovalRequestId": null,
                      "rail": "SETTLEMENT",
                      "releasedAt": null,
                      "remittance": null,
                      "replayed": false,
                      "resolveVerdict": "MATCH",
                      "settlementId": null,
                      "status": "ACTIVE",
                      "updatedAt": "2026-09-08T10:15:30.000Z"
                    },
                    "kind": "RELEASED",
                    "settlement": {
                      "activityId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "amount": "1500.00",
                      "createdAt": "2026-09-08T10:15:30.000Z",
                      "currency": "USD",
                      "direction": "OUT",
                      "disclosure": {
                        "items": [
                          "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                          "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                          "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                          "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                          "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                          "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                          "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                        ],
                        "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                        "version": "2026-10-27"
                      },
                      "endToEndId": "ACME-INV-2026-0042",
                      "fee": {
                        "amount": "0",
                        "currency": "USD"
                      },
                      "id": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                      "networkLabel": "CommaNet",
                      "rail": "SETTLEMENT",
                      "receipt": null,
                      "receiver": {
                        "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "legalName": "Acme Trading Ltd"
                      },
                      "remittance": {
                        "invoice": "INV-2026-0042"
                      },
                      "replayed": false,
                      "resolveVerdict": "MATCH",
                      "reversalOfId": null,
                      "reversedById": null,
                      "sender": {
                        "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "legalName": "Acme Trading Ltd"
                      },
                      "settledAt": "2026-09-08T10:15:30.000Z",
                      "settlementHoldId": null,
                      "settlementRequestId": null,
                      "settlementReturnId": null,
                      "status": "COMPLETED"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementHoldReleaseResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Settled"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds/{id}/release",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "WITHDRAWAL_CAP_EXCEEDED — the cap is drawn down at RELEASE, never at reserve, because a reserve has moved nothing. Nothing was withdrawn and the hold is still ACTIVE."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds/{id}/release",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds/{id}/release",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_HOLD_NOT_YOURS — only the holder releases."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds/{id}/release",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_HOLD_NOT_ACTIVE, INSUFFICIENT_BALANCE (you spent the reserved balance elsewhere), SETTLEMENT_REQUIRES_APPROVAL, or SETTLEMENT_CONFLICT."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-holds/{id}/release",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Settle a hold to the member it was reserved against",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlement-requests": {
      "get": {
        "description": "Requests the ACTING node raised or was asked for, newest first. A request past its due-by date is marked EXPIRED as this page is read — that is the only thing that expires it.",
        "operationId": "list-settlement-requests",
        "parameters": [
          {
            "in": "query",
            "name": "direction",
            "required": false,
            "schema": {
              "enum": [
                "INBOUND",
                "OUTBOUND"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "OPEN",
                "APPROVED",
                "DECLINED",
                "EXPIRED",
                "CANCELLED"
              ],
              "type": "string"
            }
          },
          {
            "description": "Treat it as opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 50
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "items": [
                      {
                        "amount": "1500.00",
                        "createdAt": "2026-09-08T10:15:30.000Z",
                        "currency": "USD",
                        "decidedAt": null,
                        "declineReason": null,
                        "direction": "INBOUND",
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "dueBy": "2026-10-01T12:00:00.000Z",
                        "endToEndId": "ACME-INV-2026-0042",
                        "id": "sreq_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                        "networkLabel": "CommaNet",
                        "payer": {
                          "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "legalName": "Acme Trading Ltd"
                        },
                        "pendingApprovalRequestId": null,
                        "rail": "SETTLEMENT",
                        "remittance": {
                          "invoice": "INV-2026-0042"
                        },
                        "replayed": false,
                        "requester": {
                          "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "legalName": "Acme Trading Ltd"
                        },
                        "settlementId": null,
                        "status": "OPEN",
                        "updatedAt": "2026-09-08T10:15:30.000Z"
                      }
                    ],
                    "nextCursor": null
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfSettlementRequestsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of requests"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-requests",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-requests",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-requests",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-requests",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List settlement requests",
        "tags": [
          "Settlements"
        ]
      },
      "post": {
        "description": "An ASK. It holds nothing, reserves nothing and moves nothing — the payer decides. Name the account you want credited and exactly one of toHandle, toIban or toClientAccountId. Cross-tree only: a movement inside your own tree is POST /transfers.",
        "operationId": "create-settlement-request",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. The key is remembered permanently: it is recorded against the movement it created, so a replay years later still resolves to that one movement.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "1500.00",
                "currency": "USD",
                "dueBy": "2026-10-01T12:00:00.000Z",
                "endToEndId": "ACME-INV-2026-0042",
                "fromAccountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                "idempotencyKey": "acme-req-2026-09-08-0001",
                "remittance": {
                  "invoice": "INV-2026-0042"
                },
                "toClientAccountId": "246f8056-fc27-4e06-a589-0866d9cbffbd",
                "toHandle": "acme-treasury",
                "toIban": "BH00TCB00000000000001"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerSettlementRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1500.00",
                    "createdAt": "2026-09-08T10:15:30.000Z",
                    "currency": "USD",
                    "decidedAt": null,
                    "declineReason": null,
                    "direction": "INBOUND",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "dueBy": "2026-10-01T12:00:00.000Z",
                    "endToEndId": "ACME-INV-2026-0042",
                    "id": "sreq_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "payer": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "pendingApprovalRequestId": null,
                    "rail": "SETTLEMENT",
                    "remittance": {
                      "invoice": "INV-2026-0042"
                    },
                    "replayed": false,
                    "requester": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "settlementId": null,
                    "status": "OPEN",
                    "updatedAt": "2026-09-08T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementRequestResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Raised, or the original replayed"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_INVALID (a malformed amount, endToEndId, remittance, idempotency key, dueBy in the past, or zero/two targets named). An idempotency key may not begin stl:, shld:, sreq:, sret: or ret: — those namespaces belong to the rail itself."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "NOT_ON_NETWORK (no such member) or SOURCE_ACCOUNT_NOT_USABLE."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "IDEMPOTENCY_MISMATCH — this key already raised something else."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "code": "TRANSFER_NOT_WITHIN_TREE",
                  "error": "Unprocessable Entity",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests",
                  "statusCode": 422,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_NOT_CROSS_TREE (both sides are under one root — use POST /transfers) or RECEIVER_HAS_NO_ACCOUNT (you hold no active account in this currency to be credited)."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Ask another network member to pay you",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlement-requests/{id}": {
      "get": {
        "description": "Both parties read the same request, with direction reported for YOU. One you are not a party to answers 404 — never 403, which would confirm it exists.",
        "operationId": "get-settlement-request",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1500.00",
                    "createdAt": "2026-09-08T10:15:30.000Z",
                    "currency": "USD",
                    "decidedAt": null,
                    "declineReason": null,
                    "direction": "INBOUND",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "dueBy": "2026-10-01T12:00:00.000Z",
                    "endToEndId": "ACME-INV-2026-0042",
                    "id": "sreq_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "payer": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "pendingApprovalRequestId": null,
                    "rail": "SETTLEMENT",
                    "remittance": {
                      "invoice": "INV-2026-0042"
                    },
                    "replayed": false,
                    "requester": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "settlementId": null,
                    "status": "OPEN",
                    "updatedAt": "2026-09-08T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementRequestResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The request"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-requests/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-requests/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-requests/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_REQUEST_NOT_FOUND."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-requests/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one settlement request by its sreq_ id",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlement-requests/{id}/approve": {
      "post": {
        "description": "Settles from the account YOU name, through the ordinary settlement path — the same checks, the same four ledger entries, the same stl_ row. The request is closed inside that same transaction, so it can never read APPROVED without a settlement behind it.",
        "operationId": "approve-settlement-request",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "fromAccountId": "a1c93e6f-52b7-4d08-8e51-6b2f0c9d3a47"
              },
              "schema": {
                "$ref": "#/components/schemas/ApprovePartnerSettlementRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "kind": "SETTLED",
                    "request": {
                      "amount": "1500.00",
                      "createdAt": "2026-09-08T10:15:30.000Z",
                      "currency": "USD",
                      "decidedAt": null,
                      "declineReason": null,
                      "direction": "INBOUND",
                      "disclosure": {
                        "items": [
                          "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                          "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                          "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                          "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                          "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                          "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                          "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                        ],
                        "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                        "version": "2026-10-27"
                      },
                      "dueBy": "2026-10-01T12:00:00.000Z",
                      "endToEndId": "ACME-INV-2026-0042",
                      "id": "sreq_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                      "networkLabel": "CommaNet",
                      "payer": {
                        "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "legalName": "Acme Trading Ltd"
                      },
                      "pendingApprovalRequestId": null,
                      "rail": "SETTLEMENT",
                      "remittance": {
                        "invoice": "INV-2026-0042"
                      },
                      "replayed": false,
                      "requester": {
                        "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "legalName": "Acme Trading Ltd"
                      },
                      "settlementId": null,
                      "status": "OPEN",
                      "updatedAt": "2026-09-08T10:15:30.000Z"
                    },
                    "settlement": {
                      "activityId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "amount": "1500.00",
                      "createdAt": "2026-09-08T10:15:30.000Z",
                      "currency": "USD",
                      "direction": "OUT",
                      "disclosure": {
                        "items": [
                          "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                          "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                          "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                          "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                          "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                          "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                          "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                        ],
                        "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                        "version": "2026-10-27"
                      },
                      "endToEndId": "ACME-INV-2026-0042",
                      "fee": {
                        "amount": "0",
                        "currency": "USD"
                      },
                      "id": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                      "networkLabel": "CommaNet",
                      "rail": "SETTLEMENT",
                      "receipt": null,
                      "receiver": {
                        "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "legalName": "Acme Trading Ltd"
                      },
                      "remittance": {
                        "invoice": "INV-2026-0042"
                      },
                      "replayed": false,
                      "resolveVerdict": "MATCH",
                      "reversalOfId": null,
                      "reversedById": null,
                      "sender": {
                        "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "legalName": "Acme Trading Ltd"
                      },
                      "settledAt": "2026-09-08T10:15:30.000Z",
                      "settlementHoldId": null,
                      "settlementRequestId": null,
                      "settlementReturnId": null,
                      "status": "COMPLETED"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementRequestApprovalResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Settled"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests/{id}/approve",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "WITHDRAWAL_CAP_EXCEEDED — paying a request draws down the same cap a settlement does. Nothing was withdrawn and the request is still open."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests/{id}/approve",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests/{id}/approve",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_REQUEST_NOT_YOURS — only the payer approves."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests/{id}/approve",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_REQUEST_NOT_OPEN, SETTLEMENT_REQUEST_EXPIRED (its due-by has passed; the row is flipped as you are told), INSUFFICIENT_BALANCE, SETTLEMENT_REQUIRES_APPROVAL (your organisation's approval rules would hold this settlement for approval, or block it — approve the request from the app), or SETTLEMENT_CONFLICT."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests/{id}/approve",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Pay a settlement request",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlement-requests/{id}/cancel": {
      "post": {
        "operationId": "cancel-settlement-request",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1500.00",
                    "createdAt": "2026-09-08T10:15:30.000Z",
                    "currency": "USD",
                    "decidedAt": null,
                    "declineReason": null,
                    "direction": "INBOUND",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "dueBy": "2026-10-01T12:00:00.000Z",
                    "endToEndId": "ACME-INV-2026-0042",
                    "id": "sreq_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "payer": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "pendingApprovalRequestId": null,
                    "rail": "SETTLEMENT",
                    "remittance": {
                      "invoice": "INV-2026-0042"
                    },
                    "replayed": false,
                    "requester": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "settlementId": null,
                    "status": "OPEN",
                    "updatedAt": "2026-09-08T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementRequestResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The closed request"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests/{id}/cancel",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests/{id}/cancel",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests/{id}/cancel",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_REQUEST_NOT_OPEN or SETTLEMENT_REQUEST_EXPIRED."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests/{id}/cancel",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Withdraw a settlement request you raised, while it is still open",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlement-requests/{id}/decline": {
      "post": {
        "operationId": "decline-settlement-request",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "reason": "Invoice already paid by bank transfer"
              },
              "schema": {
                "$ref": "#/components/schemas/PartnerSettlementDecisionReasonDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1500.00",
                    "createdAt": "2026-09-08T10:15:30.000Z",
                    "currency": "USD",
                    "decidedAt": null,
                    "declineReason": null,
                    "direction": "INBOUND",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "dueBy": "2026-10-01T12:00:00.000Z",
                    "endToEndId": "ACME-INV-2026-0042",
                    "id": "sreq_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "payer": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "pendingApprovalRequestId": null,
                    "rail": "SETTLEMENT",
                    "remittance": {
                      "invoice": "INV-2026-0042"
                    },
                    "replayed": false,
                    "requester": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "settlementId": null,
                    "status": "OPEN",
                    "updatedAt": "2026-09-08T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementRequestResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The closed request"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests/{id}/decline",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests/{id}/decline",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests/{id}/decline",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests/{id}/decline",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_REQUEST_NOT_OPEN or SETTLEMENT_REQUEST_EXPIRED."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-requests/{id}/decline",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Refuse a settlement request made of you",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlement-returns": {
      "get": {
        "description": "Returns the ACTING node asked for or was asked for, newest first.",
        "operationId": "list-settlement-returns",
        "parameters": [
          {
            "in": "query",
            "name": "direction",
            "required": false,
            "schema": {
              "enum": [
                "INBOUND",
                "OUTBOUND"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "OPEN",
                "ACCEPTED",
                "DECLINED",
                "CANCELLED"
              ],
              "type": "string"
            }
          },
          {
            "description": "Treat it as opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 50
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "items": [
                      {
                        "amount": "1500.00",
                        "counterparty": {
                          "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13"
                        },
                        "createdAt": "2026-09-08T10:15:30.000Z",
                        "currency": "USD",
                        "decidedAt": null,
                        "declineReason": null,
                        "direction": "INBOUND",
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "id": "sret_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                        "networkLabel": "CommaNet",
                        "pendingApprovalRequestId": null,
                        "rail": "SETTLEMENT",
                        "reason": "Paid twice against the same invoice",
                        "requestedBy": {
                          "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13"
                        },
                        "reversalSettlementId": null,
                        "settlementId": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                        "status": "OPEN",
                        "updatedAt": "2026-09-08T10:15:30.000Z"
                      }
                    ],
                    "nextCursor": null
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfSettlementReturnsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of return requests"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-returns",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-returns",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-returns",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-returns",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List return requests",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlement-returns/{id}": {
      "get": {
        "operationId": "get-settlement-return",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1500.00",
                    "counterparty": {
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13"
                    },
                    "createdAt": "2026-09-08T10:15:30.000Z",
                    "currency": "USD",
                    "decidedAt": null,
                    "declineReason": null,
                    "direction": "INBOUND",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "id": "sret_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "pendingApprovalRequestId": null,
                    "rail": "SETTLEMENT",
                    "reason": "Paid twice against the same invoice",
                    "requestedBy": {
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13"
                    },
                    "reversalSettlementId": null,
                    "settlementId": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "status": "OPEN",
                    "updatedAt": "2026-09-08T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementReturnResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The return request"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-returns/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-returns/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-returns/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_RETURN_NOT_FOUND."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlement-returns/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one return request by its sret_ id",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlement-returns/{id}/accept": {
      "post": {
        "description": "Books a LINKED reversing settlement: the original flips to REVERSED, a new settlement posts in the opposite direction with a zero fee, and both are one transaction. The reversal draws down no cap — it returns the full amount to the one account it came from.",
        "operationId": "accept-settlement-return",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "kind": "ACCEPTED",
                    "return": {
                      "amount": "1500.00",
                      "counterparty": {
                        "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13"
                      },
                      "createdAt": "2026-09-08T10:15:30.000Z",
                      "currency": "USD",
                      "decidedAt": null,
                      "declineReason": null,
                      "direction": "INBOUND",
                      "disclosure": {
                        "items": [
                          "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                          "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                          "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                          "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                          "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                          "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                          "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                        ],
                        "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                        "version": "2026-10-27"
                      },
                      "id": "sret_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                      "networkLabel": "CommaNet",
                      "pendingApprovalRequestId": null,
                      "rail": "SETTLEMENT",
                      "reason": "Paid twice against the same invoice",
                      "requestedBy": {
                        "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13"
                      },
                      "reversalSettlementId": null,
                      "settlementId": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                      "status": "OPEN",
                      "updatedAt": "2026-09-08T10:15:30.000Z"
                    },
                    "reversal": {
                      "activityId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "amount": "1500.00",
                      "createdAt": "2026-09-08T10:15:30.000Z",
                      "currency": "USD",
                      "direction": "OUT",
                      "disclosure": {
                        "items": [
                          "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                          "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                          "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                          "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                          "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                          "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                          "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                        ],
                        "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                        "version": "2026-10-27"
                      },
                      "endToEndId": "ACME-INV-2026-0042",
                      "fee": {
                        "amount": "0",
                        "currency": "USD"
                      },
                      "id": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                      "networkLabel": "CommaNet",
                      "rail": "SETTLEMENT",
                      "receipt": null,
                      "receiver": {
                        "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "legalName": "Acme Trading Ltd"
                      },
                      "remittance": {
                        "invoice": "INV-2026-0042"
                      },
                      "replayed": false,
                      "resolveVerdict": "MATCH",
                      "reversalOfId": null,
                      "reversedById": null,
                      "sender": {
                        "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "legalName": "Acme Trading Ltd"
                      },
                      "settledAt": "2026-09-08T10:15:30.000Z",
                      "settlementHoldId": null,
                      "settlementRequestId": null,
                      "settlementReturnId": null,
                      "status": "COMPLETED"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementReturnAcceptanceResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Returned"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-returns/{id}/accept",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-returns/{id}/accept",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_RETURN_NOT_YOURS — only the receiver accepts."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-returns/{id}/accept",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_RETURN_NOT_OPEN, SETTLEMENT_ALREADY_REVERSED, INSUFFICIENT_BALANCE, SETTLEMENT_REQUIRES_APPROVAL, SETTLEMENT_CONFLICT, or SENDER_NOT_ELIGIBLE when you accept under x-on-behalf-of and that sub-client lacks sendExternal — giving the money back sends it out of its tree, so it needs the same grant a settlement needs."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-returns/{id}/accept",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Give the money back",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlement-returns/{id}/cancel": {
      "post": {
        "operationId": "cancel-settlement-return",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1500.00",
                    "counterparty": {
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13"
                    },
                    "createdAt": "2026-09-08T10:15:30.000Z",
                    "currency": "USD",
                    "decidedAt": null,
                    "declineReason": null,
                    "direction": "INBOUND",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "id": "sret_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "pendingApprovalRequestId": null,
                    "rail": "SETTLEMENT",
                    "reason": "Paid twice against the same invoice",
                    "requestedBy": {
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13"
                    },
                    "reversalSettlementId": null,
                    "settlementId": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "status": "OPEN",
                    "updatedAt": "2026-09-08T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementReturnResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The closed request"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-returns/{id}/cancel",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-returns/{id}/cancel",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-returns/{id}/cancel",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_RETURN_NOT_OPEN."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-returns/{id}/cancel",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Withdraw a return request you raised",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlement-returns/{id}/decline": {
      "post": {
        "operationId": "decline-settlement-return",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "reason": "Invoice already paid by bank transfer"
              },
              "schema": {
                "$ref": "#/components/schemas/PartnerSettlementDecisionReasonDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1500.00",
                    "counterparty": {
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13"
                    },
                    "createdAt": "2026-09-08T10:15:30.000Z",
                    "currency": "USD",
                    "decidedAt": null,
                    "declineReason": null,
                    "direction": "INBOUND",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "id": "sret_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "pendingApprovalRequestId": null,
                    "rail": "SETTLEMENT",
                    "reason": "Paid twice against the same invoice",
                    "requestedBy": {
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13"
                    },
                    "reversalSettlementId": null,
                    "settlementId": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "status": "OPEN",
                    "updatedAt": "2026-09-08T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementReturnResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The closed request"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-returns/{id}/decline",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-returns/{id}/decline",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-returns/{id}/decline",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-returns/{id}/decline",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_RETURN_NOT_OPEN."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlement-returns/{id}/decline",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Keep the money",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlements": {
      "get": {
        "description": "Settlements the ACTING node sent or received, newest first, cursor-paginated. Scoped the way GET /accounts is: to read a sub-client's settlements, act as that sub-client.",
        "operationId": "list-settlements",
        "parameters": [
          {
            "description": "Only settlements touching this account, on either side.",
            "in": "query",
            "name": "accountId",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Treat it as opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 50
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "items": [
                      {
                        "activityId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "amount": "1500.00",
                        "createdAt": "2026-09-08T10:15:30.000Z",
                        "currency": "USD",
                        "direction": "OUT",
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "endToEndId": "ACME-INV-2026-0042",
                        "fee": {
                          "amount": "0",
                          "currency": "USD"
                        },
                        "id": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                        "networkLabel": "CommaNet",
                        "rail": "SETTLEMENT",
                        "receipt": null,
                        "receiver": {
                          "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "legalName": "Acme Trading Ltd"
                        },
                        "remittance": {
                          "invoice": "INV-2026-0042"
                        },
                        "replayed": false,
                        "resolveVerdict": "MATCH",
                        "reversalOfId": null,
                        "reversedById": null,
                        "sender": {
                          "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                          "legalName": "Acme Trading Ltd"
                        },
                        "settledAt": "2026-09-08T10:15:30.000Z",
                        "settlementHoldId": null,
                        "settlementRequestId": null,
                        "settlementReturnId": null,
                        "status": "COMPLETED"
                      }
                    ],
                    "nextCursor": null
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfSettlementsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of settlements"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlements",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "limit outside 1-50."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlements",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlements",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlements",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List settlements",
        "tags": [
          "Settlements"
        ]
      },
      "post": {
        "description": "Name the account to debit and exactly one of instrumentId, resolveToken or toAccountId. The two accounts must belong to DIFFERENT root clients, hold the same currency, and both be fiat and active. x-on-behalf-of settles from that sub-client, and the settlement then records the SUB-CLIENT's legal name as the originator, never yours.",
        "operationId": "create-settlement",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. The key is remembered permanently: it is recorded against the movement it created, so a replay years later still resolves to that one movement.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "1500.00",
                "currency": "USD",
                "endToEndId": "ACME-INV-2026-0042",
                "fromAccountId": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
                "idempotencyKey": "acme-2026-09-08-0001",
                "instrumentId": "2f6b1a90-7c34-4de1-91a8-5b0e3d7c4f21",
                "remittance": {
                  "dueDate": "2026-09-30",
                  "invoice": "INV-2026-0042"
                },
                "toAccountId": "a1c93e6f-52b7-4d08-8e51-6b2f0c9d3a47"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerSettlementDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "activityId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "amount": "1500.00",
                    "createdAt": "2026-09-08T10:15:30.000Z",
                    "currency": "USD",
                    "direction": "OUT",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "endToEndId": "ACME-INV-2026-0042",
                    "fee": {
                      "amount": "0",
                      "currency": "USD"
                    },
                    "id": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "rail": "SETTLEMENT",
                    "receipt": null,
                    "receiver": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "remittance": {
                      "invoice": "INV-2026-0042"
                    },
                    "replayed": false,
                    "resolveVerdict": "MATCH",
                    "reversalOfId": null,
                    "reversedById": null,
                    "sender": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "settledAt": "2026-09-08T10:15:30.000Z",
                    "settlementHoldId": null,
                    "settlementRequestId": null,
                    "settlementReturnId": null,
                    "status": "COMPLETED"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Settled, or the original result replayed"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlements",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_INVALID (a malformed amount, endToEndId, remittance, idempotency key, or zero/two targets named), AMOUNT_PRECISION_EXCEEDED (the amount carries more decimals than the currency settles at: USD 2, JPY 0, BHD 3; nothing was held, round it and resubmit), RESOLVE_TOKEN_INVALID (the token is forged or older than ten minutes — resolve again), or SOURCE_ACCOUNT_NOT_USABLE when the account holds another currency. An idempotency key may not begin stl:, shld:, sreq:, sret: or ret: — those namespaces belong to the settlement rail itself."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlements",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlements",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "INSUFFICIENT_SCOPE — the key lacks settlement:execute."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlements",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SOURCE_ACCOUNT_NOT_USABLE (no such account of yours) or NOT_ON_NETWORK (no such payee, account or member). An account in another tree is indistinguishable from one that does not exist."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlements",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "INSUFFICIENT_BALANCE, SOURCE_ACCOUNT_NOT_USABLE (the account is frozen or closed), IDEMPOTENCY_MISMATCH (this key already settled something else — use a new key), SETTLEMENT_REQUIRES_APPROVAL (your organisation's approval rules would hold this settlement for approval, or block it, so it cannot be posted with an API key — make it in the app. A settlement the rules let through posts. It does NOT apply when you send a SUB-CLIENT's money under x-on-behalf-of: a sub-client has no approval policy of its own and the root's is not imposed on it), or SETTLEMENT_CONFLICT (a concurrent movement on the same account; nothing was written, retry the same request)."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "code": "TRANSFER_NOT_WITHIN_TREE",
                  "error": "Unprocessable Entity",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlements",
                  "statusCode": 422,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_NOT_CROSS_TREE (both accounts are under one root — use POST /transfers), SETTLEMENT_FIAT_ONLY, SETTLEMENT_TARGET_UNREACHABLE (that member cannot be paid), RECEIVER_HAS_NO_ACCOUNT (no active account of theirs in this currency), or RECEIVE_POLICY_REFUSED (that member accepts settlements from connected senders only)."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlements",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Settle to another network member",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlements/{id}": {
      "get": {
        "description": "The same row both parties read, with direction reported for YOU. A settlement you are not a party to answers 404 — never 403, which would confirm it exists.",
        "operationId": "get-settlement",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "activityId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "amount": "1500.00",
                    "createdAt": "2026-09-08T10:15:30.000Z",
                    "currency": "USD",
                    "direction": "OUT",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "endToEndId": "ACME-INV-2026-0042",
                    "fee": {
                      "amount": "0",
                      "currency": "USD"
                    },
                    "id": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "rail": "SETTLEMENT",
                    "receipt": null,
                    "receiver": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "remittance": {
                      "invoice": "INV-2026-0042"
                    },
                    "replayed": false,
                    "resolveVerdict": "MATCH",
                    "reversalOfId": null,
                    "reversedById": null,
                    "sender": {
                      "accountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                      "legalName": "Acme Trading Ltd"
                    },
                    "settledAt": "2026-09-08T10:15:30.000Z",
                    "settlementHoldId": null,
                    "settlementRequestId": null,
                    "settlementReturnId": null,
                    "status": "COMPLETED"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The settlement"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlements/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlements/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlements/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_NOT_FOUND."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/settlements/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one settlement by its stl_ id",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/settlements/{id}/return-request": {
      "post": {
        "description": "Only the SENDER may ask, only on a COMPLETED settlement, and only for the full amount in this version. Finality is untouched while the request is open: the receiver still holds the money and may decline.",
        "operationId": "create-settlement-return",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "1500.00",
                "reason": "Paid twice against the same invoice"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerSettlementReturnDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1500.00",
                    "counterparty": {
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13"
                    },
                    "createdAt": "2026-09-08T10:15:30.000Z",
                    "currency": "USD",
                    "decidedAt": null,
                    "declineReason": null,
                    "direction": "INBOUND",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "id": "sret_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "networkLabel": "CommaNet",
                    "pendingApprovalRequestId": null,
                    "rail": "SETTLEMENT",
                    "reason": "Paid twice against the same invoice",
                    "requestedBy": {
                      "clientAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13"
                    },
                    "reversalSettlementId": null,
                    "settlementId": "stl_3f8c1d2a5e6b7049a1b2c3d4e5f60718",
                    "status": "OPEN",
                    "updatedAt": "2026-09-08T10:15:30.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSettlementReturnResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The return request"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlements/{id}/return-request",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlements/{id}/return-request",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlements/{id}/return-request",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_RETURN_NOT_YOURS — only the sender asks."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlements/{id}/return-request",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_NOT_FOUND."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlements/{id}/return-request",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_NOT_RETURNABLE (not completed), SETTLEMENT_RETURN_NOT_OPEN (one is already open), SETTLEMENT_ALREADY_REVERSED, or SETTLEMENT_CONFLICT (a concurrent change to the same settlement; nothing was written, retry the request)."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "code": "TRANSFER_NOT_WITHIN_TREE",
                  "error": "Unprocessable Entity",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlements/{id}/return-request",
                  "statusCode": 422,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SETTLEMENT_RETURN_PARTIAL_UNSUPPORTED — omit amount, or send the settlement amount exactly."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/settlements/{id}/return-request",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Ask the receiver to return a settlement",
        "tags": [
          "Settlements"
        ]
      }
    },
    "/api/partner/v1/share-redemption-requests": {
      "get": {
        "description": "Newest first. Filter by status.",
        "operationId": "list-share-redemption-requests",
        "parameters": [
          {
            "description": "The nextCursor from the previous page. Opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "PENDING",
                "EXECUTING_ONCHAIN",
                "QUEUED",
                "SETTLED",
                "CANCELLED",
                "FAILED",
                "FAILED_PENDING_COMPENSATION",
                "COMPENSATED"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "items": [
                      {
                        "amount": "1000",
                        "createdAt": "2026-09-02T10:15:30.000Z",
                        "currency": "USD",
                        "custody": {
                          "mode": "TCB_SUBACCOUNT",
                          "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                        },
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                        "idempotencyKey": "acme-step-2026-10-12-0001",
                        "onchain": {
                          "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                        },
                        "queue": {
                          "claimableAt": "2026-09-02T10:15:30.000Z",
                          "fills": [
                            {
                              "bookedAt": "2026-09-02T10:15:30.000Z",
                              "tokens": "400",
                              "txHash": "0x8c41…"
                            }
                          ],
                          "onchainRequestId": "42",
                          "sharesEscrowed": "398.120000000000000000000000"
                        },
                        "replayed": false,
                        "settledAt": "2026-09-02T10:15:30.000Z",
                        "shares": {
                          "moved": "987.654321000000000000000000"
                        },
                        "status": "SETTLED",
                        "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "token": {
                          "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                          "chain": "ARBITRUM",
                          "symbol": "tcbUSD"
                        },
                        "tokens": {
                          "moved": "1000"
                        },
                        "type": "TOKEN_MINT",
                        "vault": {
                          "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                          "chain": "ARBITRUM"
                        }
                      }
                    ]
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfPartnerChainStepsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of requests"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemption-requests",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "limit, cursor or status malformed (INVALID_AMOUNT)"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemption-requests",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemption-requests",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemption-requests",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List your queued redemptions",
        "tags": [
          "Tokenised deposit chain"
        ]
      },
      "post": {
        "description": "Places shares booked to the sub-account in the vault's redemption queue for the tcbUSD amount you name. The vault pays the request once liquidity is available, possibly in parts; each part is booked to the sub-account as tcbUSD, the same as an instant redemption. The step answers QUEUED and moves to SETTLED (something was paid) or CANCELLED (you cancelled before anything was paid); follow it with the share_redemption_request.* events or GET. An idempotency key is MANDATORY: send it as the Idempotency-Key header or as the idempotencyKey body field. Replaying a key returns the original result without re-executing; reusing one with different parameters is rejected with IDEMPOTENCY_KEY_REUSED.",
        "operationId": "create-share-redemption-request",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. The key is remembered permanently: it is recorded against the movement it created, so a replay years later still resolves to that one movement.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "400",
                "currency": "USD",
                "idempotencyKey": "acme-step-2026-10-12-0001",
                "subAccountId": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerShareRedemptionRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1000",
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                    "idempotencyKey": "acme-step-2026-10-12-0001",
                    "onchain": {
                      "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                    },
                    "queue": {
                      "claimableAt": "2026-09-02T10:15:30.000Z",
                      "fills": [
                        {
                          "bookedAt": "2026-09-02T10:15:30.000Z",
                          "tokens": "400",
                          "txHash": "0x8c41…"
                        }
                      ],
                      "onchainRequestId": "42",
                      "sharesEscrowed": "398.120000000000000000000000"
                    },
                    "replayed": false,
                    "settledAt": "2026-09-02T10:15:30.000Z",
                    "shares": {
                      "moved": "987.654321000000000000000000"
                    },
                    "status": "SETTLED",
                    "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "token": {
                      "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                      "chain": "ARBITRUM",
                      "symbol": "tcbUSD"
                    },
                    "tokens": {
                      "moved": "1000"
                    },
                    "type": "TOKEN_MINT",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerChainStepResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Queued, or a replay: the request as it stands now"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemption-requests",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Invalid request, INSUFFICIENT_SUB_ACCOUNT_POSITION, INSUFFICIENT_VAULT_POSITION or WITHDRAWAL_CAP_EXCEEDED. Nothing was queued and the key stays usable."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemption-requests",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemption-requests",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemption-requests",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "VAULT_NOT_AVAILABLE, or an unknown sub-account"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemption-requests",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "IDEMPOTENCY_KEY_REUSED, IDEMPOTENT_REQUEST_IN_PROGRESS, VAULT_TOKEN_MISMATCH, PARTNER_RAIL_FROZEN or STEP_AUTHORIZATION_CONFLICT (retry with the same key)."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemption-requests",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          },
          "500": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTERNAL_ERROR",
                  "error": "Internal Server Error",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemption-requests",
                  "statusCode": 500,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SHARE_REDEMPTION_REQUEST_FAILED — the request never reached the vault queue; the shares are available again and a new key may be used."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "code": "CHAIN_UNAVAILABLE",
                  "error": "Service Unavailable",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemption-requests",
                  "statusCode": 503,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Chain read or gas unavailable. Nothing queued."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Queue a redemption in the vault's queue",
        "tags": [
          "Tokenised deposit chain"
        ]
      }
    },
    "/api/partner/v1/share-redemption-requests/{id}": {
      "get": {
        "description": "The request in its current state, with its place in the queue and what has been paid, read from the vault.",
        "operationId": "get-share-redemption-request",
        "parameters": [
          {
            "description": "The id returned when you created the step, or carried by its event.",
            "example": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1000",
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                    "idempotencyKey": "acme-step-2026-10-12-0001",
                    "onchain": {
                      "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                    },
                    "queue": {
                      "claimableAt": "2026-09-02T10:15:30.000Z",
                      "fills": [
                        {
                          "bookedAt": "2026-09-02T10:15:30.000Z",
                          "tokens": "400",
                          "txHash": "0x8c41…"
                        }
                      ],
                      "onchainRequestId": "42",
                      "sharesEscrowed": "398.120000000000000000000000"
                    },
                    "replayed": false,
                    "settledAt": "2026-09-02T10:15:30.000Z",
                    "shares": {
                      "moved": "987.654321000000000000000000"
                    },
                    "status": "SETTLED",
                    "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "token": {
                      "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                      "chain": "ARBITRUM",
                      "symbol": "tcbUSD"
                    },
                    "tokens": {
                      "moved": "1000"
                    },
                    "type": "TOKEN_MINT",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerChainStepResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The request"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemption-requests/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemption-requests/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemption-requests/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SHARE_REDEMPTION_REQUEST_NOT_FOUND"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemption-requests/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one queued redemption",
        "tags": [
          "Tokenised deposit chain"
        ]
      }
    },
    "/api/partner/v1/share-redemption-requests/{id}/cancel": {
      "post": {
        "description": "Takes the request out of the vault's queue. Shares not yet paid return to your sub-account; anything already paid stays paid. Answers the request in its new state: CANCELLED when nothing had been paid, SETTLED for the part that was.",
        "operationId": "cancel-share-redemption-request",
        "parameters": [
          {
            "description": "The id returned when you created the step, or carried by its event.",
            "example": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1000",
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                    "idempotencyKey": "acme-step-2026-10-12-0001",
                    "onchain": {
                      "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                    },
                    "queue": {
                      "claimableAt": "2026-09-02T10:15:30.000Z",
                      "fills": [
                        {
                          "bookedAt": "2026-09-02T10:15:30.000Z",
                          "tokens": "400",
                          "txHash": "0x8c41…"
                        }
                      ],
                      "onchainRequestId": "42",
                      "sharesEscrowed": "398.120000000000000000000000"
                    },
                    "replayed": false,
                    "settledAt": "2026-09-02T10:15:30.000Z",
                    "shares": {
                      "moved": "987.654321000000000000000000"
                    },
                    "status": "SETTLED",
                    "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "token": {
                      "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                      "chain": "ARBITRUM",
                      "symbol": "tcbUSD"
                    },
                    "tokens": {
                      "moved": "1000"
                    },
                    "type": "TOKEN_MINT",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerChainStepResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The request after the cancel"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemption-requests/{id}/cancel",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemption-requests/{id}/cancel",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemption-requests/{id}/cancel",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SHARE_REDEMPTION_REQUEST_NOT_FOUND"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemption-requests/{id}/cancel",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SHARE_REDEMPTION_REQUEST_NOT_CANCELLABLE — already paid, cancelled or failed. SHARE_REDEMPTION_REQUEST_NOT_CONFIRMED — not on the queue yet; retry shortly."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemption-requests/{id}/cancel",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "code": "CHAIN_UNAVAILABLE",
                  "error": "Service Unavailable",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemption-requests/{id}/cancel",
                  "statusCode": 503,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Gas could not be funded. Nothing was cancelled."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Cancel a queued redemption",
        "tags": [
          "Tokenised deposit chain"
        ]
      }
    },
    "/api/partner/v1/share-redemptions": {
      "get": {
        "description": "Newest first. Filter by status.",
        "operationId": "list-share-redemptions",
        "parameters": [
          {
            "description": "The nextCursor from the previous page. Opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "PENDING",
                "EXECUTING_ONCHAIN",
                "QUEUED",
                "SETTLED",
                "CANCELLED",
                "FAILED",
                "FAILED_PENDING_COMPENSATION",
                "COMPENSATED"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "items": [
                      {
                        "amount": "1000",
                        "createdAt": "2026-09-02T10:15:30.000Z",
                        "currency": "USD",
                        "custody": {
                          "mode": "TCB_SUBACCOUNT",
                          "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                        },
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                        "idempotencyKey": "acme-step-2026-10-12-0001",
                        "onchain": {
                          "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                        },
                        "queue": {
                          "claimableAt": "2026-09-02T10:15:30.000Z",
                          "fills": [
                            {
                              "bookedAt": "2026-09-02T10:15:30.000Z",
                              "tokens": "400",
                              "txHash": "0x8c41…"
                            }
                          ],
                          "onchainRequestId": "42",
                          "sharesEscrowed": "398.120000000000000000000000"
                        },
                        "replayed": false,
                        "settledAt": "2026-09-02T10:15:30.000Z",
                        "shares": {
                          "moved": "987.654321000000000000000000"
                        },
                        "status": "SETTLED",
                        "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "token": {
                          "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                          "chain": "ARBITRUM",
                          "symbol": "tcbUSD"
                        },
                        "tokens": {
                          "moved": "1000"
                        },
                        "type": "TOKEN_MINT",
                        "vault": {
                          "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                          "chain": "ARBITRUM"
                        }
                      }
                    ]
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfPartnerChainStepsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of redemptions"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemptions",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "limit, cursor or status malformed (INVALID_AMOUNT)"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemptions",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemptions",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemptions",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List your instant vault redemptions",
        "tags": [
          "Tokenised deposit chain"
        ]
      },
      "post": {
        "description": "Redeems vault shares booked to the sub-account for the tcbUSD amount you name, paid at once into the TCB wallet assigned to you and booked to the same sub-account. When the vault cannot pay the amount right now (INSUFFICIENT_VAULT_LIQUIDITY or INSUFFICIENT_VAULT_POSITION), queue it with POST /share-redemption-requests. An idempotency key is MANDATORY: send it as the Idempotency-Key header or as the idempotencyKey body field. Replaying a key returns the original result without re-executing; reusing one with different parameters is rejected with IDEMPOTENCY_KEY_REUSED.",
        "operationId": "create-share-redemption",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. The key is remembered permanently: it is recorded against the movement it created, so a replay years later still resolves to that one movement.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "400",
                "currency": "USD",
                "idempotencyKey": "acme-step-2026-10-12-0001",
                "subAccountId": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerShareRedemptionDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1000",
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                    "idempotencyKey": "acme-step-2026-10-12-0001",
                    "onchain": {
                      "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                    },
                    "queue": {
                      "claimableAt": "2026-09-02T10:15:30.000Z",
                      "fills": [
                        {
                          "bookedAt": "2026-09-02T10:15:30.000Z",
                          "tokens": "400",
                          "txHash": "0x8c41…"
                        }
                      ],
                      "onchainRequestId": "42",
                      "sharesEscrowed": "398.120000000000000000000000"
                    },
                    "replayed": false,
                    "settledAt": "2026-09-02T10:15:30.000Z",
                    "shares": {
                      "moved": "987.654321000000000000000000"
                    },
                    "status": "SETTLED",
                    "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "token": {
                      "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                      "chain": "ARBITRUM",
                      "symbol": "tcbUSD"
                    },
                    "tokens": {
                      "moved": "1000"
                    },
                    "type": "TOKEN_MINT",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerChainStepResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Redeemed, or the original result replayed"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemptions",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Invalid request, INSUFFICIENT_SUB_ACCOUNT_POSITION, INSUFFICIENT_VAULT_POSITION or WITHDRAWAL_CAP_EXCEEDED (a redemption counts against your withdrawal cap). Nothing moved and the key stays usable."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemptions",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemptions",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemptions",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "VAULT_NOT_AVAILABLE, or an unknown sub-account"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemptions",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "INSUFFICIENT_VAULT_LIQUIDITY — queue it instead. Or IDEMPOTENCY_KEY_REUSED, IDEMPOTENT_REQUEST_IN_PROGRESS, VAULT_TOKEN_MISMATCH, PARTNER_RAIL_FROZEN, STEP_AUTHORIZATION_CONFLICT."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemptions",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          },
          "500": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTERNAL_ERROR",
                  "error": "Internal Server Error",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemptions",
                  "statusCode": 500,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SHARE_REDEMPTION_FAILED_PENDING_COMPENSATION, SHARE_REDEMPTION_SETTLEMENT_NOT_RECORDED or LEDGER_ENTRY_NOT_RECORDED. On the *_FAILED_PENDING_COMPENSATION and *_SETTLEMENT_NOT_RECORDED codes the step is recorded for resolution: do NOT retry with a new key, which would move the money again."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "code": "CHAIN_UNAVAILABLE",
                  "error": "Service Unavailable",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-redemptions",
                  "statusCode": 503,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Chain read or gas unavailable. Nothing moved."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Take tcbUSD out of the vault, instantly",
        "tags": [
          "Tokenised deposit chain"
        ]
      }
    },
    "/api/partner/v1/share-redemptions/{id}": {
      "get": {
        "description": "The redemption in its current state.",
        "operationId": "get-share-redemption",
        "parameters": [
          {
            "description": "The id returned when you created the step, or carried by its event.",
            "example": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1000",
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                    "idempotencyKey": "acme-step-2026-10-12-0001",
                    "onchain": {
                      "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                    },
                    "queue": {
                      "claimableAt": "2026-09-02T10:15:30.000Z",
                      "fills": [
                        {
                          "bookedAt": "2026-09-02T10:15:30.000Z",
                          "tokens": "400",
                          "txHash": "0x8c41…"
                        }
                      ],
                      "onchainRequestId": "42",
                      "sharesEscrowed": "398.120000000000000000000000"
                    },
                    "replayed": false,
                    "settledAt": "2026-09-02T10:15:30.000Z",
                    "shares": {
                      "moved": "987.654321000000000000000000"
                    },
                    "status": "SETTLED",
                    "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "token": {
                      "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                      "chain": "ARBITRUM",
                      "symbol": "tcbUSD"
                    },
                    "tokens": {
                      "moved": "1000"
                    },
                    "type": "TOKEN_MINT",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerChainStepResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The redemption"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemptions/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemptions/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemptions/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No redemption with that id in your scope"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-redemptions/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one instant vault redemption",
        "tags": [
          "Tokenised deposit chain"
        ]
      }
    },
    "/api/partner/v1/share-subscriptions": {
      "get": {
        "description": "Newest first. Filter by status.",
        "operationId": "list-share-subscriptions",
        "parameters": [
          {
            "description": "The nextCursor from the previous page. Opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "PENDING",
                "EXECUTING_ONCHAIN",
                "QUEUED",
                "SETTLED",
                "CANCELLED",
                "FAILED",
                "FAILED_PENDING_COMPENSATION",
                "COMPENSATED"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "items": [
                      {
                        "amount": "1000",
                        "createdAt": "2026-09-02T10:15:30.000Z",
                        "currency": "USD",
                        "custody": {
                          "mode": "TCB_SUBACCOUNT",
                          "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                        },
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                        "idempotencyKey": "acme-step-2026-10-12-0001",
                        "onchain": {
                          "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                        },
                        "queue": {
                          "claimableAt": "2026-09-02T10:15:30.000Z",
                          "fills": [
                            {
                              "bookedAt": "2026-09-02T10:15:30.000Z",
                              "tokens": "400",
                              "txHash": "0x8c41…"
                            }
                          ],
                          "onchainRequestId": "42",
                          "sharesEscrowed": "398.120000000000000000000000"
                        },
                        "replayed": false,
                        "settledAt": "2026-09-02T10:15:30.000Z",
                        "shares": {
                          "moved": "987.654321000000000000000000"
                        },
                        "status": "SETTLED",
                        "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "token": {
                          "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                          "chain": "ARBITRUM",
                          "symbol": "tcbUSD"
                        },
                        "tokens": {
                          "moved": "1000"
                        },
                        "type": "TOKEN_MINT",
                        "vault": {
                          "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                          "chain": "ARBITRUM"
                        }
                      }
                    ]
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfPartnerChainStepsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of subscriptions"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-subscriptions",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "limit, cursor or status malformed (INVALID_AMOUNT)"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-subscriptions",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-subscriptions",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-subscriptions",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List your vault subscriptions",
        "tags": [
          "Tokenised deposit chain"
        ]
      },
      "post": {
        "description": "Moves tcbUSD booked to the sub-account into the currency's vault and books the shares it receives to the same sub-account. Authorised against that sub-account's available tcbUSD only. An idempotency key is MANDATORY: send it as the Idempotency-Key header or as the idempotencyKey body field. Replaying a key returns the original result without re-executing; reusing one with different parameters is rejected with IDEMPOTENCY_KEY_REUSED.",
        "operationId": "create-share-subscription",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. The key is remembered permanently: it is recorded against the movement it created, so a replay years later still resolves to that one movement.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "1000",
                "currency": "USD",
                "idempotencyKey": "acme-step-2026-10-12-0001",
                "subAccountId": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerShareSubscriptionDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1000",
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                    "idempotencyKey": "acme-step-2026-10-12-0001",
                    "onchain": {
                      "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                    },
                    "queue": {
                      "claimableAt": "2026-09-02T10:15:30.000Z",
                      "fills": [
                        {
                          "bookedAt": "2026-09-02T10:15:30.000Z",
                          "tokens": "400",
                          "txHash": "0x8c41…"
                        }
                      ],
                      "onchainRequestId": "42",
                      "sharesEscrowed": "398.120000000000000000000000"
                    },
                    "replayed": false,
                    "settledAt": "2026-09-02T10:15:30.000Z",
                    "shares": {
                      "moved": "987.654321000000000000000000"
                    },
                    "status": "SETTLED",
                    "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "token": {
                      "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                      "chain": "ARBITRUM",
                      "symbol": "tcbUSD"
                    },
                    "tokens": {
                      "moved": "1000"
                    },
                    "type": "TOKEN_MINT",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerChainStepResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Subscribed, or the original result replayed"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-subscriptions",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Invalid request, INSUFFICIENT_SUB_ACCOUNT_TOKENS or DEPOSIT_CAP_EXCEEDED (a subscription counts against your deposit cap). Nothing moved and the key stays usable."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-subscriptions",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-subscriptions",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "WALLET_NOT_ALLOWLISTED"
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-subscriptions",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "VAULT_NOT_AVAILABLE, or an unknown sub-account"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-subscriptions",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "IDEMPOTENCY_KEY_REUSED, IDEMPOTENT_REQUEST_IN_PROGRESS, VAULT_SUBSCRIPTIONS_CLOSED, VAULT_TOKEN_MISMATCH, PARTNER_RAIL_FROZEN or STEP_AUTHORIZATION_CONFLICT (retry with the same key)."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-subscriptions",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          },
          "500": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTERNAL_ERROR",
                  "error": "Internal Server Error",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-subscriptions",
                  "statusCode": 500,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SHARE_SUBSCRIPTION_FAILED_PENDING_COMPENSATION, SHARE_SUBSCRIPTION_SETTLEMENT_NOT_RECORDED or LEDGER_ENTRY_NOT_RECORDED. On the *_FAILED_PENDING_COMPENSATION and *_SETTLEMENT_NOT_RECORDED codes the step is recorded for resolution: do NOT retry with a new key, which would move the money again."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "code": "CHAIN_UNAVAILABLE",
                  "error": "Service Unavailable",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/share-subscriptions",
                  "statusCode": 503,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Chain read or gas unavailable (CHAIN_UNAVAILABLE, GAS_PREFLIGHT_FAILED). Nothing moved."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Put tcbUSD into the vault",
        "tags": [
          "Tokenised deposit chain"
        ]
      }
    },
    "/api/partner/v1/share-subscriptions/{id}": {
      "get": {
        "description": "The subscription in its current state.",
        "operationId": "get-share-subscription",
        "parameters": [
          {
            "description": "The id returned when you created the step, or carried by its event.",
            "example": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1000",
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                    "idempotencyKey": "acme-step-2026-10-12-0001",
                    "onchain": {
                      "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                    },
                    "queue": {
                      "claimableAt": "2026-09-02T10:15:30.000Z",
                      "fills": [
                        {
                          "bookedAt": "2026-09-02T10:15:30.000Z",
                          "tokens": "400",
                          "txHash": "0x8c41…"
                        }
                      ],
                      "onchainRequestId": "42",
                      "sharesEscrowed": "398.120000000000000000000000"
                    },
                    "replayed": false,
                    "settledAt": "2026-09-02T10:15:30.000Z",
                    "shares": {
                      "moved": "987.654321000000000000000000"
                    },
                    "status": "SETTLED",
                    "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "token": {
                      "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                      "chain": "ARBITRUM",
                      "symbol": "tcbUSD"
                    },
                    "tokens": {
                      "moved": "1000"
                    },
                    "type": "TOKEN_MINT",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerChainStepResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The subscription"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-subscriptions/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-subscriptions/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-subscriptions/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No subscription with that id in your scope"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/share-subscriptions/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one vault subscription",
        "tags": [
          "Tokenised deposit chain"
        ]
      }
    },
    "/api/partner/v1/statements": {
      "get": {
        "description": "Without `month`, a page of your already-issued statements. With `month`, the statement for that closed calendar month — issued on your first request for it, and the same statement id on every later request for the same month. A month that has not closed yet is refused.",
        "operationId": "list-statements",
        "parameters": [
          {
            "description": "A closed calendar month, `YYYY-MM`. Issues the statement on first read.",
            "example": "2026-08",
            "in": "query",
            "name": "month",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "The nextCursor from the previous page. Omit it for the first page. Treat it as opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Rows per page, 1-100. Defaults to 25. Ignored when `month` is set.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "items": [
                      {
                        "formats": [
                          "JSON",
                          "CSV"
                        ],
                        "id": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "issuedAt": "2026-09-02T10:15:30.000Z",
                        "payloadHash": "0f4c8b1d92a7e35604fd1c8a37b2905e6417da8c25f0b93e71c6482da05f3b9e",
                        "periodEnd": "2026-08-31",
                        "periodStart": "2026-08-01",
                        "supersededById": {},
                        "supersedesId": {}
                      }
                    ],
                    "nextCursor": {}
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfPartnerStatementsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of statements, or the single statement for `month`."
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/statements",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "STATEMENT_PERIOD_OPEN"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/statements",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/statements",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/statements",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List statements, or issue and return the one for a month",
        "tags": [
          "Statements"
        ]
      }
    },
    "/api/partner/v1/statements/{id}": {
      "get": {
        "operationId": "get-statement",
        "parameters": [
          {
            "description": "The statement id, as returned by GET /statements.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Defaults to json.",
            "in": "query",
            "name": "format",
            "required": false,
            "schema": {
              "enum": [
                "json",
                "csv"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "issuedAt": "2026-09-02T10:15:30.000Z",
                    "period": {
                      "from": "2026-08-01",
                      "to": "2026-08-31"
                    },
                    "statement": {
                      "notes": [
                        "No period-end asset valuation is included in this statement; the ledger records shares and per-entry asset amounts only."
                      ],
                      "subAccounts": [
                        {
                          "closingShares": "100000000000000000000000000",
                          "currencyCode": "USD",
                          "entries": [
                            {
                              "assets": "100.00",
                              "currencyCode": "USD",
                              "entryId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                              "entryType": "DEPOSIT",
                              "intentId": {},
                              "occurredAt": "2026-09-02T10:15:30.000Z",
                              "runningShares": "100000000000000000000000000",
                              "shares": "100000000000000000000000000"
                            }
                          ],
                          "externalRef": "tcb:default",
                          "openingShares": "0",
                          "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13"
                        }
                      ]
                    },
                    "supersededById": {},
                    "supersedesId": {}
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerStatementDetailResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The statement detail, or `text/csv` bytes when `format=csv`."
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/statements/{id}",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/statements/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/statements/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/statements/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "STATEMENT_NOT_FOUND"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/statements/{id}",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "STATEMENT_NOT_READY"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/statements/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Get one statement, as JSON or CSV",
        "tags": [
          "Statements"
        ]
      }
    },
    "/api/partner/v1/sub-accounts": {
      "get": {
        "description": "Registry rows only, oldest first, so your default sub-account leads the list. Positions are on GET /partner/v1/positions, which needs a currency to be meaningful.",
        "operationId": "list-sub-accounts",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "createdAt": "2026-08-14T08:42:11.000Z",
                      "externalRef": "acme-fund-002",
                      "isDefault": false,
                      "label": "Growth Fund II",
                      "subAccountId": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395"
                    }
                  ],
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/PartnerSubAccountResponse"
                      },
                      "type": "array"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Your sub-accounts"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-accounts",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-accounts",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-accounts",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List your sub-accounts",
        "tags": [
          "Vault sub-accounts"
        ]
      },
      "post": {
        "description": "Creates a named partition of your omnibus position. A sub-account is a partition of YOUR book: it confers no wallet, no key and no allowlist entry, and every share still sits in the one sub-account wallet TCB custodies for you. Use the returned subAccountId on deposits and withdrawals to attribute them; omit it and they land in your default sub-account.",
        "operationId": "create-sub-account",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "externalRef": "acme-fund-002",
                "label": "Growth Fund II"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerSubAccountDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "createdAt": "2026-08-14T08:42:11.000Z",
                    "externalRef": "acme-fund-002",
                    "isDefault": false,
                    "label": "Growth Fund II",
                    "subAccountId": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSubAccountResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Sub-account registered"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-accounts",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "externalRef is in the reserved tcb: namespace"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-accounts",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-accounts",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-accounts",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "externalRef already used by one of your sub-accounts"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-accounts",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Register a sub-account",
        "tags": [
          "Vault sub-accounts"
        ]
      }
    },
    "/api/partner/v1/sub-clients": {
      "get": {
        "description": "Registry rows, newest first, each carrying its own `totalHeldUsd` and `lastActivityAt` (#109 MR B). Money held for a sub-client is money you ADMINISTER — it is never part of your own balances, and no aggregate ACROSS sub-clients is returned here.",
        "operationId": "list-sub-clients",
        "parameters": [
          {
            "description": "The nextCursor from the previous page. Omit it for the first page. Treat it as opaque.",
            "example": "f39b0c74-51ae-4d82-9b06-3c7e2a5d1f80",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Rows per page, 1-100. Defaults to 25.",
            "example": 25,
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100
            }
          },
          {
            "description": "Defaults to returning both.",
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "ACTIVE",
                "CLOSED"
              ],
              "type": "string"
            }
          },
          {
            "description": "Return only the sub-client carrying this identifier of yours.",
            "example": "acme:cust-04231",
            "in": "query",
            "name": "externalRef",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Case-insensitive search across legal name, external ref and email.",
            "example": "khalifa",
            "in": "query",
            "name": "q",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "ISO 3166-1 alpha-2. Matches the derivation reported as the row `country`.",
            "example": "BH",
            "in": "query",
            "name": "country",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Filter to one sub-client kind.",
            "in": "query",
            "name": "type",
            "required": false,
            "schema": {
              "enum": [
                "person",
                "business"
              ],
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "items": [
                      {
                        "accounts": [
                          {
                            "accountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                            "balance": {
                              "available": "1000.00",
                              "reserved": "0.00",
                              "total": "1000.00"
                            },
                            "capabilities": {
                              "holdCrypto": true,
                              "holdSavings": false,
                              "receive": true,
                              "sendCrypto": true,
                              "sendExternal": false,
                              "sendInternal": true
                            },
                            "createdAt": "2026-08-14T08:42:11.000Z",
                            "currency": "EUR",
                            "disclosure": {
                              "items": [
                                "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                                "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                                "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                                "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                                "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                                "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                                "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                              ],
                              "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                              "version": "2026-10-27"
                            },
                            "externalRef": "acme:payroll-eur",
                            "iban": {
                              "active": false,
                              "bic": "TCBKBHBMXXX",
                              "holderName": "Fatima Al-Khalifa",
                              "iban": "BH29TCBK00001234567890"
                            },
                            "label": "Payroll reserve",
                            "localRails": [
                              {
                                "active": false,
                                "bankAddress": "Wiesenstrasse 17, 8952 Schlieren, Switzerland",
                                "bankName": "InCore Bank AG",
                                "beneficiaryName": "Fatima Al-Khalifa",
                                "bic": "INCOCHZZ",
                                "currency": "EUR",
                                "iban": "CH0508799123456789012",
                                "paymentReference": "TCB-7K2M9QXA",
                                "rail": "SEPA / SEPA Instant"
                              }
                            ],
                            "ownerId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                            "ownerType": "SUB_CLIENT",
                            "role": "MAIN",
                            "status": "ACTIVE"
                          }
                        ],
                        "caps": {
                          "USD": {
                            "daily": "50000",
                            "perTransfer": "10000"
                          }
                        },
                        "country": "BH",
                        "createdAt": "2026-08-14T08:42:11.000Z",
                        "cryptoAccounts": [
                          {
                            "accountId": "3b9e2f71-0c4d-4a58-9e16-7d2c5a8f1b40",
                            "address": "0x5c1f0a2b3d4e5f60718293a4b5c6d7e8f9012345",
                            "balances": [
                              {
                                "asset": "USDC",
                                "balance": "250.5"
                              }
                            ],
                            "chain": "ARBITRUM",
                            "status": "ACTIVE"
                          }
                        ],
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "externalRef": "acme:cust-04231",
                        "kind": "person",
                        "lastActivityAt": "2026-09-20T14:12:00.000Z",
                        "legalName": "Fatima Al-Khalifa",
                        "status": "ACTIVE",
                        "subClientId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                        "totalHeldUsd": "1250.00",
                        "updatedAt": "2026-08-28T09:00:00.000Z",
                        "verification": {
                          "attestedAt": "2026-08-28T09:00:00.000Z",
                          "capabilities": {
                            "holdCrypto": true,
                            "holdSavings": false,
                            "receive": true,
                            "sendCrypto": true,
                            "sendExternal": false,
                            "sendInternal": true
                          },
                          "level": "RELIANCE",
                          "requirements": {
                            "currentlyDue": [
                              "identity.person.dateOfBirth",
                              "attestation",
                              "screening"
                            ],
                            "disabledReason": null,
                            "eventuallyDue": [],
                            "pastDue": []
                          },
                          "status": "VERIFIED",
                          "verifiedAt": "2026-08-28T09:00:00.000Z"
                        }
                      }
                    ],
                    "nextCursor": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfSubClientsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of sub-clients"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List your sub-clients",
        "tags": [
          "Sub-clients"
        ]
      },
      "post": {
        "description": "Creates a sub-client and, atomically, reserves one MAIN account per requested currency. Every one of them receives on the sub-client's IBAN, which carries its own legal name as the payee name, and each also carries local details for its currency where the currency has them. Nothing is live yet: every capability is false and the details are inactive until the sub-client is VERIFIED — it must not be given out, is not entered into verification of payee, and accepts no funds. `identity` and `attestation` are both optional on this call: omitting either leaves the sub-client REQUIREMENTS_DUE, which names what is still outstanding, rather than rejecting the call. Cannot be called under x-on-behalf-of — a sub-client never has sub-clients.",
        "operationId": "create-sub-client",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. A key is remembered for 24 hours from the first call; after that it is forgotten and reusing it starts a new request.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "attestation": {
                  "cddPerformedAt": "2026-08-28T09:00:00.000Z",
                  "cddStandard": "standard",
                  "idempotencyKey": "acme-2026-09-02-0001",
                  "pepStatus": "none",
                  "riskRating": "low",
                  "screeningResult": "clear",
                  "text": "We have performed customer due diligence and screening on this customer under our agreed reliance programme.",
                  "verificationMethod": "documentary",
                  "verificationResult": "verified",
                  "verifierRef": "acme-case-88214",
                  "version": "reliance-2026-09"
                },
                "currencies": [
                  "EUR"
                ],
                "externalRef": "acme:cust-04231",
                "idempotencyKey": "acme-2026-09-02-0001",
                "identity": {
                  "address": {
                    "city": "Manama",
                    "country": "BH",
                    "line1": "14 Road 2825"
                  },
                  "dateOfBirth": "1988-04-17",
                  "firstName": "Fatima",
                  "lastName": "Al-Khalifa",
                  "nationality": "BH"
                },
                "kind": "person",
                "legalName": "Fatima Al-Khalifa",
                "metadata": {
                  "onboardedBy": "app",
                  "segment": "retail"
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CreateSubClientDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "accounts": [
                      {
                        "accountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                        "balance": {
                          "available": "1000.00",
                          "reserved": "0.00",
                          "total": "1000.00"
                        },
                        "capabilities": {
                          "holdCrypto": true,
                          "holdSavings": false,
                          "receive": true,
                          "sendCrypto": true,
                          "sendExternal": false,
                          "sendInternal": true
                        },
                        "createdAt": "2026-08-14T08:42:11.000Z",
                        "currency": "EUR",
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "externalRef": "acme:payroll-eur",
                        "iban": {
                          "active": false,
                          "bic": "TCBKBHBMXXX",
                          "holderName": "Fatima Al-Khalifa",
                          "iban": "BH29TCBK00001234567890"
                        },
                        "label": "Payroll reserve",
                        "localRails": [
                          {
                            "active": false,
                            "bankAddress": "Wiesenstrasse 17, 8952 Schlieren, Switzerland",
                            "bankName": "InCore Bank AG",
                            "beneficiaryName": "Fatima Al-Khalifa",
                            "bic": "INCOCHZZ",
                            "currency": "EUR",
                            "iban": "CH0508799123456789012",
                            "paymentReference": "TCB-7K2M9QXA",
                            "rail": "SEPA / SEPA Instant"
                          }
                        ],
                        "ownerId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                        "ownerType": "SUB_CLIENT",
                        "role": "MAIN",
                        "status": "ACTIVE"
                      }
                    ],
                    "caps": {
                      "USD": {
                        "daily": "50000",
                        "perTransfer": "10000"
                      }
                    },
                    "country": "BH",
                    "createdAt": "2026-08-14T08:42:11.000Z",
                    "cryptoAccounts": [
                      {
                        "accountId": "3b9e2f71-0c4d-4a58-9e16-7d2c5a8f1b40",
                        "address": "0x5c1f0a2b3d4e5f60718293a4b5c6d7e8f9012345",
                        "balances": [
                          {
                            "asset": "USDC",
                            "balance": "250.5"
                          }
                        ],
                        "chain": "ARBITRUM",
                        "status": "ACTIVE"
                      }
                    ],
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "externalRef": "acme:cust-04231",
                    "kind": "person",
                    "lastActivityAt": "2026-09-20T14:12:00.000Z",
                    "legalName": "Fatima Al-Khalifa",
                    "status": "ACTIVE",
                    "subClientId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                    "totalHeldUsd": "1250.00",
                    "updatedAt": "2026-08-28T09:00:00.000Z",
                    "verification": {
                      "attestedAt": "2026-08-28T09:00:00.000Z",
                      "capabilities": {
                        "holdCrypto": true,
                        "holdSavings": false,
                        "receive": true,
                        "sendCrypto": true,
                        "sendExternal": false,
                        "sendInternal": true
                      },
                      "level": "RELIANCE",
                      "requirements": {
                        "currentlyDue": [
                          "identity.person.dateOfBirth",
                          "attestation",
                          "screening"
                        ],
                        "disabledReason": null,
                        "eventuallyDue": [],
                        "pastDue": []
                      },
                      "status": "VERIFIED",
                      "verifiedAt": "2026-08-28T09:00:00.000Z"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSubClientResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Sub-client created"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SUB_CLIENT_EXTERNAL_REF_RESERVED, CURRENCY_NOT_SUPPORTED, IDENTITY_INVALID or — when the request embeds an `attestation` — ATTESTATION_INCOMPLETE, ATTESTATION_VERSION_UNKNOWN or ATTESTATION_TEXT_MISMATCH (details.version)"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "VERIFICATION_LEVEL_NOT_GRANTED — contact TCB"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SUB_CLIENT_EXTERNAL_REF_TAKEN, or RELIANCE_PROGRAMME_RESTRICTED when the request embeds an `attestation` and your reliance programme is restricted — contact TCB"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Create a sub-client",
        "tags": [
          "Sub-clients"
        ]
      }
    },
    "/api/partner/v1/sub-clients/{id}": {
      "get": {
        "description": "One of your end customers. Each sub-client holds its own account with TCB, in its own name; you collect the identity information, TCB accepts it, and you instruct on the sub-client's behalf. Returned: its identity handles, where it stands in verification, what it may do today, its accounts and the transfer ceilings you set on it. An id outside your tree answers 404 rather than 403, so an id cannot be probed for existence.",
        "operationId": "get-sub-client",
        "parameters": [
          {
            "description": "The sub-client id, as returned by GET /sub-clients.",
            "example": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "accounts": [
                      {
                        "accountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                        "balance": {
                          "available": "1000.00",
                          "reserved": "0.00",
                          "total": "1000.00"
                        },
                        "capabilities": {
                          "holdCrypto": true,
                          "holdSavings": false,
                          "receive": true,
                          "sendCrypto": true,
                          "sendExternal": false,
                          "sendInternal": true
                        },
                        "createdAt": "2026-08-14T08:42:11.000Z",
                        "currency": "EUR",
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "externalRef": "acme:payroll-eur",
                        "iban": {
                          "active": false,
                          "bic": "TCBKBHBMXXX",
                          "holderName": "Fatima Al-Khalifa",
                          "iban": "BH29TCBK00001234567890"
                        },
                        "label": "Payroll reserve",
                        "localRails": [
                          {
                            "active": false,
                            "bankAddress": "Wiesenstrasse 17, 8952 Schlieren, Switzerland",
                            "bankName": "InCore Bank AG",
                            "beneficiaryName": "Fatima Al-Khalifa",
                            "bic": "INCOCHZZ",
                            "currency": "EUR",
                            "iban": "CH0508799123456789012",
                            "paymentReference": "TCB-7K2M9QXA",
                            "rail": "SEPA / SEPA Instant"
                          }
                        ],
                        "ownerId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                        "ownerType": "SUB_CLIENT",
                        "role": "MAIN",
                        "status": "ACTIVE"
                      }
                    ],
                    "caps": {
                      "USD": {
                        "daily": "50000",
                        "perTransfer": "10000"
                      }
                    },
                    "country": "BH",
                    "createdAt": "2026-08-14T08:42:11.000Z",
                    "cryptoAccounts": [
                      {
                        "accountId": "3b9e2f71-0c4d-4a58-9e16-7d2c5a8f1b40",
                        "address": "0x5c1f0a2b3d4e5f60718293a4b5c6d7e8f9012345",
                        "balances": [
                          {
                            "asset": "USDC",
                            "balance": "250.5"
                          }
                        ],
                        "chain": "ARBITRUM",
                        "status": "ACTIVE"
                      }
                    ],
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "externalRef": "acme:cust-04231",
                    "kind": "person",
                    "lastActivityAt": "2026-09-20T14:12:00.000Z",
                    "legalName": "Fatima Al-Khalifa",
                    "status": "ACTIVE",
                    "subClientId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                    "totalHeldUsd": "1250.00",
                    "updatedAt": "2026-08-28T09:00:00.000Z",
                    "verification": {
                      "attestedAt": "2026-08-28T09:00:00.000Z",
                      "capabilities": {
                        "holdCrypto": true,
                        "holdSavings": false,
                        "receive": true,
                        "sendCrypto": true,
                        "sendExternal": false,
                        "sendInternal": true
                      },
                      "level": "RELIANCE",
                      "requirements": {
                        "currentlyDue": [
                          "identity.person.dateOfBirth",
                          "attestation",
                          "screening"
                        ],
                        "disabledReason": null,
                        "eventuallyDue": [],
                        "pastDue": []
                      },
                      "status": "VERIFIED",
                      "verifiedAt": "2026-08-28T09:00:00.000Z"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSubClientResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The sub-client"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SUB_CLIENT_NOT_FOUND"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one sub-client by id",
        "tags": [
          "Sub-clients"
        ]
      },
      "patch": {
        "description": "Merges an identity patch field by field and/or changes the legal name. A legalName change on a VERIFIED sub-client moves it back to REQUIREMENTS_DUE and deactivates its IBANs until it is verified again. Nothing is re-issued: the same coordinates reactivate, carrying the corrected payee name.",
        "operationId": "update-sub-client",
        "parameters": [
          {
            "description": "The sub-client id.",
            "example": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "caps": {
                  "USD": {
                    "daily": "50000",
                    "perTransfer": "10000"
                  }
                },
                "identity": {
                  "address": {
                    "city": "Manama",
                    "country": "BH",
                    "line1": "9 Road 3812"
                  }
                },
                "legalName": "Fatima Al-Khalifa",
                "metadata": {
                  "segment": "priority"
                }
              },
              "schema": {
                "$ref": "#/components/schemas/UpdateSubClientDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "accounts": [
                      {
                        "accountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                        "balance": {
                          "available": "1000.00",
                          "reserved": "0.00",
                          "total": "1000.00"
                        },
                        "capabilities": {
                          "holdCrypto": true,
                          "holdSavings": false,
                          "receive": true,
                          "sendCrypto": true,
                          "sendExternal": false,
                          "sendInternal": true
                        },
                        "createdAt": "2026-08-14T08:42:11.000Z",
                        "currency": "EUR",
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "externalRef": "acme:payroll-eur",
                        "iban": {
                          "active": false,
                          "bic": "TCBKBHBMXXX",
                          "holderName": "Fatima Al-Khalifa",
                          "iban": "BH29TCBK00001234567890"
                        },
                        "label": "Payroll reserve",
                        "localRails": [
                          {
                            "active": false,
                            "bankAddress": "Wiesenstrasse 17, 8952 Schlieren, Switzerland",
                            "bankName": "InCore Bank AG",
                            "beneficiaryName": "Fatima Al-Khalifa",
                            "bic": "INCOCHZZ",
                            "currency": "EUR",
                            "iban": "CH0508799123456789012",
                            "paymentReference": "TCB-7K2M9QXA",
                            "rail": "SEPA / SEPA Instant"
                          }
                        ],
                        "ownerId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                        "ownerType": "SUB_CLIENT",
                        "role": "MAIN",
                        "status": "ACTIVE"
                      }
                    ],
                    "caps": {
                      "USD": {
                        "daily": "50000",
                        "perTransfer": "10000"
                      }
                    },
                    "country": "BH",
                    "createdAt": "2026-08-14T08:42:11.000Z",
                    "cryptoAccounts": [
                      {
                        "accountId": "3b9e2f71-0c4d-4a58-9e16-7d2c5a8f1b40",
                        "address": "0x5c1f0a2b3d4e5f60718293a4b5c6d7e8f9012345",
                        "balances": [
                          {
                            "asset": "USDC",
                            "balance": "250.5"
                          }
                        ],
                        "chain": "ARBITRUM",
                        "status": "ACTIVE"
                      }
                    ],
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "externalRef": "acme:cust-04231",
                    "kind": "person",
                    "lastActivityAt": "2026-09-20T14:12:00.000Z",
                    "legalName": "Fatima Al-Khalifa",
                    "status": "ACTIVE",
                    "subClientId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                    "totalHeldUsd": "1250.00",
                    "updatedAt": "2026-08-28T09:00:00.000Z",
                    "verification": {
                      "attestedAt": "2026-08-28T09:00:00.000Z",
                      "capabilities": {
                        "holdCrypto": true,
                        "holdSavings": false,
                        "receive": true,
                        "sendCrypto": true,
                        "sendExternal": false,
                        "sendInternal": true
                      },
                      "level": "RELIANCE",
                      "requirements": {
                        "currentlyDue": [
                          "identity.person.dateOfBirth",
                          "attestation",
                          "screening"
                        ],
                        "disabledReason": null,
                        "eventuallyDue": [],
                        "pastDue": []
                      },
                      "status": "VERIFIED",
                      "verifiedAt": "2026-08-28T09:00:00.000Z"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSubClientResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Sub-client updated"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "PATCH",
                  "path": "/api/partner/v1/sub-clients/{id}",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "IDENTITY_INVALID (details.fields[])"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "PATCH",
                  "path": "/api/partner/v1/sub-clients/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "PATCH",
                  "path": "/api/partner/v1/sub-clients/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "PATCH",
                  "path": "/api/partner/v1/sub-clients/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SUB_CLIENT_NOT_FOUND"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "PATCH",
                  "path": "/api/partner/v1/sub-clients/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Update a sub-client",
        "tags": [
          "Sub-clients"
        ]
      }
    },
    "/api/partner/v1/sub-clients/{id}/attestations": {
      "get": {
        "description": "Newest first.",
        "operationId": "list-attestations",
        "parameters": [
          {
            "description": "The sub-client id.",
            "example": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "items": [
                      {
                        "attestationId": "b7f204e9-1c86-4a53-9e70-3d5f8b1c0a29",
                        "cddPerformedAt": "2026-08-28T09:00:00.000Z",
                        "cddStandard": "standard",
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "level": "RELIANCE",
                        "payloadSha256": "0f4c8b1d92a7e35604fd1c8a37b2905e6417da8c25f0b93e71c6482da05f3b9e",
                        "pepStatus": "none",
                        "receivedAt": "2026-08-28T09:00:04.000Z",
                        "riskRating": "low",
                        "screeningResult": "clear",
                        "subClientId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                        "text": "We have performed customer due diligence and screening on this customer under our agreed reliance programme.",
                        "verificationMethod": "documentary",
                        "verificationResult": "verified",
                        "verifierRef": "acme-case-88214",
                        "version": "reliance-2026-09"
                      }
                    ]
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AttestationListResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The attestations"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients/{id}/attestations",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients/{id}/attestations",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients/{id}/attestations",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SUB_CLIENT_NOT_FOUND"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients/{id}/attestations",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List a sub-client's attestations",
        "tags": [
          "Sub-clients"
        ]
      },
      "post": {
        "description": "Your statement, to TCB, that you performed CDD and screening on this customer under your own regulated programme. It is evidence of that work, not what activates the sub-client: activation also requires the mandatory identity data, your screening results and TCB's own screening. An attestation missing a required field, or sent for a sub-client whose mandatory identity data is still outstanding, is refused and nothing is recorded. `text` and `version` must be the wording TCB agreed for your programme, sent verbatim with its version string — a retired or unrecognised version, or text that no longer matches it, is also refused. Append-only: no edit, no delete — a new attestation supersedes a stale one, and the database refuses every UPDATE and DELETE.",
        "operationId": "create-attestation",
        "parameters": [
          {
            "description": "The sub-client id.",
            "example": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. A key is remembered for 24 hours from the first call; after that it is forgotten and reusing it starts a new request.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "cddPerformedAt": "2026-08-28T09:00:00.000Z",
                "cddStandard": "standard",
                "idempotencyKey": "acme-2026-09-02-0001",
                "pepStatus": "none",
                "riskRating": "low",
                "screeningResult": "clear",
                "text": "We have performed customer due diligence and screening on this customer under our agreed reliance programme.",
                "verificationMethod": "documentary",
                "verificationResult": "verified",
                "verifierRef": "acme-case-88214",
                "version": "reliance-2026-09"
              },
              "schema": {
                "$ref": "#/components/schemas/AttestationDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "attestationId": "b7f204e9-1c86-4a53-9e70-3d5f8b1c0a29",
                    "cddPerformedAt": "2026-08-28T09:00:00.000Z",
                    "cddStandard": "standard",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "level": "RELIANCE",
                    "payloadSha256": "0f4c8b1d92a7e35604fd1c8a37b2905e6417da8c25f0b93e71c6482da05f3b9e",
                    "pepStatus": "none",
                    "receivedAt": "2026-08-28T09:00:04.000Z",
                    "riskRating": "low",
                    "screeningResult": "clear",
                    "subClientId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                    "text": "We have performed customer due diligence and screening on this customer under our agreed reliance programme.",
                    "verificationMethod": "documentary",
                    "verificationResult": "verified",
                    "verifierRef": "acme-case-88214",
                    "version": "reliance-2026-09"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerAttestationResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Attestation recorded"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/attestations",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "ATTESTATION_INCOMPLETE, ATTESTATION_VERSION_UNKNOWN or ATTESTATION_TEXT_MISMATCH (details.version)"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/attestations",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/attestations",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/attestations",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SUB_CLIENT_NOT_FOUND"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/attestations",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "RELIANCE_PROGRAMME_RESTRICTED — your reliance programme is restricted, contact TCB"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/attestations",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Append an attestation",
        "tags": [
          "Sub-clients"
        ]
      }
    },
    "/api/partner/v1/sub-clients/{id}/close": {
      "post": {
        "description": "Irreversible. Every account under the sub-client must hold a zero balance. On success every IBAN retires; inbound to a retired IBAN is parked by TCB, never credited.",
        "operationId": "close-sub-client",
        "parameters": [
          {
            "description": "The sub-client id.",
            "example": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Your own key for this request, 1-100 characters. Required: this route takes no body, so the header is the only place to send it. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. A key is remembered for 24 hours from the first call; after that it is forgotten and reusing it starts a new request.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "accounts": [
                      {
                        "accountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                        "balance": {
                          "available": "1000.00",
                          "reserved": "0.00",
                          "total": "1000.00"
                        },
                        "capabilities": {
                          "holdCrypto": true,
                          "holdSavings": false,
                          "receive": true,
                          "sendCrypto": true,
                          "sendExternal": false,
                          "sendInternal": true
                        },
                        "createdAt": "2026-08-14T08:42:11.000Z",
                        "currency": "EUR",
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "externalRef": "acme:payroll-eur",
                        "iban": {
                          "active": false,
                          "bic": "TCBKBHBMXXX",
                          "holderName": "Fatima Al-Khalifa",
                          "iban": "BH29TCBK00001234567890"
                        },
                        "label": "Payroll reserve",
                        "localRails": [
                          {
                            "active": false,
                            "bankAddress": "Wiesenstrasse 17, 8952 Schlieren, Switzerland",
                            "bankName": "InCore Bank AG",
                            "beneficiaryName": "Fatima Al-Khalifa",
                            "bic": "INCOCHZZ",
                            "currency": "EUR",
                            "iban": "CH0508799123456789012",
                            "paymentReference": "TCB-7K2M9QXA",
                            "rail": "SEPA / SEPA Instant"
                          }
                        ],
                        "ownerId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                        "ownerType": "SUB_CLIENT",
                        "role": "MAIN",
                        "status": "ACTIVE"
                      }
                    ],
                    "caps": {
                      "USD": {
                        "daily": "50000",
                        "perTransfer": "10000"
                      }
                    },
                    "country": "BH",
                    "createdAt": "2026-08-14T08:42:11.000Z",
                    "cryptoAccounts": [
                      {
                        "accountId": "3b9e2f71-0c4d-4a58-9e16-7d2c5a8f1b40",
                        "address": "0x5c1f0a2b3d4e5f60718293a4b5c6d7e8f9012345",
                        "balances": [
                          {
                            "asset": "USDC",
                            "balance": "250.5"
                          }
                        ],
                        "chain": "ARBITRUM",
                        "status": "ACTIVE"
                      }
                    ],
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "externalRef": "acme:cust-04231",
                    "kind": "person",
                    "lastActivityAt": "2026-09-20T14:12:00.000Z",
                    "legalName": "Fatima Al-Khalifa",
                    "status": "ACTIVE",
                    "subClientId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                    "totalHeldUsd": "1250.00",
                    "updatedAt": "2026-08-28T09:00:00.000Z",
                    "verification": {
                      "attestedAt": "2026-08-28T09:00:00.000Z",
                      "capabilities": {
                        "holdCrypto": true,
                        "holdSavings": false,
                        "receive": true,
                        "sendCrypto": true,
                        "sendExternal": false,
                        "sendInternal": true
                      },
                      "level": "RELIANCE",
                      "requirements": {
                        "currentlyDue": [
                          "identity.person.dateOfBirth",
                          "attestation",
                          "screening"
                        ],
                        "disabledReason": null,
                        "eventuallyDue": [],
                        "pastDue": []
                      },
                      "status": "VERIFIED",
                      "verifiedAt": "2026-08-28T09:00:00.000Z"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSubClientResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Sub-client closed"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/close",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The request failed validation: a body field or query parameter is missing, malformed, or outside the range this route accepts. `message` names what was wrong."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/close",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/close",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/close",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SUB_CLIENT_HAS_CRYPTO_BALANCE (details.accountIds; checked first) while a crypto account still holds an asset, SUB_CLIENT_HAS_BALANCE (details.accountIds), or SUB_CLIENT_HAS_PENDING_ACTIVITY (details.accountIds, details.pending[]) while a movement against one of the sub-client's accounts has not reached a terminal state. An account can read a zero balance and still be named: an outbound payout debits it when it is admitted, and a return or a failure credits it back. SUB_CLIENT_HAS_CRYPTO_DEPOSIT_IN_FLIGHT (details.accountIds, details.depositIds) while a crypto deposit to the sub-client is still confirming."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/close",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Close a sub-client",
        "tags": [
          "Sub-clients"
        ]
      }
    },
    "/api/partner/v1/sub-clients/{id}/currencies": {
      "post": {
        "description": "Creates that currency's MAIN account the same way POST /sub-clients does at creation: it receives on the sub-client's IBAN, and carries local details for its currency where the currency has them. Nothing is active until the sub-client is VERIFIED.",
        "operationId": "add-sub-client-currency",
        "parameters": [
          {
            "description": "The sub-client id.",
            "example": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. A key is remembered for 24 hours from the first call; after that it is forgotten and reusing it starts a new request.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "currency": "USD",
                "idempotencyKey": "acme-2026-09-02-0001"
              },
              "schema": {
                "$ref": "#/components/schemas/AddSubClientCurrencyDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "accounts": [
                      {
                        "accountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
                        "balance": {
                          "available": "1000.00",
                          "reserved": "0.00",
                          "total": "1000.00"
                        },
                        "capabilities": {
                          "holdCrypto": true,
                          "holdSavings": false,
                          "receive": true,
                          "sendCrypto": true,
                          "sendExternal": false,
                          "sendInternal": true
                        },
                        "createdAt": "2026-08-14T08:42:11.000Z",
                        "currency": "EUR",
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "externalRef": "acme:payroll-eur",
                        "iban": {
                          "active": false,
                          "bic": "TCBKBHBMXXX",
                          "holderName": "Fatima Al-Khalifa",
                          "iban": "BH29TCBK00001234567890"
                        },
                        "label": "Payroll reserve",
                        "localRails": [
                          {
                            "active": false,
                            "bankAddress": "Wiesenstrasse 17, 8952 Schlieren, Switzerland",
                            "bankName": "InCore Bank AG",
                            "beneficiaryName": "Fatima Al-Khalifa",
                            "bic": "INCOCHZZ",
                            "currency": "EUR",
                            "iban": "CH0508799123456789012",
                            "paymentReference": "TCB-7K2M9QXA",
                            "rail": "SEPA / SEPA Instant"
                          }
                        ],
                        "ownerId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                        "ownerType": "SUB_CLIENT",
                        "role": "MAIN",
                        "status": "ACTIVE"
                      }
                    ],
                    "caps": {
                      "USD": {
                        "daily": "50000",
                        "perTransfer": "10000"
                      }
                    },
                    "country": "BH",
                    "createdAt": "2026-08-14T08:42:11.000Z",
                    "cryptoAccounts": [
                      {
                        "accountId": "3b9e2f71-0c4d-4a58-9e16-7d2c5a8f1b40",
                        "address": "0x5c1f0a2b3d4e5f60718293a4b5c6d7e8f9012345",
                        "balances": [
                          {
                            "asset": "USDC",
                            "balance": "250.5"
                          }
                        ],
                        "chain": "ARBITRUM",
                        "status": "ACTIVE"
                      }
                    ],
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "externalRef": "acme:cust-04231",
                    "kind": "person",
                    "lastActivityAt": "2026-09-20T14:12:00.000Z",
                    "legalName": "Fatima Al-Khalifa",
                    "status": "ACTIVE",
                    "subClientId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                    "totalHeldUsd": "1250.00",
                    "updatedAt": "2026-08-28T09:00:00.000Z",
                    "verification": {
                      "attestedAt": "2026-08-28T09:00:00.000Z",
                      "capabilities": {
                        "holdCrypto": true,
                        "holdSavings": false,
                        "receive": true,
                        "sendCrypto": true,
                        "sendExternal": false,
                        "sendInternal": true
                      },
                      "level": "RELIANCE",
                      "requirements": {
                        "currentlyDue": [
                          "identity.person.dateOfBirth",
                          "attestation",
                          "screening"
                        ],
                        "disabledReason": null,
                        "eventuallyDue": [],
                        "pastDue": []
                      },
                      "status": "VERIFIED",
                      "verifiedAt": "2026-08-28T09:00:00.000Z"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerSubClientResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Currency added"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/currencies",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "CURRENCY_NOT_SUPPORTED"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/currencies",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/currencies",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/currencies",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "The sub-client already holds a MAIN in that currency"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/sub-clients/{id}/currencies",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Add a currency to a sub-client",
        "tags": [
          "Sub-clients"
        ]
      }
    },
    "/api/partner/v1/sub-clients/{id}/identity": {
      "get": {
        "description": "Returns what you supplied, as stored — TCB adds nothing to it.",
        "operationId": "get-sub-client-identity",
        "parameters": [
          {
            "description": "The sub-client id.",
            "example": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "business": {
                      "businessActivity": "Payment services",
                      "incorporation": {
                        "country": "BH",
                        "date": "2019-02-01"
                      },
                      "legalForm": "W.L.L.",
                      "parties": [
                        {
                          "address": "BH",
                          "dateOfBirth": "1978-06-30",
                          "firstName": "Yousef",
                          "lastName": "Al-Sayed",
                          "nationalId": "780630221",
                          "nationality": "BH",
                          "ownershipPercent": "60",
                          "role": "ubo"
                        }
                      ],
                      "registeredAddress": {
                        "city": "Manama",
                        "country": "BH",
                        "line1": "Bahrain Bay Tower"
                      },
                      "registrationNumber": "CR-114523",
                      "seniorManagement": [
                        {
                          "firstName": "Layla",
                          "lastName": "Mansour",
                          "role": "CEO"
                        }
                      ]
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "kind": "person",
                    "person": {
                      "address": {
                        "city": "Manama",
                        "country": "BH",
                        "line1": "14 Road 2825"
                      },
                      "dateOfBirth": "1988-04-17",
                      "firstName": "Fatima",
                      "lastName": "Al-Khalifa",
                      "nationality": "BH"
                    },
                    "subClientId": "c4f81e2a-9b60-4d37-a512-8e0f3c6b7d95",
                    "updatedAt": "2026-08-28T09:00:00.000Z"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/IdentityRecordResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The identity record"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients/{id}/identity",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients/{id}/identity",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients/{id}/identity",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SUB_CLIENT_NOT_FOUND"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/sub-clients/{id}/identity",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch a sub-client's identity record",
        "tags": [
          "Sub-clients"
        ]
      }
    },
    "/api/partner/v1/token-mints": {
      "get": {
        "description": "Newest first. Filter by status.",
        "operationId": "list-token-mints",
        "parameters": [
          {
            "description": "The nextCursor from the previous page. Opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "PENDING",
                "EXECUTING_ONCHAIN",
                "QUEUED",
                "SETTLED",
                "CANCELLED",
                "FAILED",
                "FAILED_PENDING_COMPENSATION",
                "COMPENSATED"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "items": [
                      {
                        "amount": "1000",
                        "createdAt": "2026-09-02T10:15:30.000Z",
                        "currency": "USD",
                        "custody": {
                          "mode": "TCB_SUBACCOUNT",
                          "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                        },
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                        "idempotencyKey": "acme-step-2026-10-12-0001",
                        "onchain": {
                          "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                        },
                        "queue": {
                          "claimableAt": "2026-09-02T10:15:30.000Z",
                          "fills": [
                            {
                              "bookedAt": "2026-09-02T10:15:30.000Z",
                              "tokens": "400",
                              "txHash": "0x8c41…"
                            }
                          ],
                          "onchainRequestId": "42",
                          "sharesEscrowed": "398.120000000000000000000000"
                        },
                        "replayed": false,
                        "settledAt": "2026-09-02T10:15:30.000Z",
                        "shares": {
                          "moved": "987.654321000000000000000000"
                        },
                        "status": "SETTLED",
                        "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "token": {
                          "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                          "chain": "ARBITRUM",
                          "symbol": "tcbUSD"
                        },
                        "tokens": {
                          "moved": "1000"
                        },
                        "type": "TOKEN_MINT",
                        "vault": {
                          "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                          "chain": "ARBITRUM"
                        }
                      }
                    ]
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfPartnerChainStepsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of mints"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-mints",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "limit, cursor or status malformed (INVALID_AMOUNT)"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-mints",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-mints",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-mints",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List your tcbUSD mints",
        "tags": [
          "Tokenised deposit chain"
        ]
      },
      "post": {
        "description": "Debits a fiat account and mints the same amount of tcbUSD into the TCB wallet assigned to you, booked to the sub-account you name. tcbUSD earns nothing on its own; put it into the vault with POST /share-subscriptions to earn the vault rate. An idempotency key is MANDATORY: send it as the Idempotency-Key header or as the idempotencyKey body field. Replaying a key returns the original result without re-executing; reusing one with different parameters is rejected with IDEMPOTENCY_KEY_REUSED.",
        "operationId": "create-token-mint",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. The key is remembered permanently: it is recorded against the movement it created, so a replay years later still resolves to that one movement.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "1000.00",
                "currency": "USD",
                "idempotencyKey": "acme-step-2026-10-12-0001",
                "sourceAccountId": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
                "subAccountId": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerTokenMintDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1000",
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                    "idempotencyKey": "acme-step-2026-10-12-0001",
                    "onchain": {
                      "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                    },
                    "queue": {
                      "claimableAt": "2026-09-02T10:15:30.000Z",
                      "fills": [
                        {
                          "bookedAt": "2026-09-02T10:15:30.000Z",
                          "tokens": "400",
                          "txHash": "0x8c41…"
                        }
                      ],
                      "onchainRequestId": "42",
                      "sharesEscrowed": "398.120000000000000000000000"
                    },
                    "replayed": false,
                    "settledAt": "2026-09-02T10:15:30.000Z",
                    "shares": {
                      "moved": "987.654321000000000000000000"
                    },
                    "status": "SETTLED",
                    "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "token": {
                      "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                      "chain": "ARBITRUM",
                      "symbol": "tcbUSD"
                    },
                    "tokens": {
                      "moved": "1000"
                    },
                    "type": "TOKEN_MINT",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerChainStepResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Minted, or the original result replayed"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-mints",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Invalid request, AMOUNT_PRECISION_EXCEEDED, INSUFFICIENT_BALANCE, SOURCE_ACCOUNT_NOT_USABLE or TOKEN_MINT_CAP_EXCEEDED. Nothing was charged and the key stays usable."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-mints",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-mints",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-mints",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "SOURCE_ACCOUNT_NOT_FOUND, or an unknown sub-account"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-mints",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "IDEMPOTENCY_KEY_REUSED, IDEMPOTENT_REQUEST_IN_PROGRESS, SOURCE_ACCOUNT_AMBIGUOUS, FIAT_ACCOUNT_NOT_PROVISIONED, TOKEN_CONFIG_NOT_AVAILABLE or TOKEN_ISSUANCE_PAUSED (details.idempotencyKeySpent says whether the key survived)."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-mints",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          },
          "500": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTERNAL_ERROR",
                  "error": "Internal Server Error",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-mints",
                  "statusCode": 500,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "TOKEN_MINT_FAILED — nothing was charged, retry with a new key. TOKEN_MINT_FAILED_PENDING_COMPENSATION or TOKEN_MINT_SETTLEMENT_NOT_RECORDED. On the *_FAILED_PENDING_COMPENSATION and *_SETTLEMENT_NOT_RECORDED codes the step is recorded for resolution: do NOT retry with a new key, which would move the money again."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "code": "CHAIN_UNAVAILABLE",
                  "error": "Service Unavailable",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-mints",
                  "statusCode": 503,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "A check could not complete (TOKEN_CONFIG_CHECK_FAILED), or PARTNER_WALLET_PROVISIONING_FAILED (your custody wallet is created on your first mint and that did not complete). Nothing charged and the idempotency key was not claimed: resend with the same key or a new one, parameters may change."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Mint tcbUSD from fiat",
        "tags": [
          "Tokenised deposit chain"
        ]
      }
    },
    "/api/partner/v1/token-mints/{id}": {
      "get": {
        "description": "The mint in its current state, failures included.",
        "operationId": "get-token-mint",
        "parameters": [
          {
            "description": "The id returned when you created the step, or carried by its event.",
            "example": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1000",
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                    "idempotencyKey": "acme-step-2026-10-12-0001",
                    "onchain": {
                      "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                    },
                    "queue": {
                      "claimableAt": "2026-09-02T10:15:30.000Z",
                      "fills": [
                        {
                          "bookedAt": "2026-09-02T10:15:30.000Z",
                          "tokens": "400",
                          "txHash": "0x8c41…"
                        }
                      ],
                      "onchainRequestId": "42",
                      "sharesEscrowed": "398.120000000000000000000000"
                    },
                    "replayed": false,
                    "settledAt": "2026-09-02T10:15:30.000Z",
                    "shares": {
                      "moved": "987.654321000000000000000000"
                    },
                    "status": "SETTLED",
                    "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "token": {
                      "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                      "chain": "ARBITRUM",
                      "symbol": "tcbUSD"
                    },
                    "tokens": {
                      "moved": "1000"
                    },
                    "type": "TOKEN_MINT",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerChainStepResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The mint"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-mints/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-mints/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-mints/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No mint with that id in your scope"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-mints/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one tcbUSD mint",
        "tags": [
          "Tokenised deposit chain"
        ]
      }
    },
    "/api/partner/v1/token-redemptions": {
      "get": {
        "description": "Newest first. Filter by status.",
        "operationId": "list-token-redemptions",
        "parameters": [
          {
            "description": "The nextCursor from the previous page. Opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "PENDING",
                "EXECUTING_ONCHAIN",
                "QUEUED",
                "SETTLED",
                "CANCELLED",
                "FAILED",
                "FAILED_PENDING_COMPENSATION",
                "COMPENSATED"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "items": [
                      {
                        "amount": "1000",
                        "createdAt": "2026-09-02T10:15:30.000Z",
                        "currency": "USD",
                        "custody": {
                          "mode": "TCB_SUBACCOUNT",
                          "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                        },
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                        "idempotencyKey": "acme-step-2026-10-12-0001",
                        "onchain": {
                          "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                        },
                        "queue": {
                          "claimableAt": "2026-09-02T10:15:30.000Z",
                          "fills": [
                            {
                              "bookedAt": "2026-09-02T10:15:30.000Z",
                              "tokens": "400",
                              "txHash": "0x8c41…"
                            }
                          ],
                          "onchainRequestId": "42",
                          "sharesEscrowed": "398.120000000000000000000000"
                        },
                        "replayed": false,
                        "settledAt": "2026-09-02T10:15:30.000Z",
                        "shares": {
                          "moved": "987.654321000000000000000000"
                        },
                        "status": "SETTLED",
                        "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                        "token": {
                          "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                          "chain": "ARBITRUM",
                          "symbol": "tcbUSD"
                        },
                        "tokens": {
                          "moved": "1000"
                        },
                        "type": "TOKEN_MINT",
                        "vault": {
                          "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                          "chain": "ARBITRUM"
                        }
                      }
                    ]
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfPartnerChainStepsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of redemptions"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-redemptions",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "limit, cursor or status malformed (INVALID_AMOUNT)"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-redemptions",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-redemptions",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-redemptions",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List your tcbUSD redemptions",
        "tags": [
          "Tokenised deposit chain"
        ]
      },
      "post": {
        "description": "Burns tcbUSD booked to the sub-account you name and credits the same amount of fiat to a fiat account. Authorised against that sub-account's available tcbUSD only. An idempotency key is MANDATORY: send it as the Idempotency-Key header or as the idempotencyKey body field. Replaying a key returns the original result without re-executing; reusing one with different parameters is rejected with IDEMPOTENCY_KEY_REUSED.",
        "operationId": "create-token-redemption",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. The key is remembered permanently: it is recorded against the movement it created, so a replay years later still resolves to that one movement.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "250.00",
                "currency": "USD",
                "destinationAccountId": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
                "idempotencyKey": "acme-step-2026-10-12-0001",
                "subAccountId": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerTokenRedemptionDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1000",
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                    "idempotencyKey": "acme-step-2026-10-12-0001",
                    "onchain": {
                      "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                    },
                    "queue": {
                      "claimableAt": "2026-09-02T10:15:30.000Z",
                      "fills": [
                        {
                          "bookedAt": "2026-09-02T10:15:30.000Z",
                          "tokens": "400",
                          "txHash": "0x8c41…"
                        }
                      ],
                      "onchainRequestId": "42",
                      "sharesEscrowed": "398.120000000000000000000000"
                    },
                    "replayed": false,
                    "settledAt": "2026-09-02T10:15:30.000Z",
                    "shares": {
                      "moved": "987.654321000000000000000000"
                    },
                    "status": "SETTLED",
                    "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "token": {
                      "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                      "chain": "ARBITRUM",
                      "symbol": "tcbUSD"
                    },
                    "tokens": {
                      "moved": "1000"
                    },
                    "type": "TOKEN_MINT",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerChainStepResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Redeemed, or the original result replayed"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-redemptions",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Invalid request, AMOUNT_PRECISION_EXCEEDED, INSUFFICIENT_SUB_ACCOUNT_TOKENS, DESTINATION_ACCOUNT_NOT_USABLE or TOKEN_REDEMPTION_CAP_EXCEEDED. Nothing moved and the key stays usable."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-redemptions",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-redemptions",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-redemptions",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "DESTINATION_ACCOUNT_NOT_FOUND, or an unknown sub-account"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-redemptions",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "IDEMPOTENCY_KEY_REUSED, IDEMPOTENT_REQUEST_IN_PROGRESS, DESTINATION_ACCOUNT_AMBIGUOUS, FIAT_ACCOUNT_NOT_PROVISIONED, PARTNER_RAIL_FROZEN or STEP_AUTHORIZATION_CONFLICT (retry with the same key)."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-redemptions",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          },
          "500": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTERNAL_ERROR",
                  "error": "Internal Server Error",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-redemptions",
                  "statusCode": 500,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "TOKEN_REDEMPTION_FAILED — nothing was burned, the tcbUSD is available again. TOKEN_REDEMPTION_FAILED_PENDING_COMPENSATION or TOKEN_REDEMPTION_SETTLEMENT_NOT_RECORDED. On the *_FAILED_PENDING_COMPENSATION and *_SETTLEMENT_NOT_RECORDED codes the step is recorded for resolution: do NOT retry with a new key, which would move the money again."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "code": "CHAIN_UNAVAILABLE",
                  "error": "Service Unavailable",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/token-redemptions",
                  "statusCode": 503,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "A check could not complete, or gas could not be funded. Nothing moved."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Redeem tcbUSD to fiat",
        "tags": [
          "Tokenised deposit chain"
        ]
      }
    },
    "/api/partner/v1/token-redemptions/{id}": {
      "get": {
        "description": "The redemption in its current state.",
        "operationId": "get-token-redemption",
        "parameters": [
          {
            "description": "The id returned when you created the step, or carried by its event.",
            "example": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "1000",
                    "createdAt": "2026-09-02T10:15:30.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "fiatAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "id": "7c1e5a90-2b4d-4f86-9e13-5a0d7b2c4e68",
                    "idempotencyKey": "acme-step-2026-10-12-0001",
                    "onchain": {
                      "txHash": "0x4a1f9c07d3b28e615a0c47f8d29b3e6c15087af2d94b6c308e17b5d02fa4c396"
                    },
                    "queue": {
                      "claimableAt": "2026-09-02T10:15:30.000Z",
                      "fills": [
                        {
                          "bookedAt": "2026-09-02T10:15:30.000Z",
                          "tokens": "400",
                          "txHash": "0x8c41…"
                        }
                      ],
                      "onchainRequestId": "42",
                      "sharesEscrowed": "398.120000000000000000000000"
                    },
                    "replayed": false,
                    "settledAt": "2026-09-02T10:15:30.000Z",
                    "shares": {
                      "moved": "987.654321000000000000000000"
                    },
                    "status": "SETTLED",
                    "subAccountId": "9f1c2a54-7b3d-4e08-9a61-2c5f0b7d4e13",
                    "token": {
                      "address": "0x5c9E0a7d4F3b21C68e0A9b7D1f2E34c5A6b7C8d9",
                      "chain": "ARBITRUM",
                      "symbol": "tcbUSD"
                    },
                    "tokens": {
                      "moved": "1000"
                    },
                    "type": "TOKEN_MINT",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    }
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerChainStepResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The redemption"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-redemptions/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-redemptions/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-redemptions/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No redemption with that id in your scope"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/token-redemptions/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one tcbUSD redemption",
        "tags": [
          "Tokenised deposit chain"
        ]
      }
    },
    "/api/partner/v1/transfers": {
      "get": {
        "description": "Cursor pagination, oldest-to-newest window given by from/to. Scoped the way GET /accounts is: transfers touching the ACTING node's own partitions. To read a movement between two of your sub-clients, act as one of them.",
        "operationId": "list-transfers",
        "parameters": [
          {
            "description": "Return only transfers touching this account, on either side.",
            "example": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74",
            "in": "query",
            "name": "accountId",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Include transfers executed at or after this instant (ISO 8601).",
            "example": "2026-09-01T00:00:00.000Z",
            "in": "query",
            "name": "from",
            "required": false,
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "description": "Include transfers executed at or before this instant (ISO 8601).",
            "example": "2026-09-30T23:59:59.000Z",
            "in": "query",
            "name": "to",
            "required": false,
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "description": "The nextCursor from the previous page. Omit it for the first page. Treat it as opaque.",
            "example": "f39b0c74-51ae-4d82-9b06-3c7e2a5d1f80",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Rows per page, 1-100. Defaults to 25.",
            "example": 25,
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "items": [
                      {
                        "amount": "250.00",
                        "currency": "USD",
                        "disclosure": {
                          "items": [
                            "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                            "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                            "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                            "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                            "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                            "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                            "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                          ],
                          "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                          "version": "2026-10-27"
                        },
                        "executedAt": "2026-09-02T10:15:30.000Z",
                        "from": {
                          "accountId": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
                          "ownerId": "3a7e5c91-0d24-4b6f-8e13-5c9a2f7b1d04",
                          "ownerType": "CLIENT"
                        },
                        "ownership": "SAME_OWNER",
                        "reference": "Invoice 2026-0412",
                        "replayed": false,
                        "status": "COMPLETED",
                        "to": {
                          "accountId": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
                          "ownerId": "3a7e5c91-0d24-4b6f-8e13-5c9a2f7b1d04",
                          "ownerType": "CLIENT"
                        },
                        "transferId": "0c93a6e1-58fb-4d27-9a04-7e1b3c5d8f26"
                      }
                    ],
                    "nextCursor": "0c93a6e1-58fb-4d27-9a04-7e1b3c5d8f26"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfTransfersResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of transfers"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/transfers",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "limit outside 1-100, or an unparseable from/to."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/transfers",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/transfers",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/transfers",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List transfers",
        "tags": [
          "Transfers"
        ]
      },
      "post": {
        "description": "Both accounts must resolve under the caller's root client (own accounts or accounts of the caller's sub-clients). Same currency, instant, terminal on the response — no screening, no TCB limits, no approval. x-on-behalf-of narrows what may be named as fromAccountId to that sub-client's accounts; toAccountId may still be any account in the same tree. Idempotency key is MANDATORY.",
        "operationId": "create-transfer",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. The key is remembered permanently: it is recorded against the movement it created, so a replay years later still resolves to that one movement.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "250.00",
                "currency": "USD",
                "fromAccountId": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
                "idempotencyKey": "acme-transfer-2026-09-02-0001",
                "metadata": {
                  "ledgerRef": "JRNL-2026-0412"
                },
                "reference": "Invoice 2026-0412",
                "toAccountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerTransferDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "250.00",
                    "currency": "USD",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "executedAt": "2026-09-02T10:15:30.000Z",
                    "from": {
                      "accountId": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
                      "ownerId": "3a7e5c91-0d24-4b6f-8e13-5c9a2f7b1d04",
                      "ownerType": "CLIENT"
                    },
                    "ownership": "SAME_OWNER",
                    "reference": "Invoice 2026-0412",
                    "replayed": false,
                    "status": "COMPLETED",
                    "to": {
                      "accountId": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
                      "ownerId": "3a7e5c91-0d24-4b6f-8e13-5c9a2f7b1d04",
                      "ownerType": "CLIENT"
                    },
                    "transferId": "0c93a6e1-58fb-4d27-9a04-7e1b3c5d8f26"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerTransferResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Transfer completed, or the original result replayed"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/transfers",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Missing/invalid idempotency key, INVALID_AMOUNT, TRANSFER_CURRENCY_MISMATCH, TRANSFER_SAME_ACCOUNT, TRANSFER_NON_LEDGER_ACCOUNT (one side is a connected external wallet, whose balance lives on-chain and cannot move on the ledger) or TRANSFER_ASSET_NOT_SUPPORTED (one side is not a fiat account; transfers move fiat only)."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/transfers",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/transfers",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Key lacks transfer:execute. Using x-on-behalf-of may also return ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY (this key is restricted to a subset of your sub-clients and that one is not in it)."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/transfers",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "ACCOUNT_NOT_FOUND — acting on behalf of a sub-client, fromAccountId is not one of its accounts. Using x-on-behalf-of may also return ON_BEHALF_OF_NOT_FOUND."
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/transfers",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "INSUFFICIENT_BALANCE, ACCOUNT_CLOSED (a named account is closed), ACCOUNT_NOT_ACTIVE (a named account is neither active nor closed — today that means frozen; details.status carries the state either way), TRANSFER_CAP_EXCEEDED (the root-set ceiling on the debited sub-client), or SUB_CLIENT_CAPABILITY_UNAVAILABLE (the debited or credited owner's relevant capability — sendInternal to debit, receive to credit — is false; fix that sub-client's verification, distinct from 403 INSUFFICIENT_SCOPE which means fix your key). Using x-on-behalf-of may also return ON_BEHALF_OF_SUB_CLIENT_CLOSED."
          },
          "422": {
            "content": {
              "application/json": {
                "example": {
                  "code": "TRANSFER_NOT_WITHIN_TREE",
                  "error": "Unprocessable Entity",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/transfers",
                  "statusCode": 422,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "TRANSFER_NOT_WITHIN_TREE — one or both accounts are outside your tree. Transfers between different clients are not supported on this API."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/transfers",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Transfer within one tree",
        "tags": [
          "Transfers"
        ]
      }
    },
    "/api/partner/v1/transfers/{id}": {
      "get": {
        "description": "The transfer in its current (terminal) state.",
        "operationId": "get-transfer",
        "parameters": [
          {
            "description": "The transfer id.",
            "example": "0c93a6e1-58fb-4d27-9a04-7e1b3c5d8f26",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.",
            "in": "header",
            "name": "x-on-behalf-of",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "250.00",
                    "currency": "USD",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "executedAt": "2026-09-02T10:15:30.000Z",
                    "from": {
                      "accountId": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
                      "ownerId": "3a7e5c91-0d24-4b6f-8e13-5c9a2f7b1d04",
                      "ownerType": "CLIENT"
                    },
                    "ownership": "SAME_OWNER",
                    "reference": "Invoice 2026-0412",
                    "replayed": false,
                    "status": "COMPLETED",
                    "to": {
                      "accountId": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
                      "ownerId": "3a7e5c91-0d24-4b6f-8e13-5c9a2f7b1d04",
                      "ownerType": "CLIENT"
                    },
                    "transferId": "0c93a6e1-58fb-4d27-9a04-7e1b3c5d8f26"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerTransferResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The transfer"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/transfers/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/transfers/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/transfers/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No transfer with that id in your scope. Using x-on-behalf-of may also return ON_BEHALF_OF_NOT_FOUND (the named sub-client does not exist in your tree)."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/transfers/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one transfer by id",
        "tags": [
          "Transfers"
        ]
      }
    },
    "/api/partner/v1/webhooks": {
      "get": {
        "description": "Registry rows, oldest first. Secrets are shown as previews only.",
        "operationId": "list-webhooks",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "createdAt": "2026-08-14T08:42:11.000Z",
                      "disclosure": {
                        "items": [
                          "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                          "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                          "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                          "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                          "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                          "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                          "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                        ],
                        "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                        "version": "2026-10-27"
                      },
                      "events": [
                        "deposit.settled",
                        "withdrawal.settled"
                      ],
                      "previousSecretExpiresAt": "2026-09-03T10:15:30.000Z",
                      "secret": "whsec_k3vJ9aQ2mR7xL0pT4wZ8nB1yC6dF5gH2jK9sV3eA7u",
                      "secretPreview": "whsec_k3vJ9aQ2…",
                      "status": "ACTIVE",
                      "url": "https://partner.example.com/tcb/webhooks",
                      "webhookId": "4e8b1d70-a35c-4692-b0f1-9d2c6a4e73b8"
                    }
                  ],
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "items": {
                        "$ref": "#/components/schemas/PartnerWebhookResponse"
                      },
                      "type": "array"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Your endpoints"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/webhooks",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/webhooks",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/webhooks",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List your webhook endpoints",
        "tags": [
          "Webhooks"
        ]
      },
      "post": {
        "description": "Events from your chosen catalogue subset are POSTed to the URL, signed. The response carries the signing secret IN FULL, exactly once — store it; reads only ever show a preview. Payloads are thin (id + type + resource pointer): fetch the object through the read endpoints.",
        "operationId": "create-webhook",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "events": [
                  "deposit.settled",
                  "withdrawal.settled"
                ],
                "url": "https://partner.example.com/tcb/webhooks"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerWebhookDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "createdAt": "2026-08-14T08:42:11.000Z",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "events": [
                      "deposit.settled",
                      "withdrawal.settled"
                    ],
                    "previousSecretExpiresAt": "2026-09-03T10:15:30.000Z",
                    "secret": "whsec_k3vJ9aQ2mR7xL0pT4wZ8nB1yC6dF5gH2jK9sV3eA7u",
                    "secretPreview": "whsec_k3vJ9aQ2…",
                    "status": "ACTIVE",
                    "url": "https://partner.example.com/tcb/webhooks",
                    "webhookId": "4e8b1d70-a35c-4692-b0f1-9d2c6a4e73b8"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerWebhookResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Endpoint registered; secret shown once"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/webhooks",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Invalid URL or event list"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/webhooks",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/webhooks",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/webhooks",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Register a webhook endpoint",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/api/partner/v1/webhooks/{id}": {
      "delete": {
        "description": "Disables delivery. The subscription row and its delivery history are retained — they are the record of what was sent where — and undelivered events stop being attempted while the endpoint is disabled.",
        "operationId": "disable-webhook",
        "parameters": [
          {
            "description": "The webhookId returned when the endpoint was registered.",
            "example": "4e8b1d70-a35c-4692-b0f1-9d2c6a4e73b8",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "createdAt": "2026-08-14T08:42:11.000Z",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "events": [
                      "deposit.settled",
                      "withdrawal.settled"
                    ],
                    "previousSecretExpiresAt": "2026-09-03T10:15:30.000Z",
                    "secret": "whsec_k3vJ9aQ2mR7xL0pT4wZ8nB1yC6dF5gH2jK9sV3eA7u",
                    "secretPreview": "whsec_k3vJ9aQ2…",
                    "status": "ACTIVE",
                    "url": "https://partner.example.com/tcb/webhooks",
                    "webhookId": "4e8b1d70-a35c-4692-b0f1-9d2c6a4e73b8"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerWebhookResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Endpoint disabled"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/webhooks/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/webhooks/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/webhooks/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No such subscription in your scope"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "DELETE",
                  "path": "/api/partner/v1/webhooks/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Disable a webhook endpoint",
        "tags": [
          "Webhooks"
        ]
      },
      "get": {
        "description": "The subscription as registered: its URL, the events it receives, whether it is still active, and a preview of the secret currently signing its deliveries. The full secret is never returned by a read — only by the call that minted it.",
        "operationId": "get-webhook",
        "parameters": [
          {
            "description": "The webhookId returned when the endpoint was registered.",
            "example": "4e8b1d70-a35c-4692-b0f1-9d2c6a4e73b8",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "createdAt": "2026-08-14T08:42:11.000Z",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "events": [
                      "deposit.settled",
                      "withdrawal.settled"
                    ],
                    "previousSecretExpiresAt": "2026-09-03T10:15:30.000Z",
                    "secret": "whsec_k3vJ9aQ2mR7xL0pT4wZ8nB1yC6dF5gH2jK9sV3eA7u",
                    "secretPreview": "whsec_k3vJ9aQ2…",
                    "status": "ACTIVE",
                    "url": "https://partner.example.com/tcb/webhooks",
                    "webhookId": "4e8b1d70-a35c-4692-b0f1-9d2c6a4e73b8"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerWebhookResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The endpoint"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/webhooks/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/webhooks/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/webhooks/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No such subscription in your scope"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/webhooks/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one webhook endpoint by id",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/api/partner/v1/webhooks/{id}/rotate-secret": {
      "post": {
        "description": "Mints a new signing secret and returns it IN FULL, exactly once. Until previousSecretExpiresAt, deliveries are signed with BOTH the new and the old secret (two v1= entries in the signature header), so either verifies while you cut over. Rotating again inside the window replaces the old secret immediately.",
        "operationId": "rotate-webhook-secret",
        "parameters": [
          {
            "description": "The webhookId returned when the endpoint was registered.",
            "example": "4e8b1d70-a35c-4692-b0f1-9d2c6a4e73b8",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "createdAt": "2026-08-14T08:42:11.000Z",
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "events": [
                      "deposit.settled",
                      "withdrawal.settled"
                    ],
                    "previousSecretExpiresAt": "2026-09-03T10:15:30.000Z",
                    "secret": "whsec_k3vJ9aQ2mR7xL0pT4wZ8nB1yC6dF5gH2jK9sV3eA7u",
                    "secretPreview": "whsec_k3vJ9aQ2…",
                    "status": "ACTIVE",
                    "url": "https://partner.example.com/tcb/webhooks",
                    "webhookId": "4e8b1d70-a35c-4692-b0f1-9d2c6a4e73b8"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerWebhookResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "New secret shown once; overlap window stated"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/webhooks/{id}/rotate-secret",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/webhooks/{id}/rotate-secret",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/webhooks/{id}/rotate-secret",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No such subscription in your scope"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/webhooks/{id}/rotate-secret",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Rotate the signing secret (dual-secret overlap)",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/api/partner/v1/withdrawals": {
      "get": {
        "description": "Your vault withdrawals, newest first, each with its status on the one savings status vocabulary (QUEUED, PROCESSING, CREDIT_PENDING, COMPLETED, FAILED, REFUNDED, CANCELLED). Filter by status. Fetch one in full with GET /withdrawals/{id}.",
        "operationId": "list-withdrawals",
        "parameters": [
          {
            "description": "The nextCursor from the previous page. Omit it for the first page. Treat it as opaque.",
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Rows per page, 1-100. Defaults to 25.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100,
              "type": "integer"
            }
          },
          {
            "description": "Only withdrawals in this status.",
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "QUEUED",
                "PROCESSING",
                "CREDIT_PENDING",
                "COMPLETED",
                "FAILED",
                "REFUNDED",
                "CANCELLED"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "items": [
                      {
                        "createdAt": "2026-10-06T10:02:05.000Z",
                        "creditedAmount": "249.99",
                        "currency": "USD",
                        "estimatedAvailableAt": "2026-10-06T10:02:13.000Z",
                        "requestedAmount": "250",
                        "settledAt": "2026-10-06T10:02:13.000Z",
                        "shares": "249.380000000000000000000000",
                        "status": "COMPLETED",
                        "subAccountId": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395",
                        "withdrawalId": "7a1d0c55-91e2-4f36-8b0a-2e64c9d8f173"
                      }
                    ]
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PageOfPartnerVaultWithdrawalsResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of withdrawals"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/withdrawals",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "limit or status malformed (INVALID_AMOUNT)"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/withdrawals",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/withdrawals",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/withdrawals",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "code": "CHAIN_UNAVAILABLE",
                  "error": "Service Unavailable",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/withdrawals",
                  "statusCode": 503,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Chain read unavailable (CHAIN_UNAVAILABLE). Retry."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "List your vault withdrawals",
        "tags": [
          "Withdrawals"
        ]
      },
      "post": {
        "description": "Redeems vault shares held in your vault sub-account back to fiat. The amount is asset-denominated — ask for a sum of fiat, exactly as on a deposit. An idempotency key is MANDATORY: send it as the Idempotency-Key header or as the idempotencyKey body field. Replaying a key returns the original result without re-executing; reusing one with different parameters is rejected with IDEMPOTENCY_KEY_REUSED. Settlement rounds DOWN to the currency precision the banking leg accepts: the response reports settledAmount and precisionResidue separately, and the residue stays in your vault sub-account wallet — it is not a fee. Every response carries the pilot disclosure: the environment is a testnet and the yield is simulated, not earned.",
        "operationId": "create-withdrawal",
        "parameters": [
          {
            "description": "Your own key for this request, 1-100 characters. Required, here or as the idempotencyKey body field; sending both is allowed only if they match. Replaying a key returns the first result without executing anything a second time, and sets replayed to true where the response carries that field. Sending the same key with different parameters is refused with 409 IDEMPOTENCY_KEY_REUSED — use a new key for a different request. While the first call is still running, a second call with the same key answers 409 IDEMPOTENT_REQUEST_IN_PROGRESS. The key is remembered permanently: it is recorded against the movement it created, so a replay years later still resolves to that one movement.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "amount": "250.00",
                "currency": "USD",
                "destinationAccountId": "1b9d4f07-6c23-4a8e-b510-9f2c7d3e5a68",
                "idempotencyKey": "acme-withdrawal-2026-08-30-0001",
                "subAccountId": "5d3b8e10-2f47-4c9a-b6e8-0a71d4c2f395"
              },
              "schema": {
                "$ref": "#/components/schemas/CreatePartnerWithdrawalDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "250",
                    "createdAt": "2026-09-02T10:15:28.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "idempotencyKey": "acme-withdrawal-2026-08-30-0001",
                    "onchain": {
                      "burnTxHash": "0xb31d0f6a29c85e470132d9af6058c7be24913f5d7ea0c86241b09fd35c7a1e64",
                      "withdrawTxHash": "0x6c58e2af017d94b3182fa0e7c53d69b148027ea5f31c8d60947b25e0fa1c3d78"
                    },
                    "precisionResidue": "0.004821",
                    "replayed": false,
                    "settledAmount": "250",
                    "settledAt": "2026-09-02T10:15:41.000Z",
                    "shares": {
                      "balance": "774.518330000000000000000000"
                    },
                    "status": "SETTLED",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    },
                    "withdrawalId": "8c1e7b25-4a93-4f06-b83d-2e5c9017a4f6"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerWithdrawalResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Withdrawal settled, or the original result replayed"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REQUIRED",
                  "error": "Bad Request",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/withdrawals",
                  "statusCode": 400,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Missing/invalid idempotency key, invalid or over-precise amount, the sub-account does not hold enough (INSUFFICIENT_VAULT_POSITION), DESTINATION_ACCOUNT_NOT_USABLE — the named account is not a fiat account in that currency (the account your crypto deposit address credits cannot receive a withdrawal), or WITHDRAWAL_CAP_EXCEEDED — the withdrawal would cross a money cap set for your account (details name the ceiling and the figure). Nothing withdrawn and the key stays usable."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/withdrawals",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/withdrawals",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Destination account unusable, or key lacks vault:withdraw"
          },
          "409": {
            "content": {
              "application/json": {
                "example": {
                  "code": "IDEMPOTENCY_KEY_REUSED",
                  "error": "Conflict",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/withdrawals",
                  "statusCode": 409,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Key reused with different parameters, still in flight, vault liquidity insufficient (INSUFFICIENT_VAULT_LIQUIDITY, with the covered amount), or custody/provisioning records inconsistent"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/withdrawals",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          },
          "500": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTERNAL_ERROR",
                  "error": "Internal Server Error",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/withdrawals",
                  "statusCode": 500,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "WITHDRAWAL_FAILED_PENDING_COMPENSATION — the withdrawal did not complete and it cannot be confirmed that nothing moved. Or WITHDRAWAL_SETTLEMENT_NOT_RECORDED — it DID complete, your fiat was credited, and only the record of it failed. Either way the intent is recorded for resolution — the compensation sweeper completes it automatically where the outcome can be proven, and escalates it to an operator otherwise. Do NOT retry with a new key, which would withdraw again. Polling this key will not change the answer until it has been resolved: a compensable intent keeps returning this same failure, and a settlement-not-recorded one keeps returning 409 IDEMPOTENT_REQUEST_IN_PROGRESS even though the withdrawal completed."
          },
          "503": {
            "content": {
              "application/json": {
                "example": {
                  "code": "CHAIN_UNAVAILABLE",
                  "error": "Service Unavailable",
                  "message": "See the description of this response for what produces it.",
                  "method": "POST",
                  "path": "/api/partner/v1/withdrawals",
                  "statusCode": 503,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Chain or gas pre-flight unavailable — nothing withdrawn"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Withdraw fiat from a curated vault",
        "tags": [
          "Withdrawals"
        ]
      }
    },
    "/api/partner/v1/withdrawals/{id}": {
      "get": {
        "description": "The withdrawal in its CURRENT state, whatever that is — including a terminal failure, reported here as the object rather than as an error. This is the fetch half of the thin webhook payloads (a *.settled / *.failed event carries only a resource pointer) and the poll surface the money errors point at.",
        "operationId": "get-withdrawal",
        "parameters": [
          {
            "description": "The withdrawalId returned when you created it, or carried by the event's resource pointer.",
            "example": "8c1e7b25-4a93-4f06-b83d-2e5c9017a4f6",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "amount": "250",
                    "createdAt": "2026-09-02T10:15:28.000Z",
                    "currency": "USD",
                    "custody": {
                      "mode": "TCB_SUBACCOUNT",
                      "walletAddress": "0x3B9aC4f27D18E056b1C4a9F30d2E85c7A6b1F094"
                    },
                    "disclosure": {
                      "items": [
                        "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.",
                        "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.",
                        "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.",
                        "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.",
                        "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.",
                        "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.",
                        "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment."
                      ],
                      "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.",
                      "version": "2026-10-27"
                    },
                    "idempotencyKey": "acme-withdrawal-2026-08-30-0001",
                    "onchain": {
                      "burnTxHash": "0xb31d0f6a29c85e470132d9af6058c7be24913f5d7ea0c86241b09fd35c7a1e64",
                      "withdrawTxHash": "0x6c58e2af017d94b3182fa0e7c53d69b148027ea5f31c8d60947b25e0fa1c3d78"
                    },
                    "precisionResidue": "0.004821",
                    "replayed": false,
                    "settledAmount": "250",
                    "settledAt": "2026-09-02T10:15:41.000Z",
                    "shares": {
                      "balance": "774.518330000000000000000000"
                    },
                    "status": "SETTLED",
                    "vault": {
                      "address": "0x7a2fD3c8e91B4A5d06E7c1F2b38A9d4C5e6f0B12",
                      "chain": "ARBITRUM"
                    },
                    "withdrawalId": "8c1e7b25-4a93-4f06-b83d-2e5c9017a4f6"
                  },
                  "success": true,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PartnerWithdrawalResponse"
                    },
                    "success": {
                      "enum": [
                        true
                      ],
                      "type": "boolean"
                    },
                    "timestamp": {
                      "format": "date-time",
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The withdrawal"
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "code": "UNAUTHORIZED",
                  "error": "Unauthorized",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/withdrawals/{id}",
                  "statusCode": 401,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your API key is missing, malformed, unknown, revoked, expired, or belongs to a principal that is no longer active. Send it as `Authorization: Bearer <key>`."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INSUFFICIENT_SCOPE",
                  "error": "Forbidden",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/withdrawals/{id}",
                  "statusCode": 403,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Your key does not carry the scope this route requires (`INSUFFICIENT_SCOPE`). Acting on behalf of a sub-client, a key restricted to a subset of your sub-clients also answers here with `ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY`."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "code": "INTENT_NOT_FOUND",
                  "error": "Not Found",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/withdrawals/{id}",
                  "statusCode": 404,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "No withdrawal with that id in your scope"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "code": "MACHINE_RATE_LIMITED",
                  "error": "Too Many Requests",
                  "message": "See the description of this response for what produces it.",
                  "method": "GET",
                  "path": "/api/partner/v1/withdrawals/{id}",
                  "statusCode": 429,
                  "timestamp": "2026-09-02T10:15:30.000Z"
                },
                "schema": {
                  "$ref": "#/components/schemas/PartnerErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded (`MACHINE_RATE_LIMITED`). Requests are counted per principal per minute — 120 unless TCB has agreed another figure with you. Retry in the next minute."
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Fetch one withdrawal by id",
        "tags": [
          "Withdrawals"
        ]
      }
    }
  },
  "servers": [
    {
      "description": "Pilot (testnet, mocked rails)",
      "url": "https://api.threecommabank.com"
    }
  ],
  "tags": [
    {
      "description": "Confirm which principal your API key authenticates as, and which sub-client it would act for. Call this first when wiring up a new key.",
      "name": "Identity"
    },
    {
      "description": "Your end customers — the people and businesses you onboard and hold money for. A sub-client has accounts and IBANs in its own legal name, an identity record you supply, and the attestations that back it.",
      "name": "Sub-clients"
    },
    {
      "description": "Fiat accounts under you or under one of your sub-clients. An account holds one currency account per currency. Every currency account receives on the account's one IBAN, and carries local details for its currency where the currency has them. To hold the same currency separately, open another account.",
      "name": "Accounts"
    },
    {
      "description": "Same-currency movements between two accounts in your tree. Instant, terminal on the response, and settled without leaving TCB.",
      "name": "Transfers"
    },
    {
      "description": "Offset what you and one other member owe each other and settle only the net. Every obligation is reserved in full from the moment it is submitted, so netting never extends credit; the member that owes the net cuts, and one ordinary settlement posts for it.",
      "name": "Settlement netting"
    },
    {
      "description": "Who can be paid on the network and how they are addressed. Choose the handle you are paid by, resolve a handle or a TCB IBAN to a verified legal name before you pay it, and search the members who chose to be listed.",
      "name": "Settlement network"
    },
    {
      "description": "Same-currency movements to a DIFFERENT client of the bank. Instant, final on the response, and free. Both parties read the same settlement.",
      "name": "Settlements"
    },
    {
      "description": "Fiat in: convert money you hold into a position in the curated vault for that currency.",
      "name": "Deposits"
    },
    {
      "description": "Crypto in: a deposit address TCB issues to you, and the record of every confirmed on-chain arrival to it. A deposit is initiated on-chain, not by an API call.",
      "name": "Crypto deposits"
    },
    {
      "description": "Fiat out: redeem part of your vault position back into one of your fiat accounts.",
      "name": "Withdrawals"
    },
    {
      "description": "Sell one currency you hold for another, between two of your own accounts, and read the rate you got before you do anything else with the proceeds.",
      "name": "Conversions"
    },
    {
      "description": "The vault deposit and withdrawal one step at a time: mint tcbUSD from fiat, put it into the vault for shares, take it back out (at once, or through the vault queue), and redeem it to fiat. Between steps the tcbUSD is held in the TCB wallet assigned to you and booked to a sub-account.",
      "name": "Tokenised deposit chain"
    },
    {
      "description": "Named partitions of your own vault position. They let you attribute deposits and withdrawals on your books; they confer no separate wallet and no separate custody.",
      "name": "Vault sub-accounts"
    },
    {
      "description": "What you hold in a vault, broken down by sub-account: settled, reserved, available, and the accrual on each — and the tcbUSD you hold between steps, by sub-account.",
      "name": "Positions"
    },
    {
      "description": "The third parties a payout can name — bank accounts and wallets you register in advance. The destination must clear screening, TCB approval and a holding period before a payout can name it.",
      "name": "Destinations"
    },
    {
      "description": "Fiat out to a third party: pay a registered destination from one of your fiat accounts. Only a destination that has completed its lifecycle can be named; the request carries no raw bank details.",
      "name": "Payouts"
    },
    {
      "description": "Register the endpoints TCB signs and POSTs events to, and rotate their signing secrets.",
      "name": "Webhooks"
    },
    {
      "description": "Monthly, immutable statements of your sub-account ledger — a fold of every settled entry in a closed calendar month, as JSON or CSV.",
      "name": "Statements"
    }
  ]
}
