diff --git a/.api-sync/contract-check-allowlist.json b/.api-sync/contract-check-allowlist.json index d2ff7b9..d07d27b 100644 --- a/.api-sync/contract-check-allowlist.json +++ b/.api-sync/contract-check-allowlist.json @@ -1,88 +1,22 @@ [ + { + "schema": "RequestOptions", + "field": "idempotencyKey", + "reason": "Client-side per-call option, not a body field: the SDK sends it as the spec's optional Idempotency-Key header parameter on mutations.", + "owner": "thayto@blindpay.com" + }, { "schema": "CreatePayoutInput", "field": "reference", "reason": "Stale surface: v2 PR #1925 prunes unreachable schemas from the public spec and this field no longer appears anywhere in it, but the SDK still exposes it on CreatePayoutInput. Remove in next major.", "owner": "eric@blindpay.com" }, - { - "schema": "GetBankAccountResponse", - "field": "account_holder_name", - "reason": "Pre-existing SDK field with no matching property in the spec (BankAccountOut has swift_account_holder_name, not account_holder_name). Unrelated to the wave-2 receiver->customer rename; needs its own follow-up.", - "owner": "eric@blindpay.com" - }, - { - "schema": "GetBankAccountResponse", - "field": "swift_code", - "reason": "Pre-existing SDK field with no matching property in the spec (BankAccountOut has swift_code_bic, not swift_code). Unrelated to wave 2; needs its own follow-up.", - "owner": "eric@blindpay.com" - }, - { - "schema": "GetBankAccountResponse", - "field": "is_primary", - "reason": "Pre-existing SDK field with no matching property anywhere on BankAccountOut in the spec. Unrelated to wave 2; needs its own follow-up.", - "owner": "eric@blindpay.com" - }, - { - "schema": "IndividualWithEnhancedKYC", - "field": "individual_holding_doc_front_file", - "reason": "Pre-existing SDK field absent from the enhanced-KYC individual schema in the spec. Unrelated to wave 2; needs its own follow-up.", - "owner": "eric@blindpay.com" - }, { "schema": "UpdateInstanceMemberRoleInput", "field": "memberId", "reason": "Path-only identifier used to build /members/{id}; never serialized as a JSON body key. Pre-existing camelCase naming (inconsistent with this SDK's snake_case convention) unrelated to wave 2.", "owner": "eric@blindpay.com" }, - { - "schema": "ListPartnerFeesResponse", - "field": "evm_wallet_address", - "reason": "Pre-existing SDK field with no matching property on the partner-fees create/list/get schemas in the spec. Unrelated to wave 2; needs its own follow-up.", - "owner": "eric@blindpay.com" - }, - { - "schema": "ListPartnerFeesResponse", - "field": "stellar_wallet_address", - "reason": "Pre-existing SDK field with no matching property on the partner-fees create/list/get schemas in the spec. Unrelated to wave 2; needs its own follow-up.", - "owner": "eric@blindpay.com" - }, - { - "schema": "CreatePartnerFeeInput", - "field": "evm_wallet_address", - "reason": "Pre-existing SDK field with no matching property on the partner-fees create/list/get schemas in the spec. Unrelated to wave 2; needs its own follow-up.", - "owner": "eric@blindpay.com" - }, - { - "schema": "CreatePartnerFeeInput", - "field": "stellar_wallet_address", - "reason": "Pre-existing SDK field with no matching property on the partner-fees create/list/get schemas in the spec. Unrelated to wave 2; needs its own follow-up.", - "owner": "eric@blindpay.com" - }, - { - "schema": "CreatePartnerFeeResponse", - "field": "evm_wallet_address", - "reason": "Pre-existing SDK field with no matching property on the partner-fees create/list/get schemas in the spec. Unrelated to wave 2; needs its own follow-up.", - "owner": "eric@blindpay.com" - }, - { - "schema": "CreatePartnerFeeResponse", - "field": "stellar_wallet_address", - "reason": "Pre-existing SDK field with no matching property on the partner-fees create/list/get schemas in the spec. Unrelated to wave 2; needs its own follow-up.", - "owner": "eric@blindpay.com" - }, - { - "schema": "GetPartnerFeeResponse", - "field": "evm_wallet_address", - "reason": "Pre-existing SDK field with no matching property on the partner-fees create/list/get schemas in the spec. Unrelated to wave 2; needs its own follow-up.", - "owner": "eric@blindpay.com" - }, - { - "schema": "GetPartnerFeeResponse", - "field": "stellar_wallet_address", - "reason": "Pre-existing SDK field with no matching property on the partner-fees create/list/get schemas in the spec. Unrelated to wave 2; needs its own follow-up.", - "owner": "eric@blindpay.com" - }, { "schema": "Payin", "field": "tracking_partner_fee", @@ -137,30 +71,6 @@ "reason": "Pre-existing tracking step modeled by the SDK that no longer exists on any Transfer schema in the spec. Unrelated to wave 2; needs its own follow-up.", "owner": "eric@blindpay.com" }, - { - "schema": "GetBankAccountResponse", - "field": "iban", - "reason": "Absent from the public spec snapshot; only appeared alongside internal-only surface in the unfiltered spec. Pre-existing SDK field, unrelated to the customers rename; needs its own investigation.", - "owner": "eric@blindpay.com" - }, - { - "schema": "IndividualWithStandardKYC", - "field": "aiprise_validation_key", - "reason": "Absent from the public spec snapshot; only appeared alongside internal-only surface in the unfiltered spec. Pre-existing SDK field, unrelated to the customers rename; needs its own investigation.", - "owner": "eric@blindpay.com" - }, - { - "schema": "IndividualWithEnhancedKYC", - "field": "aiprise_validation_key", - "reason": "Absent from the public spec snapshot; only appeared alongside internal-only surface in the unfiltered spec. Pre-existing SDK field, unrelated to the customers rename; needs its own investigation.", - "owner": "eric@blindpay.com" - }, - { - "schema": "BusinessWithStandardKYB", - "field": "aiprise_validation_key", - "reason": "Absent from the public spec snapshot; only appeared alongside internal-only surface in the unfiltered spec. Pre-existing SDK field, unrelated to the customers rename; needs its own investigation.", - "owner": "eric@blindpay.com" - }, { "schema": "SubmitPayoutDocumentsInput", "field": "payout_id", diff --git a/.api-sync/spec-map.json b/.api-sync/spec-map.json index 7625ae8..f1da701 100644 --- a/.api-sync/spec-map.json +++ b/.api-sync/spec-map.json @@ -18,6 +18,19 @@ ], "notes": null }, + { + "spec": { + "schema": "BankAccountOut", + "property": "status" + }, + "sdk": [ + { + "file": "src/resources/bank-accounts/index.ts", + "symbol": "BankAccountStatus" + } + ], + "notes": null + }, { "spec": { "schema": "BankAccountWebhookOut", @@ -113,6 +126,19 @@ ], "notes": null }, + { + "spec": { + "schema": "CreatePayableIn", + "property": "currency" + }, + "sdk": [ + { + "file": "src/resources/payables/index.ts", + "symbol": "PayableCurrency" + } + ], + "notes": "Same value set as PayableOut.currency." + }, { "spec": { "schema": "CreatePayinQuoteIn", @@ -135,13 +161,22 @@ { "file": "types/index.d.ts", "symbol": "PaymentMethod" - }, + } + ], + "notes": "Methods a payin quote accepts. PayinPaymentMethod (PayinOut.payment_method) is the wider set a created payin can report." + }, + { + "spec": { + "schema": "PayinOut", + "property": "payment_method" + }, + "sdk": [ { "file": "types/index.d.ts", "symbol": "PayinPaymentMethod" } ], - "notes": "Declared twice with identical values (PaymentMethod and PayinPaymentMethod, both in types/index.d.ts); both used across payins/transfers/bank-accounts. Verified: spec has exactly these 9 values (ach, wire, pix, spei, transfers, pse, international_swift, rtp, ted), matching both SDK unions exactly." + "notes": null }, { "spec": { @@ -160,6 +195,19 @@ ], "notes": "Declared twice, same reasoning as BankingPartner." }, + { + "spec": { + "schema": "CustomerCnaeCondition", + "property": "status" + }, + "sdk": [ + { + "file": "src/resources/customers/index.ts", + "symbol": "CnaeConditionStatus" + } + ], + "notes": null + }, { "spec": { "schema": "CustomerLimitIncreaseIn", @@ -199,6 +247,59 @@ ], "notes": "Also appears on VirtualAccountOut.kyc_status and on the ignored *WebhookOut customer/limit-increase schemas." }, + { + "spec": { + "schema": "CustomerVirtualAccountPreapproval", + "property": "banking_partners", + "itemsEnum": true + }, + "sdk": [ + { + "file": "src/resources/customers/index.ts", + "symbol": "VirtualAccountPreapprovalBankingPartner" + } + ], + "notes": "Array-of-enum (values on properties.banking_partners.items.enum). A strict subset of BankingPartner, so declared as its own union instead of reusing the shared one." + }, + { + "spec": { + "schema": "CustomerVirtualAccountPreapproval", + "property": "status" + }, + "sdk": [ + { + "file": "src/resources/customers/index.ts", + "symbol": "VirtualAccountPreapprovalStatus" + } + ], + "notes": null + }, + { + "spec": { + "schema": "InstanceRfi", + "property": "status" + }, + "sdk": [ + { + "file": "src/resources/rfi/index.ts", + "symbol": "RfiStatus" + } + ], + "notes": "Shared with Rfi.status (same member set)." + }, + { + "spec": { + "schema": "LimitIncreaseSupportingDocument", + "property": "type" + }, + "sdk": [ + { + "file": "src/resources/customers/index.ts", + "symbol": "LimitIncreaseRequestSupportingDocumentType" + } + ], + "notes": "Same 15-value set as CustomerLimitIncreaseIn.supporting_document_type." + }, { "spec": { "schema": "LimitIncreaseUpdateWebhookOut", @@ -212,6 +313,58 @@ ], "notes": null }, + { + "spec": { + "schema": "PayableBankAccount", + "property": "type" + }, + "sdk": [ + { + "file": "src/resources/payables/index.ts", + "symbol": "PayableBankAccountType" + } + ], + "notes": null + }, + { + "spec": { + "schema": "PayableOut", + "property": "currency" + }, + "sdk": [ + { + "file": "src/resources/payables/index.ts", + "symbol": "PayableCurrency" + } + ], + "notes": "Fiat-only subset of the shared Currency union (no USDC/USDT/USDB), so declared locally rather than reusing Currency." + }, + { + "spec": { + "schema": "PayableOut", + "property": "last_attempt_status" + }, + "sdk": [ + { + "file": "src/resources/payables/index.ts", + "symbol": "PayableLastAttemptStatus" + } + ], + "notes": null + }, + { + "spec": { + "schema": "PayableOut", + "property": "status" + }, + "sdk": [ + { + "file": "src/resources/payables/index.ts", + "symbol": "PayableStatus" + } + ], + "notes": "Also the value set of the list endpoint's `status` query parameter (ListPayablesInput.status)." + }, { "spec": { "schema": "PayinOut", @@ -251,6 +404,45 @@ ], "notes": null }, + { + "spec": { + "schema": "PayoutOut", + "property": "tracking_complete.step" + }, + "sdk": [ + { + "file": "types/index.d.ts", + "symbol": "TrackingStatus" + } + ], + "notes": "Shared step union of every payin, payout and transfer tracking object; anchored on one of them." + }, + { + "spec": { + "schema": "PayoutOut", + "property": "tracking_payment.forced_provider" + }, + "sdk": [ + { + "file": "types/index.d.ts", + "symbol": "PayoutForcedProvider" + } + ], + "notes": null + }, + { + "spec": { + "schema": "PayoutOut", + "property": "tracking_payment.provider_integration" + }, + "sdk": [ + { + "file": "types/index.d.ts", + "symbol": "PayoutProviderIntegration" + } + ], + "notes": null + }, { "spec": { "schema": "PayoutOut", @@ -290,6 +482,58 @@ ], "notes": null }, + { + "spec": { + "schema": "RetrieveInstanceOut", + "property": "onboarding_step" + }, + "sdk": [ + { + "file": "src/resources/instances/index.ts", + "symbol": "InstanceOnboardingStep" + } + ], + "notes": null + }, + { + "spec": { + "schema": "RetrieveInstanceOut", + "property": "type" + }, + "sdk": [ + { + "file": "src/resources/instances/index.ts", + "symbol": "InstanceType" + } + ], + "notes": null + }, + { + "spec": { + "schema": "Rfi", + "property": "status" + }, + "sdk": [ + { + "file": "src/resources/rfi/index.ts", + "symbol": "RfiStatus" + } + ], + "notes": "Shared with InstanceRfi.status (same member set)." + }, + { + "spec": { + "schema": "RfiField", + "property": "aiprise_document_type" + }, + "sdk": [ + { + "file": "src/resources/rfi/index.ts", + "symbol": "RfiDocumentType" + } + ], + "notes": null + }, { "spec": { "schema": "UpdateCustomerIn", @@ -314,7 +558,7 @@ "symbol": "BusinessIndustry" } ], - "notes": "SDK union additionally carries crypto/web3 business categories (dapp, exchange, gambling, gaming, infra, marketplace, neo_bank, other, saas, social, wallet) that are not NAICS codes and are not part of this spec property at all." + "notes": null }, { "spec": { @@ -459,6 +703,32 @@ ], "notes": null }, + { + "spec": { + "schema": "UploadAnalyzeIn", + "property": "type" + }, + "sdk": [ + { + "file": "src/resources/upload/index.ts", + "symbol": "UploadAnalyzeDocumentType" + } + ], + "notes": null + }, + { + "spec": { + "schema": "UploadAnalyzeOut", + "property": "approval_rate" + }, + "sdk": [ + { + "file": "src/resources/upload/index.ts", + "symbol": "UploadAnalyzeApprovalRate" + } + ], + "notes": null + }, { "spec": { "schema": "UploadIn", @@ -517,67 +787,131 @@ }, { "spec": { - "schema": "WebhookEndpointIn", - "property": "events", - "itemsEnum": true + "schema": "WalletDepositOut", + "property": "network" }, "sdk": [ { - "file": "src/resources/webhooks/index.ts", - "symbol": "WebhookEvents" + "file": "types/index.d.ts", + "symbol": "Network" } ], - "notes": "Array-of-enum: values live on properties.events.items.enum, not a top-level schema enum. This is also contract-check.mjs's own hard-fail anchor (regex-parsed)." - } - ], - "types": [ + "notes": "17-member set (adds tempo, tempo_testnet, arc, arc_testnet); shared Network in types/index.d.ts has only 13, so a local union is declared instead of reusing it." + }, { "spec": { - "path": "/v1/instances/{id}/members", - "method": "get", - "location": "response:200" + "schema": "WalletDepositOut", + "property": "status" }, "sdk": [ { - "file": "src/resources/instances/index.ts", - "symbol": "GetInstanceMembersResponse" + "file": "src/resources/wallets/custodial.ts", + "symbol": "WalletDepositStatus" } ], - "notes": "inline array response, not a named schema. Note: spec names this path param {id}, not {instance_id}, unlike most other instance-scoped paths." + "notes": "No `failed` member, so not identical to shared TransactionStatus. Also used for the deposits list `status` query filter." }, { "spec": { - "path": "/v1/instances/{instance_id}/create-asset-trustline", - "method": "post", - "location": "response:200" + "schema": "WalletDepositOut", + "property": "token" }, "sdk": [ { - "file": "src/resources/wallets/blockchain.ts", - "symbol": "CreateAssetTrustlineResponse" + "file": "types/index.d.ts", + "symbol": "WalletToken" } ], - "notes": "inline object body, not a named schema" + "notes": "Tokens a custodial wallet holds or moves: balances, deposits and transfers. StablecoinToken stays the payin/payout set, which has no EUR stablecoins." }, { "spec": { - "path": "/v1/instances/{instance_id}/customers/{customer_id}/bank-accounts/{bank_account_id}/offramp-wallets", - "method": "post", - "location": "requestBody" + "schema": "WebhookEndpointIn", + "property": "events", + "itemsEnum": true }, "sdk": [ { - "file": "src/resources/wallets/offramp.ts", - "symbol": "CreateOfframpWalletInput" + "file": "src/resources/webhooks/index.ts", + "symbol": "WebhookEvents" } ], - "notes": "inline object body, not a named schema" + "notes": "Array-of-enum: values live on properties.events.items.enum, not a top-level schema enum. This is also contract-check.mjs's own hard-fail anchor (regex-parsed)." }, { "spec": { - "path": "/v1/instances/{instance_id}/customers/{customer_id}/bank-accounts/{bank_account_id}/offramp-wallets", - "method": "post", - "location": "response:200" + "schema": "YieldStatus" + }, + "sdk": [ + { + "file": "src/resources/wallets/custodial.ts", + "symbol": "YieldStatus" + } + ], + "notes": "Standalone enum schema, referenced by WalletOut.yield_status and YieldOut.status." + }, + { + "spec": { + "schema": "AdditionalInfoItem", + "property": "label" + }, + "sdk": [ + { + "file": "src/resources/customers/index.ts", + "symbol": "AdditionalInfoLabel" + } + ], + "notes": null + } + ], + "types": [ + { + "spec": { + "path": "/v1/instances/{id}/members", + "method": "get", + "location": "response:200" + }, + "sdk": [ + { + "file": "src/resources/instances/index.ts", + "symbol": "GetInstanceMembersResponse" + } + ], + "notes": "inline array response, not a named schema. Note: spec names this path param {id}, not {instance_id}, unlike most other instance-scoped paths." + }, + { + "spec": { + "path": "/v1/instances/{instance_id}/create-asset-trustline", + "method": "post", + "location": "response:200" + }, + "sdk": [ + { + "file": "src/resources/wallets/blockchain.ts", + "symbol": "CreateAssetTrustlineResponse" + } + ], + "notes": "inline object body, not a named schema" + }, + { + "spec": { + "path": "/v1/instances/{instance_id}/customers/{customer_id}/bank-accounts/{bank_account_id}/offramp-wallets", + "method": "post", + "location": "requestBody" + }, + "sdk": [ + { + "file": "src/resources/wallets/offramp.ts", + "symbol": "CreateOfframpWalletInput" + } + ], + "notes": "inline object body, not a named schema" + }, + { + "spec": { + "path": "/v1/instances/{instance_id}/customers/{customer_id}/bank-accounts/{bank_account_id}/offramp-wallets", + "method": "post", + "location": "response:200" }, "sdk": [ { @@ -819,6 +1153,10 @@ { "file": "src/resources/bank-accounts/index.ts", "symbol": "CreateTedResponse" + }, + { + "file": "src/resources/bank-accounts/index.ts", + "symbol": "CreateFasterPaymentsResponse" } ], "notes": "Fan-out response side: get, list item, and 11 rail create-response types." @@ -903,6 +1241,10 @@ { "file": "src/resources/bank-accounts/index.ts", "symbol": "CreateTedInput" + }, + { + "file": "src/resources/bank-accounts/index.ts", + "symbol": "CreateFasterPaymentsInput" } ], "notes": "Discriminator fan-out: 11 rail create input types. The `type` discriminator itself is injected by the factory function body (bank-accounts/index.ts:508-610), not carried on any input type by design." @@ -953,7 +1295,7 @@ "symbol": "CreateEvmPayinInput" } ], - "notes": "createEvm(payin_quote_id) posts {payin_quote_id}, matching this schema's one field exactly. CreatePayinInput (payins/index.ts:111, `{quote_id: string}`) is dead code: never referenced by the factory, and its field name does not even match the spec (payin_quote_id). Orphaned, same situation as CreatePayoutInput (payouts/index.ts:106) noted separately." + "notes": "createEvm(payin_quote_id) posts {payin_quote_id}, matching this schema's one field exactly." }, { "spec": { @@ -1083,7 +1425,17 @@ { "file": "src/resources/customers/index.ts", "symbol": "RequestLimitIncreaseResponse" - }, + } + ], + "notes": "1-field {id} response shape shared by several create/request endpoints." + }, + { + "spec": { + "path": "/v1/instances/{instance_id}/customers", + "method": "post", + "location": "response:200" + }, + "sdk": [ { "file": "src/resources/customers/index.ts", "symbol": "CreateIndividualWithStandardKYCResponse" @@ -1097,7 +1449,7 @@ "symbol": "CreateBusinessWithStandardKYBResponse" } ], - "notes": "1-field {id} response shape shared by several create/request endpoints." + "notes": "inline object response {id, customer_id}, not a named schema. One response type per create variant." }, { "spec": { @@ -1115,9 +1467,17 @@ { "file": "src/resources/customers/index.ts", "symbol": "BusinessWithStandardKYB" + }, + { + "file": "src/resources/customers/index.ts", + "symbol": "IndividualWithLightKYC" + }, + { + "file": "src/resources/customers/index.ts", + "symbol": "BusinessWithLightKYB" } ], - "notes": "Discriminator fan-out: the 3 KYC/KYB response types. Same GetCustomerResponse/ListCustomersResponse union is used for get/list." + "notes": "Discriminator fan-out: the 5 KYC/KYB response types, including the legacy light tier that migrated customers carry. The Customer union backs GetCustomerResponse and ListCustomersResponse." }, { "spec": { @@ -1145,6 +1505,32 @@ ], "notes": "Nested at owners.[]." }, + { + "spec": { + "schema": "CreateCustomerIn", + "property": "owners" + }, + "sdk": [ + { + "file": "src/resources/customers/index.ts", + "symbol": "CreateCustomerOwnerInput" + } + ], + "notes": "Nested at owners.[]." + }, + { + "spec": { + "schema": "UpdateCustomerIn", + "property": "owners" + }, + "sdk": [ + { + "file": "src/resources/customers/index.ts", + "symbol": "UpdateCustomerOwnerInput" + } + ], + "notes": "Nested at owners.[]. id is required; every other field is optional." + }, { "spec": { "schema": "Error" @@ -1155,7 +1541,7 @@ "symbol": "ErrorResponse" } ], - "notes": "This SDK's error envelope only ever surfaces `message`; it does not expose the spec's stable `code`, `description`, `errors` list, or `trace_id`." + "notes": "The SDK's `error` object: every field but `success`, which BlindpayApiResponse's data/error split already carries." }, { "spec": { @@ -1522,6 +1908,10 @@ "schema": "Success" }, "sdk": [ + { + "file": "types/index.d.ts", + "symbol": "SuccessResponse" + }, { "file": "src/resources/instances/index.ts", "symbol": "MigrateInstanceOwnershipResponse" @@ -1742,6 +2132,518 @@ } ], "notes": null + }, + { + "spec": { + "schema": "PayableOut" + }, + "sdk": [ + { + "file": "src/resources/payables/index.ts", + "symbol": "Payable" + } + ], + "notes": "Create/get/delete responses and list items alias Payable (CreatePayableResponse, GetPayableResponse, DeletePayableResponse, ListPayablesResponse.data[])." + }, + { + "spec": { + "schema": "CreatePayableIn" + }, + "sdk": [ + { + "file": "src/resources/payables/index.ts", + "symbol": "CreatePayableInput" + } + ], + "notes": "bank_account ($ref CreateBankAccountIn) is typed as CreatePayableBankAccountInput: the existing CreateAchInput/CreateWireInput minus customer_id plus the `type` discriminator, since payables only accept ach or wire (payable-invoice docs)." + }, + { + "spec": { + "schema": "PayableParty" + }, + "sdk": [ + { + "file": "src/resources/payables/index.ts", + "symbol": "PayableParty" + } + ], + "notes": "Used for both `from` and `to` (to is allOf[PayableParty] with a description only)." + }, + { + "spec": { + "schema": "PayableLineItem" + }, + "sdk": [ + { + "file": "src/resources/payables/index.ts", + "symbol": "PayableLineItem" + } + ], + "notes": null + }, + { + "spec": { + "schema": "PayableBankAccount" + }, + "sdk": [ + { + "file": "src/resources/payables/index.ts", + "symbol": "PayableBankAccount" + } + ], + "notes": null + }, + { + "spec": { + "path": "/v1/instances/{instance_id}/payables", + "method": "get", + "location": "response:200" + }, + "sdk": [ + { + "file": "src/resources/payables/index.ts", + "symbol": "ListPayablesResponse" + } + ], + "notes": "inline anyOf body ({data, pagination} | PayableOut[]); the SDK models both branches, and the type check compares the envelope's keys." + }, + { + "spec": { + "schema": "WalletDepositOut" + }, + "sdk": [ + { + "file": "src/resources/wallets/custodial.ts", + "symbol": "WalletDeposit" + } + ], + "notes": null + }, + { + "spec": { + "schema": "WalletDepositsOut" + }, + "sdk": [ + { + "file": "src/resources/wallets/custodial.ts", + "symbol": "GetCustodialWalletDepositsResponse" + } + ], + "notes": null + }, + { + "spec": { + "schema": "CustomerVirtualAccountPreapproval" + }, + "sdk": [ + { + "file": "src/resources/customers/index.ts", + "symbol": "CustomerVirtualAccountPreapproval" + } + ], + "notes": "Nested at CustomerOut.virtual_account_preapproval on all 3 KYC/KYB response types." + }, + { + "spec": { + "schema": "CustomerCnaeCondition" + }, + "sdk": [ + { + "file": "src/resources/customers/index.ts", + "symbol": "CustomerCnaeCondition" + } + ], + "notes": "Nested at CustomerOut.cnae_condition on all 3 KYC/KYB response types." + }, + { + "spec": { + "schema": "LimitIncreaseSupportingDocument" + }, + "sdk": [ + { + "file": "src/resources/customers/index.ts", + "symbol": "LimitIncreaseSupportingDocument" + } + ], + "notes": "Item of CustomerLimitIncreaseIn.supporting_documents and GetCustomerLimitIncreaseOut.supporting_documents." + }, + { + "spec": { + "schema": "Rfi" + }, + "sdk": [ + { + "file": "src/resources/rfi/index.ts", + "symbol": "CustomerRfi" + } + ], + "notes": "Customer-scoped RFI, exposed as blindpay.customers.rfi. Spec type is [object, null]: GetCustomerRfiResponse = CustomerRfi | null. customer_type reuses the shared AccountClass (exact member set); customer_kyc_status is a bare string in the spec and is kept as string." + }, + { + "spec": { + "schema": "InstanceRfi" + }, + "sdk": [ + { + "file": "src/resources/rfi/index.ts", + "symbol": "InstanceRfi" + } + ], + "notes": "Exposed as blindpay.instances.rfi. Spec type is [object, null]: GetInstanceRfiResponse = InstanceRfi | null." + }, + { + "spec": { + "schema": "RfiSection" + }, + "sdk": [ + { + "file": "src/resources/rfi/index.ts", + "symbol": "RfiSection" + } + ], + "notes": null + }, + { + "spec": { + "schema": "RfiField" + }, + "sdk": [ + { + "file": "src/resources/rfi/index.ts", + "symbol": "RfiField" + } + ], + "notes": "items[] ({label, value}) is modeled inline." + }, + { + "spec": { + "schema": "RetrieveInstanceOut" + }, + "sdk": [ + { + "file": "src/resources/instances/index.ts", + "symbol": "Instance" + } + ], + "notes": "Response of GET /v1/instances/{id}, exposed as instances.get(); GetInstanceResponse is an alias of Instance." + }, + { + "spec": { + "path": "/v1/instances/{instance_id}/onboarding/business_details", + "method": "get", + "location": "response:200" + }, + "sdk": [ + { + "file": "src/resources/instances/onboarding.ts", + "symbol": "GetInstanceBusinessDetailsResponse" + } + ], + "notes": "inline object response, not a named schema. The spec has no required list, so every field is optional." + }, + { + "spec": { + "path": "/v1/instances/{instance_id}/onboarding/business_profile", + "method": "get", + "location": "response:200" + }, + "sdk": [ + { + "file": "src/resources/instances/onboarding.ts", + "symbol": "GetInstanceBusinessProfileResponse" + } + ], + "notes": "inline object response, not a named schema. The spec has no required list, so every field is optional." + }, + { + "spec": { + "path": "/v1/instances/{instance_id}/onboarding/ownership_documents", + "method": "get", + "location": "response:200" + }, + "sdk": [ + { + "file": "src/resources/instances/onboarding.ts", + "symbol": "GetInstanceOwnershipDocumentsResponse" + } + ], + "notes": "inline object response, not a named schema. owners[] items are InstanceOnboardingOwner. The spec has no required list, so every field is optional." + }, + { + "spec": { + "schema": "UpdateBlockchainWalletIn" + }, + "sdk": [ + { + "file": "src/resources/wallets/blockchain.ts", + "symbol": "SetBlockchainWalletSelfCustodyInput" + } + ], + "notes": "PATCH body of blockchain-wallets/{id}, exposed as wallets.blockchain.setSelfCustody(). customer_id and id on the SDK input are path params, not body fields." + }, + { + "spec": { + "schema": "PresignIn" + }, + "sdk": [ + { + "file": "src/resources/upload/index.ts", + "symbol": "PresignInput" + } + ], + "notes": "JSON request of POST /v1/presign, exposed as upload.presign(). instance_id is a required query param, not part of PresignIn; it defaults to the client's instanceId when the caller omits it." + }, + { + "spec": { + "schema": "PresignOut" + }, + "sdk": [ + { + "file": "src/resources/upload/index.ts", + "symbol": "PresignResponse" + } + ], + "notes": null + }, + { + "spec": { + "schema": "UploadAnalyzeIn" + }, + "sdk": [ + { + "file": "src/resources/upload/index.ts", + "symbol": "UploadAnalyzeInput" + } + ], + "notes": "multipart/form-data request of POST /v1/upload/analyze, exposed as upload.analyze(); instance_id is an optional query param, not part of UploadAnalyzeIn." + }, + { + "spec": { + "schema": "UploadAnalyzeOut" + }, + "sdk": [ + { + "file": "src/resources/upload/index.ts", + "symbol": "UploadAnalyzeResponse" + } + ], + "notes": null + }, + { + "spec": { + "schema": "CreatePlaidLinkIn" + }, + "sdk": [ + { + "file": "src/resources/bank-accounts/index.ts", + "symbol": "CreatePlaidBankAccountInput" + } + ], + "notes": null + }, + { + "spec": { + "schema": "PlaidLinkOut" + }, + "sdk": [ + { + "file": "src/resources/bank-accounts/index.ts", + "symbol": "CreatePlaidBankAccountResponse" + } + ], + "notes": null + }, + { + "spec": { + "schema": "AdditionalInfoItem" + }, + "sdk": [ + { + "file": "src/resources/customers/index.ts", + "symbol": "AdditionalInfoItem" + } + ], + "notes": null + }, + { + "spec": { + "schema": "PayinNewWebhookOut" + }, + "sdk": [ + { + "file": "src/resources/webhooks/events.ts", + "symbol": "PayinWebhookEvent" + } + ], + "notes": "webhook payload; one SDK type covers every event of this resource, its webhook_event union lists each event name" + }, + { + "spec": { + "schema": "PayinUpdateWebhookOut" + }, + "sdk": [ + { + "file": "src/resources/webhooks/events.ts", + "symbol": "PayinWebhookEvent" + } + ], + "notes": "webhook payload; one SDK type covers every event of this resource, its webhook_event union lists each event name" + }, + { + "spec": { + "schema": "PayinCompleteWebhookOut" + }, + "sdk": [ + { + "file": "src/resources/webhooks/events.ts", + "symbol": "PayinWebhookEvent" + } + ], + "notes": "webhook payload; one SDK type covers every event of this resource, its webhook_event union lists each event name" + }, + { + "spec": { + "schema": "PayinPartnerFeeWebhookOut" + }, + "sdk": [ + { + "file": "src/resources/webhooks/events.ts", + "symbol": "PayinWebhookEvent" + } + ], + "notes": "webhook payload; one SDK type covers every event of this resource, its webhook_event union lists each event name" + }, + { + "spec": { + "schema": "PayoutNewWebhookOut" + }, + "sdk": [ + { + "file": "src/resources/webhooks/events.ts", + "symbol": "PayoutWebhookEvent" + } + ], + "notes": "webhook payload; one SDK type covers every event of this resource, its webhook_event union lists each event name" + }, + { + "spec": { + "schema": "PayoutUpdateWebhookOut" + }, + "sdk": [ + { + "file": "src/resources/webhooks/events.ts", + "symbol": "PayoutWebhookEvent" + } + ], + "notes": "webhook payload; one SDK type covers every event of this resource, its webhook_event union lists each event name" + }, + { + "spec": { + "schema": "PayoutCompleteWebhookOut" + }, + "sdk": [ + { + "file": "src/resources/webhooks/events.ts", + "symbol": "PayoutWebhookEvent" + } + ], + "notes": "webhook payload; one SDK type covers every event of this resource, its webhook_event union lists each event name" + }, + { + "spec": { + "schema": "PayoutPartnerFeeWebhookOut" + }, + "sdk": [ + { + "file": "src/resources/webhooks/events.ts", + "symbol": "PayoutWebhookEvent" + } + ], + "notes": "webhook payload; one SDK type covers every event of this resource, its webhook_event union lists each event name" + }, + { + "spec": { + "schema": "TransferNewWebhookOut" + }, + "sdk": [ + { + "file": "src/resources/webhooks/events.ts", + "symbol": "TransferWebhookEvent" + } + ], + "notes": "webhook payload; one SDK type covers every event of this resource, its webhook_event union lists each event name" + }, + { + "spec": { + "schema": "TransferUpdateWebhookOut" + }, + "sdk": [ + { + "file": "src/resources/webhooks/events.ts", + "symbol": "TransferWebhookEvent" + } + ], + "notes": "webhook payload; one SDK type covers every event of this resource, its webhook_event union lists each event name" + }, + { + "spec": { + "schema": "TransferCompleteWebhookOut" + }, + "sdk": [ + { + "file": "src/resources/webhooks/events.ts", + "symbol": "TransferWebhookEvent" + } + ], + "notes": "webhook payload; one SDK type covers every event of this resource, its webhook_event union lists each event name" + }, + { + "spec": { + "schema": "TosAcceptWebhookOut" + }, + "sdk": [ + { + "file": "src/resources/webhooks/events.ts", + "symbol": "TosAcceptWebhookEvent" + } + ], + "notes": "webhook payload; one SDK type covers every event of this resource, its webhook_event union lists each event name" + }, + { + "spec": { + "schema": "CustomerDeleteWebhookOut" + }, + "sdk": [ + { + "file": "src/resources/webhooks/events.ts", + "symbol": "CustomerDeleteWebhookEvent" + } + ], + "notes": "webhook payload; one SDK type covers every event of this resource, its webhook_event union lists each event name" + }, + { + "spec": { + "schema": "WalletInboundWebhookOut" + }, + "sdk": [ + { + "file": "src/resources/webhooks/events.ts", + "symbol": "WalletInboundWebhookEvent" + } + ], + "notes": "webhook payload; one SDK type covers every event of this resource, its webhook_event union lists each event name" + }, + { + "spec": { + "schema": "WalletInboundTokenOut" + }, + "sdk": [ + { + "file": "src/resources/webhooks/events.ts", + "symbol": "WalletInboundToken" + } + ], + "notes": "wallet.inbound payload's token object" } ], "ignore": { @@ -1752,122 +2654,113 @@ }, { "name": "BankAccountWebhookOut", - "reason": "Webhook payload body for bankAccount.new. This SDK does not model webhook payload shapes as typed symbols anywhere; verifyWebhookSignature only verifies the signature and returns a boolean, consumers parse the JSON body themselves." + "reason": "Webhook payload body for bankAccount.new. Typed as BankAccountWebhookEvent in src/resources/webhooks/events.ts, which is { webhook_event } & ListBankAccountsResponse[number]: the payload has the same property set as BankAccountOut, whose mapping already checks those fields. Not mapped here because the patcher's field scan cannot read through an intersection." }, { - "name": "BlockchainWalletWebhookOut", - "reason": "Webhook payload body for blockchainWallet.new; same reasoning as BankAccountWebhookOut." + "name": "BlockchainWalletUpdateWebhookOut", + "reason": "Webhook payload body for blockchainWallet.update. Typed as BlockchainWalletWebhookEvent in src/resources/webhooks/events.ts, which is { webhook_event } & GetBlockchainWalletResponse: the payload has the same property set as BlockchainWalletOut, whose mapping already checks those fields. Not mapped here because the patcher's field scan cannot read through an intersection." }, { - "name": "CustomerDeleteWebhookOut", - "reason": "Webhook payload body for customer.delete; same reasoning as BankAccountWebhookOut." + "name": "BlockchainWalletWebhookOut", + "reason": "Webhook payload body for blockchainWallet.new. Typed as BlockchainWalletWebhookEvent in src/resources/webhooks/events.ts, which is { webhook_event } & GetBlockchainWalletResponse: the payload has the same property set as BlockchainWalletOut, whose mapping already checks those fields. Not mapped here because the patcher's field scan cannot read through an intersection." }, { "name": "CustomerNewWebhookOut", - "reason": "Webhook payload body for customer.new; same reasoning as BankAccountWebhookOut." + "reason": "Webhook payload body for customer.new. Typed as CustomerWebhookEvent in src/resources/webhooks/events.ts, which is { webhook_event } & GetCustomerResponse: the payload has the same property set as CustomerOut, whose mapping already checks those fields. Not mapped here because the patcher's field scan cannot read through an intersection." }, { "name": "CustomerUpdateWebhookOut", - "reason": "Webhook payload body for customer.update; same reasoning as BankAccountWebhookOut." - }, - { - "name": "InstanceRfi", - "reason": "Instance-level RFI variant; not modeled, same as Rfi." + "reason": "Webhook payload body for customer.update. Typed as CustomerWebhookEvent in src/resources/webhooks/events.ts, which is { webhook_event } & GetCustomerResponse: the payload has the same property set as CustomerOut, whose mapping already checks those fields. Not mapped here because the patcher's field scan cannot read through an intersection." }, { "name": "LimitIncreaseNewWebhookOut", - "reason": "Webhook payload body for limitIncrease.new; same reasoning as BankAccountWebhookOut." + "reason": "Webhook payload body for limitIncrease.new. Typed as LimitIncreaseWebhookEvent in src/resources/webhooks/events.ts, which is { webhook_event } & GetLimitIncreaseRequestsResponse[number]: the payload has the same property set as GetCustomerLimitIncreaseOut, whose mapping already checks those fields. Not mapped here because the patcher's field scan cannot read through an intersection." }, { "name": "LimitIncreaseUpdateWebhookOut", - "reason": "Webhook payload body for limitIncrease.update; same reasoning as BankAccountWebhookOut (still used above as the reachable anchor for the LimitIncreaseRequestStatus enum, which is otherwise identical to GetCustomerLimitIncreaseOut.status)." + "reason": "Webhook payload body for limitIncrease.update. Typed as LimitIncreaseWebhookEvent in src/resources/webhooks/events.ts, which is { webhook_event } & GetLimitIncreaseRequestsResponse[number]: the payload has the same property set as GetCustomerLimitIncreaseOut, whose mapping already checks those fields. Not mapped here because the patcher's field scan cannot read through an intersection. Still the reachable anchor for the LimitIncreaseRequestStatus enum above." + }, + { + "name": "PayableCompleteWebhookOut", + "reason": "Webhook payload body for payable.complete. Typed as PayableWebhookEvent in src/resources/webhooks/events.ts, which is { webhook_event } & Payable: the payload has the same property set as PayableOut, whose mapping already checks those fields. Not mapped here because the patcher's field scan cannot read through an intersection." + }, + { + "name": "PayableNewWebhookOut", + "reason": "Webhook payload body for payable.new. Typed as PayableWebhookEvent in src/resources/webhooks/events.ts, which is { webhook_event } & Payable: the payload has the same property set as PayableOut, whose mapping already checks those fields. Not mapped here because the patcher's field scan cannot read through an intersection." + }, + { + "name": "PayableUpdateWebhookOut", + "reason": "Webhook payload body for payable.update. Typed as PayableWebhookEvent in src/resources/webhooks/events.ts, which is { webhook_event } & Payable: the payload has the same property set as PayableOut, whose mapping already checks those fields. Not mapped here because the patcher's field scan cannot read through an intersection." }, { "name": "PayinCompleteWebhookOut", - "reason": "Webhook payload body for payin.complete; same reasoning as BankAccountWebhookOut." + "reason": "Webhook payload body for payin.complete. Its top-level fields are checked through the types[] mapping to PayinWebhookEvent (src/resources/webhooks/events.ts). Kept in ignore only so its inline nested shapes (the tracking_* objects, and blindpay_bank_details on payin) need no nestedShapeOmissions entries: they are identical to PayinOut's, which are covered there." }, { "name": "PayinNewWebhookOut", - "reason": "Webhook payload body for payin.new; same reasoning as BankAccountWebhookOut." + "reason": "Webhook payload body for payin.new. Its top-level fields are checked through the types[] mapping to PayinWebhookEvent (src/resources/webhooks/events.ts). Kept in ignore only so its inline nested shapes (the tracking_* objects, and blindpay_bank_details on payin) need no nestedShapeOmissions entries: they are identical to PayinOut's, which are covered there." }, { "name": "PayinPartnerFeeWebhookOut", - "reason": "Webhook payload body for payin.partnerFee; same reasoning as BankAccountWebhookOut." + "reason": "Webhook payload body for payin.partnerFee. Its top-level fields are checked through the types[] mapping to PayinWebhookEvent (src/resources/webhooks/events.ts). Kept in ignore only so its inline nested shapes (the tracking_* objects, and blindpay_bank_details on payin) need no nestedShapeOmissions entries: they are identical to PayinOut's, which are covered there." }, { "name": "PayinUpdateWebhookOut", - "reason": "Webhook payload body for payin.update; same reasoning as BankAccountWebhookOut." + "reason": "Webhook payload body for payin.update. Its top-level fields are checked through the types[] mapping to PayinWebhookEvent (src/resources/webhooks/events.ts). Kept in ignore only so its inline nested shapes (the tracking_* objects, and blindpay_bank_details on payin) need no nestedShapeOmissions entries: they are identical to PayinOut's, which are covered there." }, { "name": "PayoutCompleteWebhookOut", - "reason": "Webhook payload body for payout.complete; same reasoning as BankAccountWebhookOut." + "reason": "Webhook payload body for payout.complete. Its top-level fields are checked through the types[] mapping to PayoutWebhookEvent (src/resources/webhooks/events.ts). Kept in ignore only so its inline nested shapes (the tracking_* objects, and blindpay_bank_details on payin) need no nestedShapeOmissions entries: they are identical to PayoutOut's, which are covered there." }, { "name": "PayoutNewWebhookOut", - "reason": "Webhook payload body for payout.new; same reasoning as BankAccountWebhookOut." + "reason": "Webhook payload body for payout.new. Its top-level fields are checked through the types[] mapping to PayoutWebhookEvent (src/resources/webhooks/events.ts). Kept in ignore only so its inline nested shapes (the tracking_* objects, and blindpay_bank_details on payin) need no nestedShapeOmissions entries: they are identical to PayoutOut's, which are covered there." }, { "name": "PayoutPartnerFeeWebhookOut", - "reason": "Webhook payload body for payout.partnerFee; same reasoning as BankAccountWebhookOut." + "reason": "Webhook payload body for payout.partnerFee. Its top-level fields are checked through the types[] mapping to PayoutWebhookEvent (src/resources/webhooks/events.ts). Kept in ignore only so its inline nested shapes (the tracking_* objects, and blindpay_bank_details on payin) need no nestedShapeOmissions entries: they are identical to PayoutOut's, which are covered there." }, { "name": "PayoutUpdateWebhookOut", - "reason": "Webhook payload body for payout.update; same reasoning as BankAccountWebhookOut (still used above as the reachable anchor for the TransactionStatus enum)." - }, - { - "name": "Rfi", - "reason": "RFI resource (GET/POST /v1/instances/{instance_id}/rfi and .../customers/{customer_id}/rfi) is not modeled by this SDK. Known coverage gap, tracked for Phase C." - }, - { - "name": "RfiField", - "reason": "Nested under Rfi.request/response; not modeled, same as Rfi." - }, - { - "name": "RfiSection", - "reason": "Nested under Rfi.request/response; not modeled, same as Rfi." + "reason": "Webhook payload body for payout.update. Its top-level fields are checked through the types[] mapping to PayoutWebhookEvent (src/resources/webhooks/events.ts). Kept in ignore only so its inline nested shapes (the tracking_* objects, and blindpay_bank_details on payin) need no nestedShapeOmissions entries: they are identical to PayoutOut's, which are covered there. Still the reachable anchor for the TransactionStatus enum above." }, { "name": "SwiftCodeResponse", "reason": "Array-wrapper alias for SwiftCodeItem[]; the item shape itself is mapped via GetSwiftCodeBankDetailsResponse -> SwiftCodeItem." }, { - "name": "TosAcceptWebhookOut", - "reason": "Webhook payload body for tos.accept; same reasoning as BankAccountWebhookOut." + "name": "TransferCompleteWebhookOut", + "reason": "Webhook payload body for transfer.complete. Its top-level fields are checked through the types[] mapping to TransferWebhookEvent (src/resources/webhooks/events.ts). Kept in ignore only so its inline nested shapes (the tracking_* objects, and blindpay_bank_details on payin) need no nestedShapeOmissions entries: they are identical to TransferOut's, which are covered there." }, { - "name": "UploadAnalyzeIn", - "reason": "POST /v1/upload/analyze is not modeled by this SDK. Known coverage gap, tracked for Phase C." + "name": "TransferNewWebhookOut", + "reason": "Webhook payload body for transfer.new. Its top-level fields are checked through the types[] mapping to TransferWebhookEvent (src/resources/webhooks/events.ts). Kept in ignore only so its inline nested shapes (the tracking_* objects, and blindpay_bank_details on payin) need no nestedShapeOmissions entries: they are identical to TransferOut's, which are covered there." }, { - "name": "UploadAnalyzeOut", - "reason": "Response of POST /v1/upload/analyze; not modeled, same as UploadAnalyzeIn." + "name": "TransferUpdateWebhookOut", + "reason": "Webhook payload body for transfer.update. Its top-level fields are checked through the types[] mapping to TransferWebhookEvent (src/resources/webhooks/events.ts). Kept in ignore only so its inline nested shapes (the tracking_* objects, and blindpay_bank_details on payin) need no nestedShapeOmissions entries: they are identical to TransferOut's, which are covered there." }, { - "name": "WalletInboundSchemaOut", - "reason": "Webhook payload body for wallet.inbound; same reasoning as BankAccountWebhookOut." - } - ], - "operations": [ - { - "name": "GET /v1/instances/{instance_id}/customers/{customer_id}/rfi", - "reason": "Rfi (request-for-information) family has no existing SDK resource; a human must design it, the generator will not guess a brand-new resource." + "name": "VirtualAccountCompleteWebhookOut", + "reason": "Webhook payload body for virtualAccount.complete. Typed as VirtualAccountWebhookEvent in src/resources/webhooks/events.ts, which is { webhook_event } & VirtualAccount: the payload has the same property set as VirtualAccountOut, whose mapping already checks those fields. Not mapped here because the patcher's field scan cannot read through an intersection." }, { - "name": "GET /v1/instances/{instance_id}/rfi", - "reason": "Rfi family, same as the customer-scoped variant." + "name": "VirtualAccountNewWebhookOut", + "reason": "Webhook payload body for virtualAccount.new. Typed as VirtualAccountWebhookEvent in src/resources/webhooks/events.ts, which is { webhook_event } & VirtualAccount: the payload has the same property set as VirtualAccountOut, whose mapping already checks those fields. Not mapped here because the patcher's field scan cannot read through an intersection." }, { - "name": "POST /v1/instances/{instance_id}/customers/{customer_id}/rfi", - "reason": "Rfi family, same as the customer-scoped GET." + "name": "WalletNewWebhookOut", + "reason": "Webhook payload body for wallet.new. Typed as WalletWebhookEvent in src/resources/webhooks/events.ts, which is { webhook_event } & CustodialWallet: the payload has the same property set as WalletOut, whose mapping already checks those fields. Not mapped here because the patcher's field scan cannot read through an intersection." }, { - "name": "POST /v1/instances/{instance_id}/rfi", - "reason": "Rfi family, same as the customer-scoped GET." + "name": "WalletUpdateWebhookOut", + "reason": "Webhook payload body for wallet.update. Typed as WalletWebhookEvent in src/resources/webhooks/events.ts, which is { webhook_event } & CustodialWallet: the payload has the same property set as WalletOut, whose mapping already checks those fields. Not mapped here because the patcher's field scan cannot read through an intersection." }, { - "name": "POST /v1/upload/analyze", - "reason": "Multipart/binary upload, not instance-scoped and not JSON in/out; classifier never guesses this shape." + "name": "YieldFee", + "reason": "Only referenced by GetFeesOut.yield (billing fees resource, src/resources/fees/index.ts). GetFeesResponse does not model the yield fee split yet; see the GetFeesOut.yield entry in unmodeled.json properties." } - ] + ], + "operations": [] } } diff --git a/.api-sync/spec-snapshot.json b/.api-sync/spec-snapshot.json index c495d8d..325ad46 100644 --- a/.api-sync/spec-snapshot.json +++ b/.api-sync/spec-snapshot.json @@ -47,6 +47,9 @@ { "name": "Transfers" }, + { + "name": "Payables" + }, { "name": "Webhook Endpoints" }, @@ -70,7 +73,7 @@ }, { "name": "Errors", - "description": "## Error responses\n\nEvery error response uses this envelope:\n\n```json\n{\n \"success\": false,\n \"code\": \"QUOTES_EXPIRED\",\n \"message\": \"quote_expired\",\n \"description\": \"This quote has expired. Request a new quote and try again.\",\n \"errors\": [],\n \"trace_id\": \"0af7651916cd43dd8448eb211c80319c\"\n}\n```\n\n- `code` is a stable identifier, safe to build programmatic handling on.\n- `message` is a legacy machine string kept for backward compatibility. Prefer `code`.\n- `description` is human-readable text, safe to show to end users.\n- `trace_id` identifies the request. Include it when contacting support.\n\nRetry semantics per code: `retryable` means the same request can be retried as is, `terminal` means do not retry, and `actionable` means the request succeeds only after you fix something (for example funding a balance or correcting bank details).\n\nThe Status column shows the HTTP status a code typically responds with; the per-endpoint error tabs list the exact status each endpoint returns.\n\n### Error codes\n\n| Code | Status | Retry | Description |\n| --- | --- | --- | --- |\n| `AUTH_EMAIL_ALREADY_REGISTERED` | 409 | terminal | This email address is already registered. |\n| `AUTH_FORBIDDEN` | 403 | terminal | You do not have permission to perform this action. |\n| `AUTH_IP_BLOCKED` | 403 | terminal | Requests from this IP address are not allowed for this API key. |\n| `AUTH_RATE_LIMITED` | 429 | retryable | Too many requests. Wait a moment and try again. |\n| `AUTH_SERVICE_UNAVAILABLE` | 503 | retryable | The authentication service is temporarily unavailable. Try again shortly. |\n| `AUTH_TOKEN_INVALID` | 401 | actionable | This link or token is invalid or has expired. Request a new one. |\n| `AUTH_UNAUTHORIZED` | 401 | actionable | Authentication failed. Check your API key or session and try again. |\n| `BANK_ACCOUNTS_INCOMPLETE` | 400 | actionable | The bank account details are incomplete for this payment method. Provide the missing fields. |\n| `BANK_ACCOUNTS_INVALID_BANK_CODE` | 400 | actionable | The bank code provided is not valid for this payment rail. The message lists where to fetch the valid codes. |\n| `BANK_ACCOUNTS_INVALID_ROUTING` | 400 | actionable | The routing number provided is not valid. Check the number and try again. |\n| `BANK_ACCOUNTS_NOT_APPROVED` | 403 | actionable | This bank account is not approved yet. |\n| `BANK_ACCOUNTS_NOT_FOUND` | 404 | actionable | The requested bank account was not found. |\n| `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED` | 400 | terminal | This banking option is not supported for this operation. |\n| `BANK_ACCOUNTS_RTP_NOT_SUPPORTED` | 400 | terminal | The provided routing number does not support instant payments. |\n| `BILLING_INVOICE_NOT_FOUND` | 404 | actionable | The requested invoice was not found. |\n| `BILLING_INVOICE_NOT_PAYABLE` | 409 | terminal | This invoice cannot be paid or collected in its current state. |\n| `BILLING_NOT_AVAILABLE` | 403 | terminal | Billing is not available for development instances. |\n| `BLOCKCHAIN_CALL_FAILED` | 400 | retryable | The blockchain call could not be completed. Check the transaction details and try again. |\n| `BLOCKCHAIN_NETWORK_NOT_SUPPORTED` | 400 | terminal | This network or token combination is not supported for this operation. |\n| `BLOCKCHAIN_TOKEN_NOT_SUPPORTED` | 400 | actionable | This token is not supported for this instance type. Development instances settle in USDB; production instances settle in USDC or USDT. |\n| `BLOCKCHAIN_TX_FAILED` | 502 | retryable | The blockchain transaction failed. Try again, and contact support if the problem persists. |\n| `COMPLIANCE_RFI_IN_PROGRESS` | 409 | actionable | An information request is already in progress. Resolve it before continuing. |\n| `COMPLIANCE_RFI_INVALID` | 400 | actionable | The information request could not be processed. Check the submitted fields. |\n| `CUSTOMERS_ALREADY_APPROVED` | 409 | terminal | This customer is already approved. |\n| `CUSTOMERS_BUSINESS_ENHANCED_NOT_AVAILABLE` | 400 | terminal | Enhanced verification is not available for business customers. Use standard verification (kyc_type: standard) for businesses. |\n| `CUSTOMERS_COUNTRY_NOT_SUPPORTED` | 400 | terminal | This country is not supported for this operation. |\n| `CUSTOMERS_ENHANCED_KYC_REQUIRED` | 400 | actionable | Individuals from high-risk countries must use enhanced verification (kyc_type: enhanced); standard verification is not available for them. See https://www.blindpay.com/docs/kb/supported-countries for country tiers. |\n| `CUSTOMERS_ID_DOCUMENT_INVALID` | 400 | actionable | The identity document is not an accepted passport or national ID. Provide a valid passport or national ID for this customer (a driver license is not accepted for high-risk countries). |\n| `CUSTOMERS_INVALID_DATA` | 422 | actionable | The customer data was rejected by the banking provider. Check the highlighted fields and try again. |\n| `CUSTOMERS_INVALID_PHONE` | 400 | actionable | The phone number provided is not valid. Check the number and try again. |\n| `CUSTOMERS_INVALID_TAX_ID` | 400 | actionable | The tax ID provided is not valid. Check the value and try again. |\n| `CUSTOMERS_KYC_NOT_APPROVED` | 403 | actionable | This customer has not completed verification yet. Complete the verification before continuing. |\n| `CUSTOMERS_NOT_FOUND` | 404 | actionable | The requested customer was not found. |\n| `CUSTOMERS_ONBOARDING_INCOMPLETE` | 400 | actionable | Onboarding is not complete yet. Finish the remaining steps before continuing. |\n| `DATA_INTEGRITY_ERROR` | 422 | terminal | This record could not be loaded because it contains invalid stored data. Contact support with the ID below. |\n| `FEES_NOT_FOUND` | 404 | actionable | The requested fee configuration was not found. |\n| `FEES_PARTNER_FEE_EXCEEDED` | 400 | actionable | The partner fee exceeds the allowed maximum for this transaction. |\n| `FILES_ANALYSIS_FAILED` | 502 | retryable | The document could not be analyzed. Try again, and contact support if the problem persists. |\n| `FILES_EMPTY` | 400 | actionable | The uploaded file is empty. Upload a valid file. |\n| `FILES_TOO_LARGE` | 400 | actionable | The file is too large. Upload a smaller file. |\n| `FILES_TYPE_NOT_ALLOWED` | 400 | actionable | This file type is not allowed. Upload a supported file type. |\n| `FILES_UNREADABLE` | 400 | actionable | We could not read the uploaded file. Check the file and try again. |\n| `INSTANCES_BLOCKED` | 403 | terminal | This account is blocked. Contact support for assistance. |\n| `INSTANCES_LIMIT_REACHED` | 400 | terminal | You reached the maximum number of instances allowed for your account. |\n| `INSTANCES_NOT_FOUND` | 404 | actionable | The requested instance was not found. |\n| `INTERNAL_ERROR` | 500 | retryable | Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists. |\n| `LIMITS_AMOUNT_OUT_OF_RANGE` | 400 | actionable | The amount is outside the allowed range. The message includes the allowed range. |\n| `LIMITS_VOLUME_EXCEEDED` | 400 | actionable | You exceeded your transaction volume limit. The message includes the remaining amount available. |\n| `PAYINS_ALREADY_TERMINAL` | 409 | terminal | This payin already reached a final status and cannot be changed. |\n| `PAYINS_METHOD_NOT_SUPPORTED` | 400 | terminal | This payment method is not supported for this operation. |\n| `PAYINS_NOT_FOUND` | 404 | actionable | The requested payin was not found. |\n| `PAYINS_TAX_ID_REQUIRED` | 400 | actionable | A tax ID is required for this payment method. Provide the tax ID and try again. |\n| `PAYOUTS_ALLOWANCE_NOT_CONFIRMED` | 400 | retryable | The token approval for this payout has not been confirmed on-chain yet, or the approved amount is lower than the payout amount. Wait for the approval transaction to confirm and execute the quote again. |\n| `PAYOUTS_AMOUNT_BELOW_MINIMUM` | 400 | actionable | The amount is below the minimum for this payment rail. |\n| `PAYOUTS_DOCUMENTS_NOT_ACCEPTED` | 400 | terminal | Document upload is only available for international wire payouts. |\n| `PAYOUTS_INSUFFICIENT_BALANCE` | 400 | actionable | There is not enough balance to complete this payout. Fund your balance and try again. |\n| `PAYOUTS_NOT_FOUND` | 404 | actionable | The requested payout was not found. |\n| `QUOTES_ALREADY_USED` | 409 | actionable | This quote was already used. Request a new quote. |\n| `QUOTES_EXPIRED` | 400 | actionable | This quote has expired. Request a new quote and try again. |\n| `QUOTES_INSUFFICIENT_LIQUIDITY` | 400 | actionable | There is not enough market liquidity to fill this amount right now. Try a smaller amount or try again later. |\n| `QUOTES_INVALID_STATE` | 400 | actionable | This quote cannot be authorized in its current state. Request a new quote and try again. |\n| `QUOTES_NOT_FOUND` | 404 | actionable | The requested quote was not found. |\n| `QUOTES_OTC_NOT_SUPPORTED` | 400 | actionable | This OTC configuration is not supported. OTC requires BRL with USDT, and either the sender amount with fees not covered, or the receiver amount with fees covered. |\n| `QUOTES_RATE_UNAVAILABLE` | 502 | retryable | An exchange rate is temporarily unavailable. Try again shortly. |\n| `REQUEST_REJECTED` | 400 | actionable | The request was rejected. Check the error message for details. |\n| `TOS_ALREADY_ACCEPTED` | 409 | terminal | These terms of service were already accepted. |\n| `TOS_NOT_ACCEPTED` | 400 | actionable | The terms of service must be accepted before continuing. |\n| `TOS_NOT_FOUND` | 404 | actionable | The requested terms of service record was not found. |\n| `TRANSFERS_NOT_ENABLED` | 403 | terminal | Wallets and transfers are not enabled for this account. Contact support to enable them. |\n| `VALIDATION_FAILED` | 400 | actionable | The request contains invalid fields. Check the errors list for details. |\n| `VALIDATION_INVALID_REQUEST` | 400 | actionable | The request is not valid for this operation. Check the parameters and try again. |\n| `VALIDATION_MISSING_BODY` | 400 | actionable | The request body is missing or malformed. Send valid JSON with the Content-Type: application/json header. |\n| `VALIDATION_MISSING_REQUIRED_FIELDS` | 400 | actionable | Required fields are missing. Provide the missing fields and try again. |\n| `VIRTUAL_ACCOUNTS_DISABLED` | 403 | terminal | Virtual accounts are not enabled for this account. Contact support to enable them. |\n| `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED` | 400 | actionable | Additional documents are required to create this virtual account. Upload the requested documents. |\n| `VIRTUAL_ACCOUNTS_NOT_APPROVED` | 403 | actionable | This virtual account is not approved yet. |\n| `VIRTUAL_ACCOUNTS_NOT_FOUND` | 404 | actionable | The requested virtual account was not found. |\n| `VIRTUAL_ACCOUNTS_PROVISION_FAILED` | 502 | retryable | We could not create the virtual account. Try again, and contact support if the problem persists. |\n| `VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED` | 400 | terminal | Virtual accounts are not available for this country or region. |\n| `WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT` | 400 | terminal | This wallet is attached to a virtual account and cannot be deleted. Delete the virtual account first. |\n| `WALLETS_BALANCE_UNAVAILABLE` | 503 | retryable | The wallet balance is temporarily unavailable. Try again shortly. |\n| `WALLETS_NOT_FOUND` | 404 | actionable | The requested wallet was not found. |\n| `WEBHOOKS_LIMIT_REACHED` | 400 | terminal | You reached the maximum number of webhook endpoints. |\n| `WEBHOOKS_SIGNATURE_INVALID` | 401 | terminal | The webhook signature is missing or invalid. |\n| `WEBHOOKS_URL_INVALID` | 400 | actionable | The webhook URL is not valid. Use a reachable HTTPS URL. |\n" + "description": "## Error responses\n\nEvery error response uses this envelope:\n\n```json\n{\n \"success\": false,\n \"code\": \"QUOTES_EXPIRED\",\n \"message\": \"quote_expired\",\n \"description\": \"This quote has expired. Request a new quote and try again.\",\n \"errors\": [],\n \"trace_id\": \"0af7651916cd43dd8448eb211c80319c\"\n}\n```\n\n- `code` is a stable identifier, safe to build programmatic handling on.\n- `message` is a legacy machine string kept for backward compatibility. Prefer `code`.\n- `description` is human-readable text, safe to show to end users.\n- `trace_id` identifies the request. Include it when contacting support.\n\nRetry semantics per code: `retryable` means the same request can be retried as is, `terminal` means do not retry, and `actionable` means the request succeeds only after you fix something (for example funding a balance or correcting bank details).\n\nThe Status column shows the HTTP status a code typically responds with; the per-endpoint error tabs list the exact status each endpoint returns.\n\n### Error codes\n\n| Code | Status | Retry | Description |\n| --- | --- | --- | --- |\n| `AUTH_EMAIL_ALREADY_REGISTERED` | 409 | terminal | This email address is already registered. |\n| `AUTH_FORBIDDEN` | 403 | terminal | You do not have permission to perform this action. |\n| `AUTH_IP_BLOCKED` | 403 | terminal | Requests from this IP address are not allowed for this API key. |\n| `AUTH_OAUTH_CONNECTION_NOT_BOUND` | 403 | actionable | This OAuth connection is not linked to an instance. Open the BlindPay dashboard to choose the instance it should act on. |\n| `AUTH_OAUTH_CONNECTION_NOT_FOUND` | 404 | actionable | The requested OAuth connection was not found. |\n| `AUTH_OAUTH_CONNECTION_REVOKED` | 403 | actionable | This OAuth connection was revoked. Reconnect it from the BlindPay dashboard. |\n| `AUTH_RATE_LIMITED` | 429 | retryable | Too many requests. Wait a moment and try again. |\n| `AUTH_SERVICE_UNAVAILABLE` | 503 | retryable | The authentication service is temporarily unavailable. Try again shortly. |\n| `AUTH_TOKEN_INVALID` | 401 | actionable | This link or token is invalid or has expired. Request a new one. |\n| `AUTH_UNAUTHORIZED` | 401 | actionable | Authentication failed. Check your API key or session and try again. |\n| `BANK_ACCOUNTS_INCOMPLETE` | 400 | actionable | The bank account details are incomplete for this payment method. Provide the missing fields. |\n| `BANK_ACCOUNTS_INVALID_BANK_CODE` | 400 | actionable | The bank code provided is not valid for this payment rail. The message lists where to fetch the valid codes. |\n| `BANK_ACCOUNTS_INVALID_ROUTING` | 400 | actionable | The routing number provided is not valid. Check the number and try again. |\n| `BANK_ACCOUNTS_NOT_APPROVED` | 403 | actionable | This bank account is not approved yet. |\n| `BANK_ACCOUNTS_NOT_FOUND` | 404 | actionable | The requested bank account was not found. |\n| `BANK_ACCOUNTS_OWNED_BY_PAYABLE` | 400 | terminal | This bank account belongs to an invoice payable and can only be paid through that payable. Quote the payable instead. |\n| `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED` | 400 | terminal | This banking option is not supported for this operation. |\n| `BANK_ACCOUNTS_PLAID_CONNECTION_INVALID` | 400 | actionable | The bank connection could not be completed. Connect the account again. |\n| `BANK_ACCOUNTS_PLAID_LINK_FAILED` | 502 | retryable | We could not start the bank connection. Try again, and contact support if the problem persists. |\n| `BANK_ACCOUNTS_PLAID_LINK_SESSION_INVALID` | 404 | actionable | This bank connection link is unknown or has expired. Request a new link. |\n| `BANK_ACCOUNTS_PLAID_NOT_ENABLED` | 400 | terminal | Instantly connected bank accounts are not enabled for this account. Contact support to enable them. |\n| `BANK_ACCOUNTS_PLAID_NOT_FIRST_PARTY` | 400 | terminal | The connected bank account does not belong to this customer. Only accounts held in the customer's own name can be connected. |\n| `BANK_ACCOUNTS_RTP_NOT_SUPPORTED` | 400 | terminal | The provided routing number does not support instant payments. |\n| `BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR` | 400 | terminal | SEPA payouts are only available to EUR accounts. This IBAN is from a country that holds another currency, so the payment would fail at settlement. Use an IBAN from a EUR account instead. |\n| `BILLING_INVOICE_NOT_FOUND` | 404 | actionable | The requested invoice was not found. |\n| `BILLING_INVOICE_NOT_PAYABLE` | 409 | terminal | This invoice cannot be paid or collected in its current state. |\n| `BILLING_NOT_AVAILABLE` | 403 | terminal | Billing is not available for development instances. |\n| `BLOCKCHAIN_CALL_FAILED` | 400 | retryable | The blockchain call could not be completed. Check the transaction details and try again. |\n| `BLOCKCHAIN_NETWORK_NOT_SUPPORTED` | 400 | terminal | This network or token combination is not supported for this operation. |\n| `BLOCKCHAIN_TOKEN_NOT_SUPPORTED` | 400 | actionable | This token is not supported for this instance type. Development instances settle in USDB; production instances settle in USDC or USDT. |\n| `BLOCKCHAIN_TX_FAILED` | 502 | retryable | The blockchain transaction failed. Try again, and contact support if the problem persists. |\n| `COMPLIANCE_CNAE_CONDITION_INVALID` | 400 | actionable | A CNAE condition can only be set on a Brazilian business customer. |\n| `COMPLIANCE_CNAE_CONDITION_STATE` | 409 | actionable | The CNAE condition is not in a state that allows this action. |\n| `COMPLIANCE_CNPJ_LOOKUP_FAILED` | 502 | retryable | The public CNPJ record could not be fetched. Try again later. |\n| `COMPLIANCE_RFI_IN_PROGRESS` | 409 | actionable | An information request is already in progress. Resolve it before continuing. |\n| `COMPLIANCE_RFI_INVALID` | 400 | actionable | The information request could not be processed. Check the submitted fields. |\n| `CUSTOMERS_ALREADY_APPROVED` | 409 | terminal | This customer is already approved. |\n| `CUSTOMERS_BUSINESS_ENHANCED_NOT_AVAILABLE` | 400 | terminal | Enhanced verification is not available for business customers. Use standard verification (kyc_type: standard) for businesses. |\n| `CUSTOMERS_COUNTRY_NOT_SUPPORTED` | 400 | terminal | This country is not supported for this operation. |\n| `CUSTOMERS_ENHANCED_KYC_REQUIRED` | 400 | actionable | Individuals from high-risk countries must use enhanced verification (kyc_type: enhanced); standard verification is not available for them. See https://www.blindpay.com/docs/kb/supported-countries for country tiers. |\n| `CUSTOMERS_ID_DOCUMENT_INVALID` | 400 | actionable | The identity document is not accepted for this customer. Provide a valid passport, national ID, or a driver license with a valid SSN or ITIN as the tax ID. |\n| `CUSTOMERS_INVALID_DATA` | 422 | actionable | The customer data was rejected by the banking provider. Check the highlighted fields and try again. |\n| `CUSTOMERS_INVALID_PHONE` | 400 | actionable | The phone number provided is not valid. Check the number and try again. |\n| `CUSTOMERS_INVALID_TAX_ID` | 400 | actionable | The tax ID provided is not valid. Check the value and try again. |\n| `CUSTOMERS_KYC_NOT_APPROVED` | 403 | actionable | This customer has not completed verification yet. Complete the verification before continuing. |\n| `CUSTOMERS_KYC_TYPE_NOT_AVAILABLE` | 400 | terminal | The requested verification type is not available for this customer. Use a supported verification type and try again. |\n| `CUSTOMERS_NAME_INVALID` | 400 | actionable | The name registered for this customer is not accepted. Review it and try again. |\n| `CUSTOMERS_NOT_FOUND` | 404 | actionable | The requested customer was not found. |\n| `CUSTOMERS_ONBOARDING_INCOMPLETE` | 400 | actionable | Onboarding is not complete yet. Finish the remaining steps before continuing. |\n| `CUSTOMERS_OWNERSHIP_INVALID` | 400 | actionable | The ownership information for this business customer is incomplete or inconsistent. Review the registered owners and try again. |\n| `CUSTOMERS_REJECTED_DOCUMENTS_LOCKED` | 409 | actionable | Documents of a rejected customer cannot be replaced, because updating a customer does not start a new verification. Create a new customer with the new documents instead. |\n| `DATA_INTEGRITY_ERROR` | 422 | terminal | This record could not be loaded because it contains invalid stored data. Contact support with the ID below. |\n| `FEES_NOT_FOUND` | 404 | actionable | The requested fee configuration was not found. |\n| `FEES_PARTNER_FEE_EXCEEDED` | 400 | actionable | The partner fee exceeds the allowed maximum for this transaction. |\n| `FILES_ANALYSIS_FAILED` | 502 | retryable | The document could not be analyzed. Try again, and contact support if the problem persists. |\n| `FILES_EMPTY` | 400 | actionable | The uploaded file is empty. Upload a valid file. |\n| `FILES_PAGE_LIMIT_EXCEEDED` | 400 | actionable | The document has too many pages. Upload a PDF with at most 150 pages, keeping only the pages that show the required information. |\n| `FILES_TOO_LARGE` | 400 | actionable | The file is too large. Upload a smaller file. |\n| `FILES_TYPE_NOT_ALLOWED` | 400 | actionable | This file type is not allowed. Upload a supported file type. |\n| `FILES_UNREADABLE` | 400 | actionable | We could not read the uploaded file. Check the file and try again. |\n| `FILES_URL_INVALID` | 400 | actionable | The file_url is not a BlindPay file URL. Pass the file_url returned by POST /upload. |\n| `INSTANCES_BLOCKED` | 403 | terminal | This account is blocked. Contact support for assistance. |\n| `INSTANCES_DEVELOPMENT_CREATION_DISABLED` | 403 | terminal | Creating development instances is temporarily disabled. Contact support if you need one. |\n| `INSTANCES_LIMIT_REACHED` | 400 | terminal | You reached the maximum number of instances allowed for your account. |\n| `INSTANCES_NOT_FOUND` | 404 | actionable | The requested instance was not found. |\n| `INSTANCES_ONBOARDING_ALREADY_COMPLETED` | 400 | terminal | This instance has already finished onboarding. |\n| `INSTANCES_ONBOARDING_ALREADY_SUBMITTED` | 400 | terminal | This application was already submitted and is under review, so it can no longer be changed. |\n| `INSTANCES_TAX_ID_ALREADY_ONBOARDED` | 400 | terminal | Your account already has an instance of this type onboarded with this tax id. Contact support if you need another one. |\n| `INTERNAL_ERROR` | 500 | retryable | Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists. |\n| `LIMITS_AMOUNT_OUT_OF_RANGE` | 400 | actionable | The amount is outside the allowed range. The message includes the allowed range. |\n| `LIMITS_VOLUME_EXCEEDED` | 400 | actionable | You exceeded your transaction volume limit. The message includes the remaining amount available. |\n| `PAYABLES_ALREADY_PAID_OR_EXPIRED` | 400 | terminal | This payment code was already paid or has expired and can no longer be paid. |\n| `PAYABLES_ALREADY_PAID_OR_IN_FLIGHT` | 400 | actionable | This payable is already being paid or was already paid. Only draft payables can be quoted; a failed or refunded attempt returns the payable to draft. |\n| `PAYABLES_AMOUNT_NEGATIVE` | 400 | actionable | The payable total (line items plus taxes minus discount) cannot be negative. |\n| `PAYABLES_BANK_ACCOUNT_INVALID` | 400 | actionable | The bank_account details on this invoice payable were rejected. Check the errors list for the field that failed. |\n| `PAYABLES_BOLETO_WOULD_BE_OVERDUE` | 400 | terminal | This boleto is due before the next banking day, so it can no longer be paid on time. Boletos do not clear on weekends or outside banking hours. |\n| `PAYABLES_CODE_UNRESOLVABLE` | 400 | actionable | We could not read this payment code. Check the code and try again. |\n| `PAYABLES_CURRENCY_MUST_BE_BRL` | 400 | actionable | Boleto and PIX payables must use BRL. |\n| `PAYABLES_DESTINATION_NOT_SUPPORTED` | 400 | terminal | Only boleto, arrecadação (utility/tax) and PIX QR code payables can be paid right now. Bank-destination invoice payables are not payable yet. |\n| `PAYABLES_DOCUMENT_INVALID` | 400 | terminal | document_file must be a URL returned by POST /upload with bucket `documents`, uploaded by this instance. |\n| `PAYABLES_DOCUMENT_NOT_ALLOWED_FOR_PIX` | 400 | terminal | PIX payables have no document. document_file is accepted only for boleto and bank-details payables. |\n| `PAYABLES_DUPLICATE` | 400 | actionable | This payment code already has a payable registered, in progress or completed for this instance. |\n| `PAYABLES_NETWORK_NOT_SUPPORTED` | 400 | terminal | Only EVM wallets can fund payables right now. |\n| `PAYABLES_NOT_CANCELABLE` | 400 | terminal | Only draft payables can be deleted. Once a payout is executing this payable it can no longer be canceled. |\n| `PAYABLES_NOT_FOUND` | 404 | terminal | This payable was not found. |\n| `PAYABLES_PIX_AMOUNT_REQUIRED` | 400 | terminal | This PIX code has no fixed amount and no amount was provided. Send the amount as line_items when registering a PIX code that lets the payer choose the value. |\n| `PAYABLES_REVIEW_STATE_INVALID` | 400 | terminal | This payable is not awaiting compliance review. |\n| `PAYINS_ALREADY_TERMINAL` | 409 | terminal | This payin already reached a final status and cannot be changed. |\n| `PAYINS_CARD_ALREADY_CHARGED` | 409 | terminal | A card charge attempt is already recorded for this payin. Each payin accepts exactly one card charge. |\n| `PAYINS_CARD_GATEWAY_ENVIRONMENT_MISMATCH` | 400 | terminal | Card payins are not available in this environment. Contact support. |\n| `PAYINS_CARD_PAYMENT_DECLINED` | 402 | actionable | The card payment was declined by the gateway or issuer. The payin is still open: tokenize the card again and retry, or use another card. |\n| `PAYINS_CARD_PAYMENT_PENDING` | 502 | terminal | The card charge outcome could not be confirmed with the gateway. Do not retry: the charge may have gone through. The gateway webhook or an operator resolves the final state. |\n| `PAYINS_CUSTOMER_USD_REGISTRATION_PENDING` | 400 | retryable | The customer is still being set up for US bank transfer payins (ACH, wire, RTP). Wait about a minute, then create a new payin quote and try again. |\n| `PAYINS_CUSTOMER_USD_REGISTRATION_REJECTED` | 400 | actionable | The customer could not be set up for US bank transfer payins (ACH, wire, RTP) because some of their details were rejected. Correct the tax_id or phone_number listed in errors with PUT /customers/{id}, create a new payin quote, wait about a minute, and try again. For any other reason, contact support with the trace_id. |\n| `PAYINS_FUNDING_ACCOUNT_INVALID` | 400 | actionable | The selected funding bank account cannot fund this payin. Use a Plaid-connected account that belongs to the same customer, on an ach_pull payin. |\n| `PAYINS_FUNDING_PULL_FAILED` | 502 | retryable | We could not debit the selected bank account. The payin was not started. Request a new quote and try again. |\n| `PAYINS_METHOD_NOT_SUPPORTED` | 400 | terminal | This payment method is not supported for this operation. |\n| `PAYINS_NOT_FOUND` | 404 | actionable | The requested payin was not found. |\n| `PAYINS_TAX_ID_REQUIRED` | 400 | actionable | A tax ID is required for this payment method. Provide the tax ID and try again. |\n| `PAYINS_VIRTUAL_ACCOUNT_REQUIRED` | 400 | actionable | International SWIFT payins require the receiver to have an approved virtual account. Create a virtual account for this receiver and try again. |\n| `PAYOUTS_ALLOWANCE_NOT_CONFIRMED` | 400 | retryable | The token approval for this payout has not been confirmed on-chain yet, or the approved amount is lower than the payout amount. Wait for the approval transaction to confirm and execute the quote again. |\n| `PAYOUTS_AMOUNT_BELOW_MINIMUM` | 400 | actionable | The amount is below the minimum for this payment rail. |\n| `PAYOUTS_BENEFICIARY_DETAILS_INVALID` | 400 | actionable | The payment rail rejected the beneficiary name or address on this bank account (for example, unsupported characters or an invalid format). Update the bank account details and try again. |\n| `PAYOUTS_DOCUMENTS_NOT_ACCEPTED` | 400 | terminal | A document cannot be submitted for this payout in its current state. |\n| `PAYOUTS_INSUFFICIENT_BALANCE` | 400 | actionable | There is not enough balance to complete this payout. Fund your balance and try again. |\n| `PAYOUTS_NOT_FOUND` | 404 | actionable | The requested payout was not found. |\n| `QUOTES_ALREADY_USED` | 409 | actionable | This quote was already used. Request a new quote. |\n| `QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM` | 400 | actionable | The amount is below the minimum the liquidity provider accepts for this pair. Try a larger amount. |\n| `QUOTES_AMOUNT_OUTSIDE_PROVIDER_LIMITS` | 400 | actionable | The amount is outside the limits accepted for this payment rail. Adjust the amount and try again. |\n| `QUOTES_EXPIRED` | 400 | actionable | This quote has expired. Request a new quote and try again. |\n| `QUOTES_INSUFFICIENT_LIQUIDITY` | 400 | actionable | There is not enough market liquidity to fill this amount right now. Try a smaller amount or try again later. |\n| `QUOTES_INVALID_STATE` | 400 | actionable | This quote cannot be authorized in its current state. Request a new quote and try again. |\n| `QUOTES_NOT_FOUND` | 404 | actionable | The requested quote was not found. |\n| `QUOTES_OTC_NOT_SUPPORTED` | 400 | actionable | This OTC configuration is not supported. OTC requires BRL with USDT, and either the sender amount with fees not covered, or the receiver amount with fees covered. |\n| `QUOTES_RATE_UNAVAILABLE` | 502 | retryable | An exchange rate is temporarily unavailable. Try again shortly. |\n| `REQUEST_REJECTED` | 400 | actionable | The request was rejected. Check the error message for details. |\n| `SSO_CONNECTIONS_CONFIGURATION_REJECTED` | 400 | actionable | The identity provider settings were rejected. Check them and try again. |\n| `SSO_CONNECTIONS_DOMAIN_IN_USE` | 400 | terminal | One of the email domains is already configured on another SSO connection. |\n| `SSO_CONNECTIONS_DOMAIN_NOT_OWNED` | 400 | terminal | Single sign-on can only route the email domain you sign in with. Contact support to add other domains. |\n| `SSO_CONNECTIONS_DOMAIN_NOT_VERIFIED` | 400 | actionable | Verify your email domain before turning single sign-on on. Add the DNS record shown on the page, then check it. |\n| `SSO_CONNECTIONS_DOMAIN_VERIFICATION_FAILED` | 400 | retryable | We could not find the DNS record for your domain yet. Check the record name and value, and try again in a few minutes. |\n| `SSO_CONNECTIONS_IDENTITY_PROVIDER_MISSING` | 400 | actionable | Connect your identity provider before turning single sign-on on. |\n| `SSO_CONNECTIONS_METADATA_UNREADABLE` | 400 | actionable | We could not read the identity provider metadata. Check the URL, or paste the metadata XML instead. |\n| `SSO_CONNECTIONS_NOT_ENABLED` | 403 | terminal | Single sign-on is not enabled for this instance. Contact support to turn it on. |\n| `SSO_CONNECTIONS_NOT_FOUND` | 404 | actionable | The requested SSO connection was not found. |\n| `SSO_CONNECTIONS_PROVIDER_FAILED` | 502 | retryable | We could not save the SSO connection with the identity service. Try again, and contact support if the problem persists. |\n| `TOS_ALREADY_ACCEPTED` | 409 | terminal | These terms of service were already accepted. |\n| `TOS_NOT_ACCEPTED` | 400 | actionable | The terms of service must be accepted before continuing. |\n| `TOS_NOT_FOUND` | 404 | actionable | The requested terms of service record was not found. |\n| `TOS_PASSTHROUGH_ATTESTATION_INVALID` | 400 | actionable | The acceptance data does not look like it was collected from the customer device. Send the public IP address and the User-Agent of the customer browser, right after the acceptance. |\n| `TOS_PASSTHROUGH_NOT_ENABLED` | 403 | terminal | Passthrough Terms of Service is not enabled for this instance. Contact support to enable it. |\n| `TOS_PASSTHROUGH_SETUP_INCOMPLETE` | 400 | actionable | Finish the passthrough Terms of Service setup in the instance settings: add the terms link and screenshot, then accept the partner agreement. |\n| `VALIDATION_FAILED` | 400 | actionable | The request contains invalid fields. Check the errors list for details. |\n| `VALIDATION_INVALID_REQUEST` | 400 | actionable | The request is not valid for this operation. Check the parameters and try again. |\n| `VALIDATION_MISSING_BODY` | 400 | actionable | The request body is missing or malformed. Send valid JSON with the Content-Type: application/json header. |\n| `VALIDATION_MISSING_REQUIRED_FIELDS` | 400 | actionable | Required fields are missing. Provide the missing fields and try again. |\n| `VIRTUAL_ACCOUNTS_DISABLED` | 403 | terminal | Virtual accounts are not enabled for this account. Contact support to enable them. |\n| `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED` | 400 | actionable | Additional documents are required to create this virtual account. Upload the requested documents. |\n| `VIRTUAL_ACCOUNTS_NOT_APPROVED` | 403 | actionable | This virtual account is not approved yet. |\n| `VIRTUAL_ACCOUNTS_NOT_FOUND` | 404 | actionable | The requested virtual account was not found. |\n| `VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE` | 400 | terminal | This banking partner is not available for this customer. Choose a different banking partner. |\n| `VIRTUAL_ACCOUNTS_PROVISION_FAILED` | 502 | retryable | We could not create the virtual account. Try again, and contact support if the problem persists. |\n| `VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED` | 400 | terminal | Virtual accounts are not available for this country or region. |\n| `WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT` | 400 | terminal | This wallet is attached to a virtual account and cannot be deleted. Delete the virtual account first. |\n| `WALLETS_BALANCE_UNAVAILABLE` | 503 | retryable | The wallet balance is temporarily unavailable. Try again shortly. |\n| `WALLETS_DEPOSIT_UNDER_REVIEW` | 400 | terminal | A deposit into this wallet is under compliance review. Transfers out of the wallet are paused until the review is resolved. |\n| `WALLETS_DESTINATION_SANCTIONED` | 400 | terminal | The destination wallet address is on a sanctions list. Funds cannot be sent to it. |\n| `WALLETS_HAS_FUNDS` | 400 | actionable | This wallet still holds funds. Transfer them out before deleting it. |\n| `WALLETS_LIMIT_REACHED` | 400 | terminal | You reached the maximum of 10 wallets for this customer. Delete an existing wallet first. |\n| `WALLETS_NOT_FOUND` | 404 | actionable | The requested wallet was not found. |\n| `WALLETS_NOT_OWNED_BY_CUSTOMER` | 400 | actionable | The selected wallet belongs to a different customer. Choose one of this customer's wallets. |\n| `WALLETS_SELF_CUSTODY_ALREADY_SET` | 409 | terminal | The self-custody answer for this wallet was already saved and cannot be changed. Contact support if it is wrong. |\n| `WALLETS_SELF_CUSTODY_REQUIRED` | 400 | actionable | Brazilian customers must declare whether the wallet is self-custodied. Send is_self_custody as true or false. |\n| `WEBHOOKS_ENDPOINT_NOT_FOUND` | 404 | actionable | The requested webhook endpoint was not found. |\n| `WEBHOOKS_LIMIT_REACHED` | 400 | terminal | You reached the maximum number of webhook endpoints. |\n| `WEBHOOKS_SIGNATURE_INVALID` | 401 | terminal | The webhook signature is missing or invalid. |\n| `WEBHOOKS_TRANSFORMATION_INVALID` | 400 | actionable | The transformation code is not valid JavaScript on its own. Check for unbalanced braces or an unclosed string. |\n| `WEBHOOKS_URL_INVALID` | 400 | actionable | The webhook URL is not valid. Use a reachable HTTPS URL. |\n| `YIELD_INVALID_STATE` | 409 | actionable | The wallet yield status is changing. Check the current yield_status and retry when it settles. |\n| `YIELD_NOT_AVAILABLE_FOR_NETWORK` | 400 | terminal | Yield is not available on this wallet network. |\n| `YIELD_NOT_ENABLED_FOR_INSTANCE` | 403 | terminal | Yield is not enabled for this account. Contact support to enable it. |\n| `YIELD_POSITION_UNAVAILABLE` | 503 | retryable | The wallet yield position is temporarily unavailable. Try again shortly. |\n| `YIELD_VAULT_IDENTITY_LOCKED` | 400 | terminal | This yield vault is referenced by transactions, so its address, network and token cannot be changed. |\n| `YIELD_WALLET_NOT_EMPTY` | 400 | actionable | This wallet still has funds earning yield. Disable yield and wait for it to settle before deleting the wallet. |\n" } ], "security": [ @@ -127,7 +130,103 @@ "stellar_testnet", "tron", "solana", - "solana_devnet" + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "polygon" + }, + "address": { + "type": [ + "string", + "null" + ], + "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + }, + "signature_tx_hash": { + "type": [ + "string", + "null" + ], + "example": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359" + }, + "is_account_abstraction": { + "type": [ + "boolean", + "null" + ], + "example": false + }, + "is_self_custody": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the customer holds the private keys of this wallet. Required for Brazilian customers (BCB Resolution 588). null means it was never answered; once set it cannot be changed.", + "example": true + }, + "customer_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + } + }, + "required": [ + "webhook_event", + "id", + "name", + "network", + "customer_id" + ] + }, + "BlockchainWalletUpdateWebhookOut": { + "type": "object", + "properties": { + "webhook_event": { + "type": "string", + "enum": [ + "blockchainWallet.update" + ] + }, + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bw_000000000000" + }, + "name": { + "type": [ + "string", + "null" + ], + "example": "Wallet Display Name" + }, + "network": { + "type": [ + "string", + "null" + ], + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" ], "example": "polygon" }, @@ -152,6 +251,14 @@ ], "example": false }, + "is_self_custody": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the customer holds the private keys of this wallet. Required for Brazilian customers (BCB Resolution 588). null means it was never answered; once set it cannot be changed.", + "example": true + }, "customer_id": { "type": "string", "minLength": 15, @@ -195,7 +302,8 @@ "ach_cop_bitso", "international_swift", "rtp", - "sepa" + "sepa", + "faster_payments" ], "example": "wire" }, @@ -664,7 +772,6 @@ "string", "null" ], - "maxLength": 50, "example": "John Doe" }, "swift_account_number_iban": { @@ -1566,6 +1673,25 @@ ], "example": "US" }, + "swift_intermediary_bank_routing_number": { + "anyOf": [ + { + "type": "string", + "enum": [ + "" + ] + }, + { + "type": "string", + "pattern": "^\\d{9}$" + }, + { + "type": "null" + } + ], + "description": "US ABA routing number of the correspondent bank, from the beneficiary bank USD wire instructions. Used by providers that require an explicit US correspondent for the SWIFT route.", + "example": "021000089" + }, "sepa_iban": { "type": [ "string", @@ -1882,6 +2008,323 @@ ], "example": "DE" }, + "faster_payments_sort_code": { + "type": [ + "string", + "null" + ], + "description": "UK bank sort code, 6 digits. Dashes and spaces are stripped.", + "example": "040004" + }, + "faster_payments_account_number": { + "type": [ + "string", + "null" + ], + "description": "UK bank account number, 8 digits.", + "example": "12345678" + }, + "faster_payments_beneficiary_legal_name": { + "type": [ + "string", + "null" + ], + "maxLength": 128, + "example": "Oliver Smith" + }, + "faster_payments_beneficiary_address_line_1": { + "type": [ + "string", + "null" + ], + "example": "221B Baker Street" + }, + "faster_payments_beneficiary_address_line_2": { + "type": [ + "string", + "null" + ], + "example": "Flat 2" + }, + "faster_payments_beneficiary_city": { + "type": [ + "string", + "null" + ], + "example": "London" + }, + "faster_payments_beneficiary_state_province_region": { + "type": [ + "string", + "null" + ], + "example": "Greater London" + }, + "faster_payments_beneficiary_postal_code": { + "type": [ + "string", + "null" + ], + "example": "NW1 6XE" + }, + "faster_payments_beneficiary_country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "GB" + }, "business_industry": { "type": [ "string", @@ -1892,7 +2335,26 @@ "112120", "113310", "115114", + "111120", + "111219", + "111336", + "111421", + "112111", + "112210", + "112310", + "112410", + "112519", + "112990", + "113110", + "113210", + "114119", + "114210", + "115113", + "115210", + "115310", "541211", + "541213", + "541219", "541810", "541430", "541715", @@ -1902,10 +2364,29 @@ "561612", "561740", "561730", + "532490", + "533110", + "541490", + "541690", + "541720", + "561110", + "561210", + "561611", + "561990", + "722310", "236115", "236220", "237310", "238210", + "236118", + "236210", + "237130", + "237210", + "237990", + "238191", + "238391", + "238991", + "541310", "811111", "812111", "812112", @@ -1914,16 +2395,40 @@ "541922", "811210", "812199", + "532289", + "532310", + "561790", + "811198", + "811310", + "811411", + "812210", + "812320", + "812990", + "814110", "611110", "611310", "611410", "611710", + "611210", + "611420", + "611519", + "611699", "211120", "212114", "221310", "562111", "562920", "213112", + "211130", + "212290", + "212390", + "213113", + "221122", + "221210", + "221320", + "324110", + "562211", + "562998", "522110", "522210", "522320", @@ -1931,10 +2436,34 @@ "523940", "523999", "524113", + "521110", + "522130", + "522298", + "522390", + "523210", + "524128", + "524298", + "525190", + "525910", "813110", "813211", "813219", + "624190", + "624230", + "624310", + "813319", + "813410", + "813930", + "921140", + "922190", + "923130", + "924110", + "925120", + "926110", + "927110", + "928110", "551112", + "551114", "721110", "722511", "722513", @@ -1944,6 +2473,20 @@ "712110", "711110", "711211", + "487110", + "487210", + "487990", + "561599", + "711190", + "711219", + "711310", + "712120", + "713290", + "713990", + "721199", + "721211", + "721310", + "722410", "621111", "621210", "622110", @@ -1953,7 +2496,16 @@ "541940", "621399", "621910", + "621498", + "621610", + "621999", + "622210", + "622310", + "623210", + "623311", + "623990", "541110", + "541199", "311421", "337121", "322220", @@ -1970,12 +2522,93 @@ "315990", "313110", "339910", + "311119", + "311212", + "311314", + "311422", + "311511", + "311612", + "311710", + "311811", + "311999", + "312111", + "312230", + "313240", + "313310", + "314120", + "314999", + "315120", + "315250", + "316110", + "316210", + "316990", + "321113", + "321211", + "321918", + "322120", + "322299", + "323120", + "325180", + "325220", + "325320", + "325510", + "325611", + "325998", + "326111", + "326220", + "327120", + "327212", + "327310", + "327410", + "327999", + "331110", + "331210", + "331313", + "331410", + "331511", + "332111", + "332215", + "332311", + "332410", + "332510", + "332613", + "332710", + "332812", + "332999", + "333111", + "333248", + "333310", + "333413", + "333517", + "333611", + "333618", + "334310", + "334413", + "334511", + "334610", + "335131", + "335220", + "335311", + "335999", + "336211", + "336412", + "336510", + "336611", + "336999", + "337122", + "337214", + "337920", + "339999", "516120", "513130", "512250", "519130", + "519290", "711410", "711510", + "512199", + "512290", + "515210", "531110", "531120", "531130", @@ -2001,14 +2634,32 @@ "424210", "456110", "446120", + "456120", + "441110", + "441227", + "441330", + "444180", + "444240", + "445132", + "445298", + "449110", + "449129", + "454390", + "458320", + "459310", + "459410", + "459510", + "459999", "541511", "541512", "541519", "518210", "511210", + "513210", "517111", "517112", "517410", + "517810", "481111", "483111", "485210", @@ -2026,6 +2677,43 @@ "424410", "424480", "423940", + "423120", + "423220", + "423310", + "423490", + "423520", + "423620", + "423710", + "423990", + "424110", + "424310", + "424490", + "424590", + "424720", + "424820", + "425120", + "481211", + "482111", + "483112", + "483212", + "484110", + "484220", + "485119", + "485310", + "485410", + "485510", + "485999", + "486110", + "486210", + "486990", + "488190", + "488210", + "488390", + "488490", + "488999", + "492110", + "492210", + "493190", "541611", "541618", "541330", @@ -2159,7 +2847,11 @@ "sepolia", "arbitrum_sepolia", "base_sepolia", - "polygon_amoy" + "polygon_amoy", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" ], "example": "tron" }, @@ -2539,6 +3231,9 @@ "in_swift_p0107", "in_swift_p0108", "in_swift_p0109", + "in_swift_p0304", + "in_swift_p1099", + "in_swift_p1108", "jp_swift_1001", "jp_swift_1002", "jp_swift_1003", @@ -3249,6 +3944,15 @@ ], "example": "bh_swift_afl" }, + "plaid_connected_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "When the bank account was verified through Plaid. Set means the account can fund an ach payin by pull.", + "example": "2021-01-01T00:00:00Z" + }, "created_at": { "type": [ "string", @@ -3332,6 +4036,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Complete step", @@ -3367,6 +4072,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payment step", @@ -3453,6 +4159,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payin transaction step", @@ -3511,8 +4218,9 @@ "Citi", "CFSB", "Triple A Technologies", + "BCB Group", "Portage Bank", - "SSB Bank" + "NMI" ], "description": "Payment provider name", "example": "HSBC" @@ -3602,8 +4310,24 @@ }, "fid": { "type": "string", - "description": "PSE funding identifier for webhook matching", - "example": "fid_abc123" + "description": "PSE provider reference used for webhook matching (the payin intent id)", + "example": "be6185ad-afdf-d682-2ca7-d447250f5e96" + }, + "payin_intent_id": { + "type": [ + "string", + "null" + ], + "description": "PSE payin intent id at the provider", + "example": "be6185ad-afdf-d682-2ca7-d447250f5e96" + }, + "expires_at": { + "type": [ + "string", + "null" + ], + "description": "When the PSE payment link expires", + "example": "2026-02-26T23:59:59Z" }, "full_name": { "type": "string", @@ -3680,7 +4404,7 @@ "null" ], "description": "CUIT/CUIL (normalized, digits only)", - "example": "20123456783" + "example": "20123456786" } }, "required": [ @@ -3732,6 +4456,116 @@ "account_number", "account_type" ] + }, + "card_instruction": { + "type": [ + "object", + "null" + ], + "properties": { + "provider": { + "type": "string", + "description": "Which card gateway issued the tokenization key, so the checkout knows which tokenization library to load.", + "example": "nmi" + }, + "tokenization_key": { + "type": "string", + "description": "NMI Collect.js public tokenization key. Load https://secure.nmi.com/token/Collect.js with this key, tokenize the card in the browser, and submit the payment_token to the card-payment endpoint.", + "example": "KXypee-Vq3y2f-K6c7Dy-Wq92R5" + } + }, + "required": [ + "provider", + "tokenization_key" + ] + }, + "card_evidence": { + "type": [ + "object", + "null" + ], + "properties": { + "eci": { + "type": [ + "string", + "null" + ], + "description": "3DS ECI value returned by payer authentication", + "example": "05" + }, + "cavv": { + "type": [ + "string", + "null" + ], + "description": "3DS cardholder authentication verification value", + "example": "AAABBWcSNIdjeUZThmNHAAAAAAA=" + }, + "avs_response": { + "type": [ + "string", + "null" + ], + "description": "Gateway AVS result code", + "example": "Y" + }, + "cvv_response": { + "type": [ + "string", + "null" + ], + "description": "Gateway CVV result code", + "example": "M" + }, + "auth_code": { + "type": [ + "string", + "null" + ], + "description": "Issuer authorization code", + "example": "123456" + }, + "cardholder_name": { + "type": [ + "string", + "null" + ], + "description": "Cardholder name as submitted with the charge", + "example": "Jane Doe" + }, + "three_ds_version": { + "type": [ + "string", + "null" + ], + "description": "3DS protocol version used", + "example": "2.2.0" + } + } + }, + "card_failed_attempts": { + "type": [ + "integer", + "null" + ], + "description": "How many card charge attempts on this payin were declined. A payin stops accepting charges after the limit.", + "example": 0 + }, + "card_claim_at": { + "type": [ + "string", + "null" + ], + "description": "Set while a card charge attempt is in flight for this payin; guards against a double charge (NMI has no idempotency key).", + "example": null + }, + "card_gates_failed_at": { + "type": [ + "string", + "null" + ], + "description": "Set when an approved card sale failed the post-capture risk gates (CVV/AVS) and was voided; blocks any later confirmation of that charge.", + "example": null } }, "required": [ @@ -3743,7 +4577,7 @@ "number", "null" ], - "description": "Billing fee in cents (charged at the end of the month)", + "description": "BlindPay fee in cents accrued to your billing cycle (charged at the end of the month). Virtual account deposits below $100.00 always accrue here, so small deposits are delivered in full.", "example": 50 }, "transaction_fee_amount": { @@ -3751,7 +4585,7 @@ "number", "null" ], - "description": "Transaction fee in cents (percentage-based fee)", + "description": "BlindPay fee in cents deducted from the transaction at the time it is processed. Virtual account deposits of $100.00 or more are charged here (unless your instance is configured for end-of-month billing, in which case every fee accrues to billing_fee_amount).", "example": 100 }, "blindpay_bank_details": { @@ -3946,12 +4780,15 @@ ], "enum": [ "ach", + "ach_pull", "wire", "pix", + "card", "ted", "spei", "transfers", "pse", + "bre_b", "international_swift", "rtp" ], @@ -4043,6 +4880,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Complete step", @@ -4078,6 +4916,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payment step", @@ -4164,6 +5003,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payin transaction step", @@ -4222,8 +5062,9 @@ "Citi", "CFSB", "Triple A Technologies", + "BCB Group", "Portage Bank", - "SSB Bank" + "NMI" ], "description": "Payment provider name", "example": "HSBC" @@ -4313,8 +5154,24 @@ }, "fid": { "type": "string", - "description": "PSE funding identifier for webhook matching", - "example": "fid_abc123" + "description": "PSE provider reference used for webhook matching (the payin intent id)", + "example": "be6185ad-afdf-d682-2ca7-d447250f5e96" + }, + "payin_intent_id": { + "type": [ + "string", + "null" + ], + "description": "PSE payin intent id at the provider", + "example": "be6185ad-afdf-d682-2ca7-d447250f5e96" + }, + "expires_at": { + "type": [ + "string", + "null" + ], + "description": "When the PSE payment link expires", + "example": "2026-02-26T23:59:59Z" }, "full_name": { "type": "string", @@ -4391,7 +5248,7 @@ "null" ], "description": "CUIT/CUIL (normalized, digits only)", - "example": "20123456783" + "example": "20123456786" } }, "required": [ @@ -4443,6 +5300,116 @@ "account_number", "account_type" ] + }, + "card_instruction": { + "type": [ + "object", + "null" + ], + "properties": { + "provider": { + "type": "string", + "description": "Which card gateway issued the tokenization key, so the checkout knows which tokenization library to load.", + "example": "nmi" + }, + "tokenization_key": { + "type": "string", + "description": "NMI Collect.js public tokenization key. Load https://secure.nmi.com/token/Collect.js with this key, tokenize the card in the browser, and submit the payment_token to the card-payment endpoint.", + "example": "KXypee-Vq3y2f-K6c7Dy-Wq92R5" + } + }, + "required": [ + "provider", + "tokenization_key" + ] + }, + "card_evidence": { + "type": [ + "object", + "null" + ], + "properties": { + "eci": { + "type": [ + "string", + "null" + ], + "description": "3DS ECI value returned by payer authentication", + "example": "05" + }, + "cavv": { + "type": [ + "string", + "null" + ], + "description": "3DS cardholder authentication verification value", + "example": "AAABBWcSNIdjeUZThmNHAAAAAAA=" + }, + "avs_response": { + "type": [ + "string", + "null" + ], + "description": "Gateway AVS result code", + "example": "Y" + }, + "cvv_response": { + "type": [ + "string", + "null" + ], + "description": "Gateway CVV result code", + "example": "M" + }, + "auth_code": { + "type": [ + "string", + "null" + ], + "description": "Issuer authorization code", + "example": "123456" + }, + "cardholder_name": { + "type": [ + "string", + "null" + ], + "description": "Cardholder name as submitted with the charge", + "example": "Jane Doe" + }, + "three_ds_version": { + "type": [ + "string", + "null" + ], + "description": "3DS protocol version used", + "example": "2.2.0" + } + } + }, + "card_failed_attempts": { + "type": [ + "integer", + "null" + ], + "description": "How many card charge attempts on this payin were declined. A payin stops accepting charges after the limit.", + "example": 0 + }, + "card_claim_at": { + "type": [ + "string", + "null" + ], + "description": "Set while a card charge attempt is in flight for this payin; guards against a double charge (NMI has no idempotency key).", + "example": null + }, + "card_gates_failed_at": { + "type": [ + "string", + "null" + ], + "description": "Set when an approved card sale failed the post-capture risk gates (CVV/AVS) and was voided; blocks any later confirmation of that charge.", + "example": null } }, "required": [ @@ -4454,7 +5421,7 @@ "number", "null" ], - "description": "Billing fee in cents (charged at the end of the month)", + "description": "BlindPay fee in cents accrued to your billing cycle (charged at the end of the month). Virtual account deposits below $100.00 always accrue here, so small deposits are delivered in full.", "example": 50 }, "transaction_fee_amount": { @@ -4462,7 +5429,7 @@ "number", "null" ], - "description": "Transaction fee in cents (percentage-based fee)", + "description": "BlindPay fee in cents deducted from the transaction at the time it is processed. Virtual account deposits of $100.00 or more are charged here (unless your instance is configured for end-of-month billing, in which case every fee accrues to billing_fee_amount).", "example": 100 }, "blindpay_bank_details": { @@ -4657,12 +5624,15 @@ ], "enum": [ "ach", + "ach_pull", "wire", "pix", + "card", "ted", "spei", "transfers", "pse", + "bre_b", "international_swift", "rtp" ], @@ -4687,83 +5657,11 @@ "blindpay_bank_details" ] }, - "LimitIncreaseNewWebhookOut": { + "LimitIncreaseSupportingDocument": { "type": "object", "properties": { - "webhook_event": { - "type": "string", - "enum": [ - "limitIncrease.new" - ] - }, - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "rl_000000000000" - }, - "status": { + "type": { "type": "string", - "enum": [ - "in_review", - "approved", - "rejected" - ], - "example": "in_review" - }, - "per_transaction": { - "type": [ - "integer", - "null" - ], - "maximum": 100000000000, - "example": 100000 - }, - "daily": { - "type": [ - "integer", - "null" - ], - "maximum": 100000000000, - "example": 200000 - }, - "monthly": { - "type": [ - "integer", - "null" - ], - "maximum": 100000000000, - "example": 1000000 - }, - "approved_per_transaction": { - "type": [ - "integer", - "null" - ], - "maximum": 100000000000, - "example": 70000 - }, - "approved_daily": { - "type": [ - "integer", - "null" - ], - "maximum": 100000000000, - "example": 140000 - }, - "approved_monthly": { - "type": [ - "integer", - "null" - ], - "maximum": 100000000000, - "example": 700000 - }, - "supporting_document_type": { - "type": [ - "string", - "null" - ], "enum": [ "individual_bank_statement", "individual_tax_return", @@ -4783,51 +5681,24 @@ ], "example": "individual_bank_statement" }, - "supporting_document_file": { - "type": [ - "string", - "null" - ], + "file": { + "type": "string", "format": "uri", "example": "https://example.com/document.pdf" - }, - "customer_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" - }, - "created_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" - }, - "updated_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" } }, "required": [ - "webhook_event", - "id", - "status", - "customer_id" + "type", + "file" ] }, - "LimitIncreaseUpdateWebhookOut": { + "LimitIncreaseNewWebhookOut": { "type": "object", "properties": { "webhook_event": { "type": "string", "enum": [ - "limitIncrease.update" + "limitIncrease.new" ] }, "id": { @@ -4925,6 +5796,164 @@ "format": "uri", "example": "https://example.com/document.pdf" }, + "supporting_documents": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/components/schemas/LimitIncreaseSupportingDocument" + }, + "minItems": 1, + "maxItems": 5, + "description": "Every supporting document attached to the request, up to 5. The first one is mirrored in supporting_document_type and supporting_document_file." + }, + "customer_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "created_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + }, + "updated_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + } + }, + "required": [ + "webhook_event", + "id", + "status", + "customer_id" + ] + }, + "LimitIncreaseUpdateWebhookOut": { + "type": "object", + "properties": { + "webhook_event": { + "type": "string", + "enum": [ + "limitIncrease.update" + ] + }, + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "rl_000000000000" + }, + "status": { + "type": "string", + "enum": [ + "in_review", + "approved", + "rejected" + ], + "example": "in_review" + }, + "per_transaction": { + "type": [ + "integer", + "null" + ], + "maximum": 100000000000, + "example": 100000 + }, + "daily": { + "type": [ + "integer", + "null" + ], + "maximum": 100000000000, + "example": 200000 + }, + "monthly": { + "type": [ + "integer", + "null" + ], + "maximum": 100000000000, + "example": 1000000 + }, + "approved_per_transaction": { + "type": [ + "integer", + "null" + ], + "maximum": 100000000000, + "example": 70000 + }, + "approved_daily": { + "type": [ + "integer", + "null" + ], + "maximum": 100000000000, + "example": 140000 + }, + "approved_monthly": { + "type": [ + "integer", + "null" + ], + "maximum": 100000000000, + "example": 700000 + }, + "supporting_document_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "individual_bank_statement", + "individual_tax_return", + "individual_proof_of_income", + "individual_pay_stub", + "individual_employment_letter", + "individual_investment_statement", + "individual_crypto_exchange_statement", + "individual_blockchain_wallet_statement", + "business_bank_statement", + "business_financial_statements", + "business_tax_return", + "business_contract", + "business_accounts_receivable", + "business_merchant_processor_statement", + "business_shareholder_loan" + ], + "example": "individual_bank_statement" + }, + "supporting_document_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "example": "https://example.com/document.pdf" + }, + "supporting_documents": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/components/schemas/LimitIncreaseSupportingDocument" + }, + "minItems": 1, + "maxItems": 5, + "description": "Every supporting document attached to the request, up to 5. The first one is mirrored in supporting_document_type and supporting_document_file." + }, "customer_id": { "type": "string", "minLength": 15, @@ -5022,6 +6051,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Complete step", @@ -5057,6 +6087,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payment step", @@ -5143,6 +6174,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payin transaction step", @@ -5201,8 +6233,9 @@ "Citi", "CFSB", "Triple A Technologies", + "BCB Group", "Portage Bank", - "SSB Bank" + "NMI" ], "description": "Payment provider name", "example": "HSBC" @@ -5292,8 +6325,24 @@ }, "fid": { "type": "string", - "description": "PSE funding identifier for webhook matching", - "example": "fid_abc123" + "description": "PSE provider reference used for webhook matching (the payin intent id)", + "example": "be6185ad-afdf-d682-2ca7-d447250f5e96" + }, + "payin_intent_id": { + "type": [ + "string", + "null" + ], + "description": "PSE payin intent id at the provider", + "example": "be6185ad-afdf-d682-2ca7-d447250f5e96" + }, + "expires_at": { + "type": [ + "string", + "null" + ], + "description": "When the PSE payment link expires", + "example": "2026-02-26T23:59:59Z" }, "full_name": { "type": "string", @@ -5370,7 +6419,7 @@ "null" ], "description": "CUIT/CUIL (normalized, digits only)", - "example": "20123456783" + "example": "20123456786" } }, "required": [ @@ -5422,6 +6471,116 @@ "account_number", "account_type" ] + }, + "card_instruction": { + "type": [ + "object", + "null" + ], + "properties": { + "provider": { + "type": "string", + "description": "Which card gateway issued the tokenization key, so the checkout knows which tokenization library to load.", + "example": "nmi" + }, + "tokenization_key": { + "type": "string", + "description": "NMI Collect.js public tokenization key. Load https://secure.nmi.com/token/Collect.js with this key, tokenize the card in the browser, and submit the payment_token to the card-payment endpoint.", + "example": "KXypee-Vq3y2f-K6c7Dy-Wq92R5" + } + }, + "required": [ + "provider", + "tokenization_key" + ] + }, + "card_evidence": { + "type": [ + "object", + "null" + ], + "properties": { + "eci": { + "type": [ + "string", + "null" + ], + "description": "3DS ECI value returned by payer authentication", + "example": "05" + }, + "cavv": { + "type": [ + "string", + "null" + ], + "description": "3DS cardholder authentication verification value", + "example": "AAABBWcSNIdjeUZThmNHAAAAAAA=" + }, + "avs_response": { + "type": [ + "string", + "null" + ], + "description": "Gateway AVS result code", + "example": "Y" + }, + "cvv_response": { + "type": [ + "string", + "null" + ], + "description": "Gateway CVV result code", + "example": "M" + }, + "auth_code": { + "type": [ + "string", + "null" + ], + "description": "Issuer authorization code", + "example": "123456" + }, + "cardholder_name": { + "type": [ + "string", + "null" + ], + "description": "Cardholder name as submitted with the charge", + "example": "Jane Doe" + }, + "three_ds_version": { + "type": [ + "string", + "null" + ], + "description": "3DS protocol version used", + "example": "2.2.0" + } + } + }, + "card_failed_attempts": { + "type": [ + "integer", + "null" + ], + "description": "How many card charge attempts on this payin were declined. A payin stops accepting charges after the limit.", + "example": 0 + }, + "card_claim_at": { + "type": [ + "string", + "null" + ], + "description": "Set while a card charge attempt is in flight for this payin; guards against a double charge (NMI has no idempotency key).", + "example": null + }, + "card_gates_failed_at": { + "type": [ + "string", + "null" + ], + "description": "Set when an approved card sale failed the post-capture risk gates (CVV/AVS) and was voided; blocks any later confirmation of that charge.", + "example": null } }, "required": [ @@ -5433,7 +6592,7 @@ "number", "null" ], - "description": "Billing fee in cents (charged at the end of the month)", + "description": "BlindPay fee in cents accrued to your billing cycle (charged at the end of the month). Virtual account deposits below $100.00 always accrue here, so small deposits are delivered in full.", "example": 50 }, "transaction_fee_amount": { @@ -5441,7 +6600,7 @@ "number", "null" ], - "description": "Transaction fee in cents (percentage-based fee)", + "description": "BlindPay fee in cents deducted from the transaction at the time it is processed. Virtual account deposits of $100.00 or more are charged here (unless your instance is configured for end-of-month billing, in which case every fee accrues to billing_fee_amount).", "example": 100 }, "blindpay_bank_details": { @@ -5636,12 +6795,15 @@ ], "enum": [ "ach", + "ach_pull", "wire", "pix", + "card", "ted", "spei", "transfers", "pse", + "bre_b", "international_swift", "rtp" ], @@ -5733,6 +6895,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Complete step", @@ -5768,6 +6931,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payment step", @@ -5854,6 +7018,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payin transaction step", @@ -5912,8 +7077,9 @@ "Citi", "CFSB", "Triple A Technologies", + "BCB Group", "Portage Bank", - "SSB Bank" + "NMI" ], "description": "Payment provider name", "example": "HSBC" @@ -6003,8 +7169,24 @@ }, "fid": { "type": "string", - "description": "PSE funding identifier for webhook matching", - "example": "fid_abc123" + "description": "PSE provider reference used for webhook matching (the payin intent id)", + "example": "be6185ad-afdf-d682-2ca7-d447250f5e96" + }, + "payin_intent_id": { + "type": [ + "string", + "null" + ], + "description": "PSE payin intent id at the provider", + "example": "be6185ad-afdf-d682-2ca7-d447250f5e96" + }, + "expires_at": { + "type": [ + "string", + "null" + ], + "description": "When the PSE payment link expires", + "example": "2026-02-26T23:59:59Z" }, "full_name": { "type": "string", @@ -6081,7 +7263,7 @@ "null" ], "description": "CUIT/CUIL (normalized, digits only)", - "example": "20123456783" + "example": "20123456786" } }, "required": [ @@ -6133,6 +7315,116 @@ "account_number", "account_type" ] + }, + "card_instruction": { + "type": [ + "object", + "null" + ], + "properties": { + "provider": { + "type": "string", + "description": "Which card gateway issued the tokenization key, so the checkout knows which tokenization library to load.", + "example": "nmi" + }, + "tokenization_key": { + "type": "string", + "description": "NMI Collect.js public tokenization key. Load https://secure.nmi.com/token/Collect.js with this key, tokenize the card in the browser, and submit the payment_token to the card-payment endpoint.", + "example": "KXypee-Vq3y2f-K6c7Dy-Wq92R5" + } + }, + "required": [ + "provider", + "tokenization_key" + ] + }, + "card_evidence": { + "type": [ + "object", + "null" + ], + "properties": { + "eci": { + "type": [ + "string", + "null" + ], + "description": "3DS ECI value returned by payer authentication", + "example": "05" + }, + "cavv": { + "type": [ + "string", + "null" + ], + "description": "3DS cardholder authentication verification value", + "example": "AAABBWcSNIdjeUZThmNHAAAAAAA=" + }, + "avs_response": { + "type": [ + "string", + "null" + ], + "description": "Gateway AVS result code", + "example": "Y" + }, + "cvv_response": { + "type": [ + "string", + "null" + ], + "description": "Gateway CVV result code", + "example": "M" + }, + "auth_code": { + "type": [ + "string", + "null" + ], + "description": "Issuer authorization code", + "example": "123456" + }, + "cardholder_name": { + "type": [ + "string", + "null" + ], + "description": "Cardholder name as submitted with the charge", + "example": "Jane Doe" + }, + "three_ds_version": { + "type": [ + "string", + "null" + ], + "description": "3DS protocol version used", + "example": "2.2.0" + } + } + }, + "card_failed_attempts": { + "type": [ + "integer", + "null" + ], + "description": "How many card charge attempts on this payin were declined. A payin stops accepting charges after the limit.", + "example": 0 + }, + "card_claim_at": { + "type": [ + "string", + "null" + ], + "description": "Set while a card charge attempt is in flight for this payin; guards against a double charge (NMI has no idempotency key).", + "example": null + }, + "card_gates_failed_at": { + "type": [ + "string", + "null" + ], + "description": "Set when an approved card sale failed the post-capture risk gates (CVV/AVS) and was voided; blocks any later confirmation of that charge.", + "example": null } }, "required": [ @@ -6144,7 +7436,7 @@ "number", "null" ], - "description": "Billing fee in cents (charged at the end of the month)", + "description": "BlindPay fee in cents accrued to your billing cycle (charged at the end of the month). Virtual account deposits below $100.00 always accrue here, so small deposits are delivered in full.", "example": 50 }, "transaction_fee_amount": { @@ -6152,7 +7444,7 @@ "number", "null" ], - "description": "Transaction fee in cents (percentage-based fee)", + "description": "BlindPay fee in cents deducted from the transaction at the time it is processed. Virtual account deposits of $100.00 or more are charged here (unless your instance is configured for end-of-month billing, in which case every fee accrues to billing_fee_amount).", "example": 100 }, "blindpay_bank_details": { @@ -6347,12 +7639,15 @@ ], "enum": [ "ach", + "ach_pull", "wire", "pix", + "card", "ted", "spei", "transfers", "pse", + "bre_b", "international_swift", "rtp" ], @@ -6390,7 +7685,7 @@ "type": "string", "minLength": 15, "maxLength": 15, - "example": "pa_000000000000" + "example": "po_000000000000" }, "status": { "type": "string", @@ -6441,6 +7736,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Complete step", @@ -6504,6 +7800,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payment step", @@ -6526,8 +7823,9 @@ "Citi", "CFSB", "Triple A Technologies", + "BCB Group", "Portage Bank", - "SSB Bank" + "NMI" ], "description": "Payment provider name", "example": "HSBC" @@ -6545,7 +7843,8 @@ "bitso", "starkbank", "triplea", - "infinitus" + "infinitus", + "portage_g" ], "description": "Machine-readable integration that executed the fiat leg. Unlike provider_name (a client-facing bank label), this uniquely identifies the integration — e.g. zenus vs checkbook, which share the \"JPMorgan Chase\" label.", "example": "zenus" @@ -6580,6 +7879,15 @@ "description": "Provider error reason when payment fails (e.g. invalid_key, wrong_parameters)", "example": "invalid_key" }, + "returned_amount": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "Amount (in cents of the payout currency) the beneficiary bank sent back after the payment was delivered. May be lower than the amount sent when the return is partial.", + "example": 5000 + }, "provider_uetr": { "type": [ "string", @@ -6616,6 +7924,19 @@ "description": "Clearing system that processed the payment (e.g. FED, CHIPS, ACH, SWIFT).", "example": "FED" }, + "forced_provider": { + "type": [ + "string", + "null" + ], + "enum": [ + "zenus", + "veem", + "infinitus_portage" + ], + "description": "Ops-set per-payout provider override (backoffice Reroute tab). When present it wins over the instance payment_route and default routing at send time. Left in place after the send as an audit marker of the forced route.", + "example": "veem" + }, "recipient_name": { "type": [ "string", @@ -6704,6 +8025,69 @@ ], "description": "Payment completed date", "example": "2011-10-05T14:48:00.000Z" + }, + "refund_review_reason": { + "type": [ + "string", + "null" + ], + "enum": [ + "amount_threshold", + "time_window", + "late_cancellation_no_live_run", + "master_account_return", + "policy_always_review", + "operator_requested", + "partial_return" + ], + "description": "Why the payout was routed to the Pending Refunds review queue instead of auto-refunding after a provider cancellation", + "example": "amount_threshold" + }, + "refund_review_detected_at": { + "type": [ + "string", + "null" + ], + "description": "When the provider cancellation was routed to the Pending Refunds review queue", + "example": "2011-10-05T14:48:00.000Z" + }, + "refund_review_actioned_at": { + "type": [ + "string", + "null" + ], + "description": "Atomic claim marker: set the moment an operator approves a Pending Refunds entry, before the refund is sent, so a concurrent approve call cannot re-claim the same payout", + "example": "2011-10-05T14:48:00.000Z" + }, + "review_source": { + "type": [ + "string", + "null" + ], + "description": "Primary risk source that sent this payout to manual review", + "example": "nested_third_party" + }, + "review_sources": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Every risk source that sent this payout to manual review", + "example": [ + "nested_third_party", + "seon_review" + ] + }, + "review_context": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "Structured risk context for manual review" } }, "required": [ @@ -6719,6 +8103,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payout transaction step", @@ -6799,6 +8184,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payout liquidity step", @@ -6867,6 +8253,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Documents step", @@ -6931,6 +8318,16 @@ "minLength": 15, "maxLength": 15, "example": "ow_000000000000" + }, + "payable_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "description": "The payable this payout executes, when it pays a payable instead of a bank account.", + "example": "pb_000000000000" } }, "required": [ @@ -6956,7 +8353,7 @@ "type": "string", "minLength": 15, "maxLength": 15, - "example": "pa_000000000000" + "example": "po_000000000000" }, "status": { "type": "string", @@ -7007,6 +8404,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Complete step", @@ -7070,6 +8468,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payment step", @@ -7092,8 +8491,9 @@ "Citi", "CFSB", "Triple A Technologies", + "BCB Group", "Portage Bank", - "SSB Bank" + "NMI" ], "description": "Payment provider name", "example": "HSBC" @@ -7111,7 +8511,8 @@ "bitso", "starkbank", "triplea", - "infinitus" + "infinitus", + "portage_g" ], "description": "Machine-readable integration that executed the fiat leg. Unlike provider_name (a client-facing bank label), this uniquely identifies the integration — e.g. zenus vs checkbook, which share the \"JPMorgan Chase\" label.", "example": "zenus" @@ -7146,6 +8547,15 @@ "description": "Provider error reason when payment fails (e.g. invalid_key, wrong_parameters)", "example": "invalid_key" }, + "returned_amount": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "Amount (in cents of the payout currency) the beneficiary bank sent back after the payment was delivered. May be lower than the amount sent when the return is partial.", + "example": 5000 + }, "provider_uetr": { "type": [ "string", @@ -7182,6 +8592,19 @@ "description": "Clearing system that processed the payment (e.g. FED, CHIPS, ACH, SWIFT).", "example": "FED" }, + "forced_provider": { + "type": [ + "string", + "null" + ], + "enum": [ + "zenus", + "veem", + "infinitus_portage" + ], + "description": "Ops-set per-payout provider override (backoffice Reroute tab). When present it wins over the instance payment_route and default routing at send time. Left in place after the send as an audit marker of the forced route.", + "example": "veem" + }, "recipient_name": { "type": [ "string", @@ -7270,6 +8693,69 @@ ], "description": "Payment completed date", "example": "2011-10-05T14:48:00.000Z" + }, + "refund_review_reason": { + "type": [ + "string", + "null" + ], + "enum": [ + "amount_threshold", + "time_window", + "late_cancellation_no_live_run", + "master_account_return", + "policy_always_review", + "operator_requested", + "partial_return" + ], + "description": "Why the payout was routed to the Pending Refunds review queue instead of auto-refunding after a provider cancellation", + "example": "amount_threshold" + }, + "refund_review_detected_at": { + "type": [ + "string", + "null" + ], + "description": "When the provider cancellation was routed to the Pending Refunds review queue", + "example": "2011-10-05T14:48:00.000Z" + }, + "refund_review_actioned_at": { + "type": [ + "string", + "null" + ], + "description": "Atomic claim marker: set the moment an operator approves a Pending Refunds entry, before the refund is sent, so a concurrent approve call cannot re-claim the same payout", + "example": "2011-10-05T14:48:00.000Z" + }, + "review_source": { + "type": [ + "string", + "null" + ], + "description": "Primary risk source that sent this payout to manual review", + "example": "nested_third_party" + }, + "review_sources": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Every risk source that sent this payout to manual review", + "example": [ + "nested_third_party", + "seon_review" + ] + }, + "review_context": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "Structured risk context for manual review" } }, "required": [ @@ -7285,6 +8771,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payout transaction step", @@ -7365,6 +8852,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payout liquidity step", @@ -7433,6 +8921,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Documents step", @@ -7497,6 +8986,16 @@ "minLength": 15, "maxLength": 15, "example": "ow_000000000000" + }, + "payable_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "description": "The payable this payout executes, when it pays a payable instead of a bank account.", + "example": "pb_000000000000" } }, "required": [ @@ -7522,7 +9021,7 @@ "type": "string", "minLength": 15, "maxLength": 15, - "example": "pa_000000000000" + "example": "po_000000000000" }, "status": { "type": "string", @@ -7573,6 +9072,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Complete step", @@ -7636,6 +9136,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payment step", @@ -7658,8 +9159,9 @@ "Citi", "CFSB", "Triple A Technologies", + "BCB Group", "Portage Bank", - "SSB Bank" + "NMI" ], "description": "Payment provider name", "example": "HSBC" @@ -7677,7 +9179,8 @@ "bitso", "starkbank", "triplea", - "infinitus" + "infinitus", + "portage_g" ], "description": "Machine-readable integration that executed the fiat leg. Unlike provider_name (a client-facing bank label), this uniquely identifies the integration — e.g. zenus vs checkbook, which share the \"JPMorgan Chase\" label.", "example": "zenus" @@ -7712,6 +9215,15 @@ "description": "Provider error reason when payment fails (e.g. invalid_key, wrong_parameters)", "example": "invalid_key" }, + "returned_amount": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "Amount (in cents of the payout currency) the beneficiary bank sent back after the payment was delivered. May be lower than the amount sent when the return is partial.", + "example": 5000 + }, "provider_uetr": { "type": [ "string", @@ -7748,6 +9260,19 @@ "description": "Clearing system that processed the payment (e.g. FED, CHIPS, ACH, SWIFT).", "example": "FED" }, + "forced_provider": { + "type": [ + "string", + "null" + ], + "enum": [ + "zenus", + "veem", + "infinitus_portage" + ], + "description": "Ops-set per-payout provider override (backoffice Reroute tab). When present it wins over the instance payment_route and default routing at send time. Left in place after the send as an audit marker of the forced route.", + "example": "veem" + }, "recipient_name": { "type": [ "string", @@ -7836,6 +9361,69 @@ ], "description": "Payment completed date", "example": "2011-10-05T14:48:00.000Z" + }, + "refund_review_reason": { + "type": [ + "string", + "null" + ], + "enum": [ + "amount_threshold", + "time_window", + "late_cancellation_no_live_run", + "master_account_return", + "policy_always_review", + "operator_requested", + "partial_return" + ], + "description": "Why the payout was routed to the Pending Refunds review queue instead of auto-refunding after a provider cancellation", + "example": "amount_threshold" + }, + "refund_review_detected_at": { + "type": [ + "string", + "null" + ], + "description": "When the provider cancellation was routed to the Pending Refunds review queue", + "example": "2011-10-05T14:48:00.000Z" + }, + "refund_review_actioned_at": { + "type": [ + "string", + "null" + ], + "description": "Atomic claim marker: set the moment an operator approves a Pending Refunds entry, before the refund is sent, so a concurrent approve call cannot re-claim the same payout", + "example": "2011-10-05T14:48:00.000Z" + }, + "review_source": { + "type": [ + "string", + "null" + ], + "description": "Primary risk source that sent this payout to manual review", + "example": "nested_third_party" + }, + "review_sources": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Every risk source that sent this payout to manual review", + "example": [ + "nested_third_party", + "seon_review" + ] + }, + "review_context": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "Structured risk context for manual review" } }, "required": [ @@ -7851,6 +9439,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payout transaction step", @@ -7931,6 +9520,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payout liquidity step", @@ -7999,6 +9589,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Documents step", @@ -8063,6 +9654,16 @@ "minLength": 15, "maxLength": 15, "example": "ow_000000000000" + }, + "payable_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "description": "The payable this payout executes, when it pays a payable instead of a bank account.", + "example": "pb_000000000000" } }, "required": [ @@ -8088,7 +9689,7 @@ "type": "string", "minLength": 15, "maxLength": 15, - "example": "pa_000000000000" + "example": "po_000000000000" }, "status": { "type": "string", @@ -8139,6 +9740,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Complete step", @@ -8202,6 +9804,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payment step", @@ -8224,8 +9827,9 @@ "Citi", "CFSB", "Triple A Technologies", + "BCB Group", "Portage Bank", - "SSB Bank" + "NMI" ], "description": "Payment provider name", "example": "HSBC" @@ -8243,7 +9847,8 @@ "bitso", "starkbank", "triplea", - "infinitus" + "infinitus", + "portage_g" ], "description": "Machine-readable integration that executed the fiat leg. Unlike provider_name (a client-facing bank label), this uniquely identifies the integration — e.g. zenus vs checkbook, which share the \"JPMorgan Chase\" label.", "example": "zenus" @@ -8278,6 +9883,15 @@ "description": "Provider error reason when payment fails (e.g. invalid_key, wrong_parameters)", "example": "invalid_key" }, + "returned_amount": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "Amount (in cents of the payout currency) the beneficiary bank sent back after the payment was delivered. May be lower than the amount sent when the return is partial.", + "example": 5000 + }, "provider_uetr": { "type": [ "string", @@ -8314,6 +9928,19 @@ "description": "Clearing system that processed the payment (e.g. FED, CHIPS, ACH, SWIFT).", "example": "FED" }, + "forced_provider": { + "type": [ + "string", + "null" + ], + "enum": [ + "zenus", + "veem", + "infinitus_portage" + ], + "description": "Ops-set per-payout provider override (backoffice Reroute tab). When present it wins over the instance payment_route and default routing at send time. Left in place after the send as an audit marker of the forced route.", + "example": "veem" + }, "recipient_name": { "type": [ "string", @@ -8402,6 +10029,69 @@ ], "description": "Payment completed date", "example": "2011-10-05T14:48:00.000Z" + }, + "refund_review_reason": { + "type": [ + "string", + "null" + ], + "enum": [ + "amount_threshold", + "time_window", + "late_cancellation_no_live_run", + "master_account_return", + "policy_always_review", + "operator_requested", + "partial_return" + ], + "description": "Why the payout was routed to the Pending Refunds review queue instead of auto-refunding after a provider cancellation", + "example": "amount_threshold" + }, + "refund_review_detected_at": { + "type": [ + "string", + "null" + ], + "description": "When the provider cancellation was routed to the Pending Refunds review queue", + "example": "2011-10-05T14:48:00.000Z" + }, + "refund_review_actioned_at": { + "type": [ + "string", + "null" + ], + "description": "Atomic claim marker: set the moment an operator approves a Pending Refunds entry, before the refund is sent, so a concurrent approve call cannot re-claim the same payout", + "example": "2011-10-05T14:48:00.000Z" + }, + "review_source": { + "type": [ + "string", + "null" + ], + "description": "Primary risk source that sent this payout to manual review", + "example": "nested_third_party" + }, + "review_sources": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Every risk source that sent this payout to manual review", + "example": [ + "nested_third_party", + "seon_review" + ] + }, + "review_context": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "Structured risk context for manual review" } }, "required": [ @@ -8417,6 +10107,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payout transaction step", @@ -8497,6 +10188,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payout liquidity step", @@ -8565,6 +10257,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Documents step", @@ -8629,6 +10322,16 @@ "minLength": 15, "maxLength": 15, "example": "ow_000000000000" + }, + "payable_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "description": "The payable this payout executes, when it pays a payable instead of a bank account.", + "example": "pb_000000000000" } }, "required": [ @@ -8682,6 +10385,192 @@ "value": "https://example.com/ein.pdf" } }, + "CustomerCnaeCondition": { + "type": [ + "object", + "null" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "pending", + "passed", + "failed", + "cancelled" + ] + }, + "expected_cnaes": { + "type": "array", + "items": { + "type": "string", + "pattern": "^\\d{2,7}$" + }, + "minItems": 1 + }, + "cnae_at_approval": { + "type": "object", + "properties": { + "primary": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": [ + "code", + "description" + ] + }, + "secondary": { + "type": "array", + "items": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": [ + "code", + "description" + ] + } + } + }, + "required": [ + "primary", + "secondary" + ] + }, + "result_cnae": { + "type": [ + "object", + "null" + ], + "properties": { + "primary": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": [ + "code", + "description" + ] + }, + "secondary": { + "type": "array", + "items": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": [ + "code", + "description" + ] + } + } + }, + "required": [ + "primary", + "secondary" + ] + }, + "due_at": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "reviewed_at": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "status", + "expected_cnaes", + "cnae_at_approval", + "result_cnae", + "due_at", + "created_at", + "reviewed_at" + ], + "description": "Present when the customer was approved on the condition that its CNAE (Brazilian business activity code) is corrected by `due_at`. While `pending` the customer is fully approved. At `due_at` BlindPay rechecks the public CNPJ record: `passed` keeps the customer approved, `failed` sets `kyc_status` to `rejected` and adds a `CNAE_MISMATCH` entry to `kyc_warnings`." + }, + "CustomerVirtualAccountPreapproval": { + "type": [ + "object", + "null" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "in_review", + "approved", + "rejected" + ], + "example": "approved" + }, + "banking_partners": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "jpmorgan", + "portage" + ] + }, + "description": "Banking partners the customer can open a virtual account on. While `in_review`, the partners whose data requirements are met; once `approved`, the partners compliance cleared.", + "example": [ + "jpmorgan" + ] + }, + "rejection_reason": { + "type": [ + "string", + "null" + ], + "example": null + }, + "reviewed_at": { + "type": [ + "string", + "null" + ], + "example": "2026-09-01T00:00:00.000Z" + } + }, + "required": [ + "status", + "banking_partners", + "rejection_reason", + "reviewed_at" + ], + "description": "Present once the customer carries enough data for at least one virtual account banking partner. `in_review` means compliance will review the virtual account data together with the KYB/KYC case. `approved` means a virtual account created for this customer skips the compliance stage and goes straight to the bank. `rejected` carries the reason; update the customer data to be reviewed again. Every change sends a `customer.update` webhook." + }, "CustomerNewWebhookOut": { "type": "object", "properties": { @@ -8718,6 +10607,7 @@ "standard", "enhanced" ], + "description": "Use standard for individuals and businesses, or enhanced for individuals. light is not available for new customers, and businesses only support standard.", "example": "standard" }, "kyc_status": { @@ -10320,6 +12210,14 @@ ], "example": false }, + "is_nested": { + "type": [ + "boolean", + "null" + ], + "description": "Set by BlindPay compliance for nested customers (fintechs and PSPs). Only first-party transactions are allowed; third-party payins and payouts are held for manual review.", + "example": false + }, "account_purpose": { "type": [ "string", @@ -10380,152 +12278,6 @@ "string", "null" ], - "enum": [ - "111998", - "112120", - "113310", - "115114", - "541211", - "541810", - "541430", - "541715", - "541930", - "561422", - "561311", - "561612", - "561740", - "561730", - "236115", - "236220", - "237310", - "238210", - "811111", - "812111", - "812112", - "532111", - "624410", - "541922", - "811210", - "812199", - "611110", - "611310", - "611410", - "611710", - "211120", - "212114", - "221310", - "562111", - "562920", - "213112", - "522110", - "522210", - "522320", - "523150", - "523940", - "523999", - "524113", - "813110", - "813211", - "813219", - "551112", - "721110", - "722511", - "722513", - "561510", - "713110", - "713210", - "712110", - "711110", - "711211", - "621111", - "621210", - "622110", - "623110", - "621511", - "623220", - "541940", - "621399", - "621910", - "541110", - "311421", - "337121", - "322220", - "339920", - "334210", - "339930", - "312130", - "334111", - "334118", - "325412", - "339112", - "336110", - "336390", - "315990", - "313110", - "339910", - "516120", - "513130", - "512250", - "519130", - "711410", - "711510", - "531110", - "531120", - "531130", - "531190", - "531210", - "531311", - "531312", - "531320", - "531390", - "454110", - "445110", - "455110", - "457110", - "449210", - "444110", - "459210", - "459120", - "445320", - "458110", - "458210", - "458310", - "455219", - "424210", - "456110", - "446120", - "541511", - "541512", - "541519", - "518210", - "511210", - "517111", - "517112", - "517410", - "481111", - "483111", - "485210", - "488510", - "484121", - "493110", - "423430", - "423690", - "423110", - "423830", - "423840", - "423510", - "424690", - "424990", - "424410", - "424480", - "423940", - "541611", - "541618", - "541330", - "541990", - "541214", - "561499" - ], "example": "541511" }, "estimated_annual_revenue": { @@ -10556,7 +12308,9 @@ "gambling", "charitable_contributions", "inheritance", - "affiliate_or_royalty_income" + "affiliate_or_royalty_income", + "salary_or_wages", + "savings" ], "example": "affiliate_or_royalty_income" }, @@ -10718,6 +12472,12 @@ "value": "Funds originate from US payroll deposits, forwarded weekly to customer." } ] + }, + "cnae_condition": { + "$ref": "#/components/schemas/CustomerCnaeCondition" + }, + "virtual_account_preapproval": { + "$ref": "#/components/schemas/CustomerVirtualAccountPreapproval" } }, "required": [ @@ -10769,6 +12529,7 @@ "standard", "enhanced" ], + "description": "Use standard for individuals and businesses, or enhanced for individuals. light is not available for new customers, and businesses only support standard.", "example": "standard" }, "kyc_status": { @@ -12371,6 +14132,14 @@ ], "example": false }, + "is_nested": { + "type": [ + "boolean", + "null" + ], + "description": "Set by BlindPay compliance for nested customers (fintechs and PSPs). Only first-party transactions are allowed; third-party payins and payouts are held for manual review.", + "example": false + }, "account_purpose": { "type": [ "string", @@ -12431,152 +14200,6 @@ "string", "null" ], - "enum": [ - "111998", - "112120", - "113310", - "115114", - "541211", - "541810", - "541430", - "541715", - "541930", - "561422", - "561311", - "561612", - "561740", - "561730", - "236115", - "236220", - "237310", - "238210", - "811111", - "812111", - "812112", - "532111", - "624410", - "541922", - "811210", - "812199", - "611110", - "611310", - "611410", - "611710", - "211120", - "212114", - "221310", - "562111", - "562920", - "213112", - "522110", - "522210", - "522320", - "523150", - "523940", - "523999", - "524113", - "813110", - "813211", - "813219", - "551112", - "721110", - "722511", - "722513", - "561510", - "713110", - "713210", - "712110", - "711110", - "711211", - "621111", - "621210", - "622110", - "623110", - "621511", - "623220", - "541940", - "621399", - "621910", - "541110", - "311421", - "337121", - "322220", - "339920", - "334210", - "339930", - "312130", - "334111", - "334118", - "325412", - "339112", - "336110", - "336390", - "315990", - "313110", - "339910", - "516120", - "513130", - "512250", - "519130", - "711410", - "711510", - "531110", - "531120", - "531130", - "531190", - "531210", - "531311", - "531312", - "531320", - "531390", - "454110", - "445110", - "455110", - "457110", - "449210", - "444110", - "459210", - "459120", - "445320", - "458110", - "458210", - "458310", - "455219", - "424210", - "456110", - "446120", - "541511", - "541512", - "541519", - "518210", - "511210", - "517111", - "517112", - "517410", - "481111", - "483111", - "485210", - "488510", - "484121", - "493110", - "423430", - "423690", - "423110", - "423830", - "423840", - "423510", - "424690", - "424990", - "424410", - "424480", - "423940", - "541611", - "541618", - "541330", - "541990", - "541214", - "561499" - ], "example": "541511" }, "estimated_annual_revenue": { @@ -12607,7 +14230,9 @@ "gambling", "charitable_contributions", "inheritance", - "affiliate_or_royalty_income" + "affiliate_or_royalty_income", + "salary_or_wages", + "savings" ], "example": "affiliate_or_royalty_income" }, @@ -12769,6 +14394,12 @@ "value": "Funds originate from US payroll deposits, forwarded weekly to customer." } ] + }, + "cnae_condition": { + "$ref": "#/components/schemas/CustomerCnaeCondition" + }, + "virtual_account_preapproval": { + "$ref": "#/components/schemas/CustomerVirtualAccountPreapproval" } }, "required": [ @@ -12826,6 +14457,7 @@ "standard", "enhanced" ], + "description": "Use standard for individuals and businesses, or enhanced for individuals. light is not available for new customers, and businesses only support standard.", "example": "standard" }, "kyc_status": { @@ -12905,548 +14537,325 @@ "idempotency_key" ] }, - "WalletTokenOut": { + "TransferNewWebhookOut": { "type": "object", "properties": { - "address": { - "type": "string" - }, - "id": { - "type": "string" - }, - "symbol": { + "webhook_event": { "type": "string", "enum": [ - "USDC", - "USDT", - "USDB" + "transfer.new" ] }, - "amount": { - "type": "number" - } - }, - "required": [ - "address", - "id", - "symbol", - "amount" - ] - }, - "WalletInboundSchemaOut": { - "type": "object", - "properties": { "id": { - "type": "string" - }, - "address": { - "type": "string" - }, - "network": { "type": "string", - "enum": [ - "base", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "arbitrum", - "polygon", - "polygon_amoy", - "ethereum", - "stellar", - "stellar_testnet", - "tron", - "solana", - "solana_devnet" - ] - }, - "token": { - "$ref": "#/components/schemas/WalletTokenOut" - } - }, - "required": [ - "id", - "address", - "network", - "token" - ] - }, - "Success": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "example": true - } - }, - "required": [ - "success" - ] - }, - "Error": { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "example": false + "minLength": 15, + "maxLength": 15, + "example": "tr_000000000000" }, - "code": { + "status": { "type": "string", - "description": "Stable error code. See the Error codes section for the full list.", - "example": "PAYOUTS_INSUFFICIENT_BALANCE" + "enum": [ + "processing", + "failed", + "refunded", + "completed" + ], + "description": "Transfer general status", + "example": "processing" }, - "message": { - "type": "string", - "description": "Legacy machine-readable message. Prefer `code` for programmatic handling.", - "example": "not_enough_balance" + "tracking_bridge_swap": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "gas_fee": { + "type": [ + "string", + "null" + ], + "description": "Gas fee related to transaction", + "example": "100" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "error_message": { + "type": [ + "string", + "null" + ], + "example": "Gas fee is too low" + } + }, + "required": [ + "step" + ] }, - "description": { - "type": "string", - "description": "Human-readable explanation, safe to show to end users.", - "example": "There is not enough balance to complete this payout. Fund your balance and try again." + "tracking_complete": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "gas_fee": { + "type": [ + "string", + "null" + ], + "description": "Gas fee related to transaction", + "example": "100" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "error_message": { + "type": [ + "string", + "null" + ], + "example": "Gas fee is too low" + } + }, + "required": [ + "step" + ] }, - "errors": { - "type": "array", - "items": { - "type": "string" + "tracking_paymaster": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "gas_fee": { + "type": [ + "string", + "null" + ], + "description": "Gas fee related to transaction", + "example": "100" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "error_message": { + "type": [ + "string", + "null" + ], + "example": "Gas fee is too low" + } }, - "example": [ - "Bad Request" + "required": [ + "step" ] }, - "trace_id": { - "type": "string", - "description": "Request trace ID. Include it when contacting support.", - "example": "0af7651916cd43dd8448eb211c80319c" - } - }, - "required": [ - "success", - "message", - "errors" - ] - }, - "UploadOut": { - "type": "object", - "properties": { - "file_url": { - "type": "string" - } - }, - "required": [ - "file_url" - ] - }, - "UploadIn": { - "type": "object", - "properties": { - "file": {}, - "bucket": { - "type": "string", - "enum": [ - "avatar", - "onboarding", - "limit_increase" + "tracking_transaction_monitoring": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Transaction monitoring step", + "example": "processing" + }, + "blockchain_screening": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 100, + "description": "Blindpay screening step", + "example": 1 + }, + "risk_score": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 100, + "description": "Risk score", + "example": 1 + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Transfer transaction completed date", + "example": "2011-10-05T14:48:00.000Z" + } + }, + "required": [ + "step" ] - } - }, - "required": [ - "file", - "bucket" - ] - }, - "UploadAnalyzeOut": { - "type": "object", - "properties": { - "approval_rate": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ], - "description": "Confidence that the document should be approved.", - "example": "high" }, - "description": { - "type": "string", - "description": "Short explanation of why the document should or should not be approved." + "tracking_partner_fee": { + "type": [ + "object", + "null" + ], + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "gas_fee": { + "type": [ + "string", + "null" + ], + "description": "Gas fee related to transaction", + "example": "100" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "error_message": { + "type": [ + "string", + "null" + ], + "example": "Gas fee is too low" + } + }, + "required": [ + "step" + ] } }, "required": [ - "approval_rate", - "description" + "webhook_event", + "id", + "status", + "tracking_bridge_swap", + "tracking_complete", + "tracking_paymaster", + "tracking_transaction_monitoring" ] }, - "UploadAnalyzeIn": { + "TransferUpdateWebhookOut": { "type": "object", "properties": { - "file": { - "description": "The document to analyze (PDF, JPG, or PNG).", - "example": {} - }, - "type": { + "webhook_event": { "type": "string", "enum": [ - "proof_of_address", - "identity_document", - "incorporation_document", - "proof_of_ownership", - "source_of_funds", - "selfie", - "bank_statement", - "tax_return", - "proof_of_income", - "financial_statement", - "invoice", - "transaction_document", - "passport", - "pay_stub", - "employment_letter", - "investment", - "crypto_exchange", - "blockchain_wallet", - "contract", - "accounts_receivable", - "merchant_processor", - "shareholder_loan" - ], - "description": "The kind of document being analyzed. Selects the rule set used for the analysis.", - "example": "proof_of_address" + "transfer.update" + ] }, - "metadata": { - "type": "string", - "description": "Optional JSON object of expected values to verify against the document (e.g. {\"full_name\":\"Jane Doe\",\"date_of_birth\":\"1990-01-01\"}). When provided, a clear mismatch caps the rating at low.", - "example": "{\"full_name\":\"Jane Doe\"}" - } - }, - "required": [ - "file", - "type" - ] - }, - "QuoteOut": { - "type": "object", - "properties": { "id": { "type": "string", "minLength": 15, "maxLength": 15, - "example": "qu_000000000000" - }, - "expires_at": { - "type": [ - "number", - "null" - ], - "description": "Epoch unix timestamp that represents the final datetime to transaction be received on blockchain. For SEPA payouts this may be shorter than the default 5 minute window if Circle CPN returns an earlier expiry.", - "example": 1712958191 - }, - "commercial_quotation": { - "type": [ - "number", - "null" - ], - "description": "1 USD = 4.95 BRL", - "example": 495 - }, - "blindpay_quotation": { - "type": [ - "number", - "null" - ], - "description": "1 USD = 4.85 BRL (commercial quotation - (blindpay taxes))", - "example": 485 - }, - "receiver_amount": { - "type": [ - "number", - "null" - ], - "description": "52.40 BRL", - "example": 5240 - }, - "sender_amount": { - "type": [ - "number", - "null" - ], - "description": "10.10 USDC needs to be sent to bank account blockchain address", - "example": 1010 + "example": "tr_000000000000" }, - "partner_fee_amount": { - "type": [ - "number", - "null" + "status": { + "type": "string", + "enum": [ + "processing", + "failed", + "refunded", + "completed" ], - "default": 0, - "description": "1.5 USDC", - "example": 150 + "description": "Transfer general status", + "example": "processing" }, - "flat_fee": { - "type": [ - "number", - "null" - ], - "description": "0.5 USDC", - "example": 50 - }, - "billing_fee_amount": { - "type": [ - "number", - "null" - ], - "description": "Billing fee in cents (charged via invoice at the end of the month)", - "example": 50 - }, - "contract": { - "type": [ - "object", - "null" - ], - "properties": { - "abi": { - "type": "array", - "items": { - "type": "object", - "properties": {}, - "description": "Contract abi related to the network you send in request params", - "example": {} - } - }, - "address": { - "type": "string", - "description": "Token address related to the network you send in request params", - "example": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238" - }, - "functionName": { - "type": "string", - "enum": [ - "approve" - ], - "description": "Function name from ERC20 smart contract", - "example": "approve" - }, - "blindpayContractAddress": { - "type": "string", - "description": "Blindpay contract address", - "example": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238" - }, - "amount": { - "type": "string", - "description": "Amount to approve with correct decimal places", - "example": "1000000000000000000" - }, - "network": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "Ethereum" - }, - "chainId": { - "type": "number", - "example": 1 - } - }, - "required": [ - "name", - "chainId" - ] - } - }, - "required": [ - "abi", - "address", - "functionName", - "blindpayContractAddress", - "amount", - "network" - ] - }, - "customer_local_amount": { - "type": [ - "number", - "null" - ], - "description": "Estimated amount in the currency of recipient bank account", - "example": 1000 - }, - "description": { - "type": [ - "string", - "null" - ], - "maxLength": 128, - "example": "Memo code or description, only works with USD and BRL" - } - }, - "required": [ - "id", - "expires_at", - "commercial_quotation", - "blindpay_quotation", - "receiver_amount", - "sender_amount" - ] - }, - "QuoteIn": { - "type": "object", - "properties": { - "bank_account_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "ba_000000000000" - }, - "currency_type": { - "type": "string", - "enum": [ - "sender", - "receiver" - ], - "description": "", - "example": "sender" - }, - "cover_fees": { - "type": [ - "boolean", - "null" - ], - "description": "If true, the sender will cover the fees. If false, the customer will cover the fees.", - "example": true - }, - "request_amount": { - "type": "integer", - "minimum": 500, - "description": "1000 represents 10.00, 2050 represents 20.50", - "example": 1000 - }, - "network": { - "type": "string", - "enum": [ - "base", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "arbitrum", - "polygon", - "polygon_amoy", - "ethereum", - "stellar", - "stellar_testnet", - "tron", - "solana", - "solana_devnet" - ], - "description": "Check blindpay available networks", - "example": "sepolia" - }, - "token": { - "type": "string", - "enum": [ - "USDC", - "USDT", - "USDB" - ], - "description": "Check blindpay available tokens", - "example": "USDC" - }, - "description": { - "type": [ - "string", - "null" - ], - "maxLength": 128, - "example": "Memo code or description, only works with USD and BRL" - }, - "partner_fee_id": { - "type": [ - "string", - "null" - ], - "minLength": 15, - "maxLength": 15, - "example": "pf_000000000000" - }, - "refund_wallet_address": { - "type": [ - "string", - "null" - ], - "description": "Optional wallet address to receive the refund if this payout fails or is refunded. Must be a valid address on the quote network. When omitted, refunds are sent back to the sender wallet address.", - "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" - } - }, - "required": [ - "bank_account_id", - "currency_type", - "request_amount", - "network", - "token" - ] - }, - "PayoutOut": { - "type": "object", - "properties": { - "customer_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer id", - "example": "re_000000000000" - }, - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "pa_000000000000" - }, - "status": { - "type": "string", - "enum": [ - "processing", - "failed", - "refunded", - "completed", - "on_hold" - ], - "description": "Payout general status", - "example": "processing" - }, - "sender_wallet_address": { - "type": "string", - "description": "Payout wallet address", - "example": "0x123...890" - }, - "signed_transaction": { - "type": [ - "string", - "null" - ], - "description": "Signed transaction", - "example": "AAA...Zey8y0A" - }, - "quote_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "qu_000000000000" - }, - "instance_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "partner_fee": { - "type": "integer", - "minimum": 0, - "default": 0, - "description": "Payout partner fee amount in cents (can be negative for rebates)", - "example": -25000 - }, - "tracking_transaction": { + "tracking_bridge_swap": { "type": "object", "properties": { "step": { @@ -13455,75 +14864,49 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], - "description": "Payout transaction step", - "example": "processing" - }, - "status": { - "type": [ - "string", - "null" - ], - "enum": [ - "failed", - "found" - ], - "description": "Payout transaction status", - "example": "failed" + "description": "Complete step", + "example": "on_hold" }, "transaction_hash": { "type": [ "string", "null" ], - "description": "Blockchain transaction hash", + "description": "Complete transaction hash", "example": "0x123...890" }, - "completed_at": { - "type": [ - "string", - "null" - ], - "description": "Payout transaction completed date", - "example": "2011-10-05T14:48:00.000Z" - }, - "provider_transaction_id": { - "type": [ - "string", - "null" - ], - "description": "Provider-side handle for the on-chain leg (e.g. Circle CPN payment id).", - "example": "67c12eae-b7bc-31cc-a5ef-623dcea82346" - }, - "provider_error_reason": { + "gas_fee": { "type": [ "string", "null" ], - "description": "Provider error reason when the crypto collection fails (e.g. erc20_allowance_insufficient, ESTIMATION_ERROR: execution reverted)", - "example": "erc20_allowance_insufficient" + "description": "Gas fee related to transaction", + "example": "100" }, - "ledger_in_transaction_id": { + "completed_at": { "type": [ "string", "null" ], - "description": "Ledger transaction ID for the IN (crypto deposit) transaction" + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" }, - "ledger_out_transaction_id": { + "error_message": { "type": [ "string", "null" ], - "description": "Ledger transaction ID for the OUT (fiat withdrawal) transaction" + "example": "Gas fee is too low" } }, "required": [ "step" ] }, - "tracking_payment": { + "tracking_complete": { "type": "object", "properties": { "step": { @@ -13532,217 +14915,291 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], - "description": "Payment step", + "description": "Complete step", "example": "on_hold" }, - "provider_name": { + "transaction_hash": { "type": [ "string", "null" ], - "enum": [ - "Nvio Pagos", - "Brex", - "Stark Bank", - "JPMorgan Chase", - "HSBC", - "Inter", - "JP Morgan Chase", - "Bitso", - "Citi", - "CFSB", - "Triple A Technologies", - "Portage Bank", - "SSB Bank" - ], - "description": "Payment provider name", - "example": "HSBC" + "description": "Complete transaction hash", + "example": "0x123...890" }, - "provider_integration": { + "gas_fee": { "type": [ "string", "null" ], - "enum": [ - "veem", - "zenus", - "checkbook", - "onemoney", - "bitso", - "starkbank", - "triplea", - "infinitus" - ], - "description": "Machine-readable integration that executed the fiat leg. Unlike provider_name (a client-facing bank label), this uniquely identifies the integration — e.g. zenus vs checkbook, which share the \"JPMorgan Chase\" label.", - "example": "zenus" + "description": "Gas fee related to transaction", + "example": "100" }, - "provider_transaction_id": { + "completed_at": { "type": [ "string", "null" ], - "description": "Payment provider transaction id", - "example": "0x123...890" + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" }, - "provider_status": { + "error_message": { "type": [ "string", "null" ], + "example": "Gas fee is too low" + } + }, + "required": [ + "step" + ] + }, + "tracking_paymaster": { + "type": "object", + "properties": { + "step": { + "type": "string", "enum": [ - "canceled", - "failed", - "returned", - "sent" + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" ], - "description": "Payment provider status", - "example": "canceled" + "description": "Complete step", + "example": "on_hold" }, - "provider_error_reason": { + "transaction_hash": { "type": [ "string", "null" ], - "description": "Provider error reason when payment fails (e.g. invalid_key, wrong_parameters)", - "example": "invalid_key" + "description": "Complete transaction hash", + "example": "0x123...890" }, - "provider_uetr": { + "gas_fee": { "type": [ "string", "null" ], - "maxLength": 120, - "description": "Unique end-to-end transaction reference (UETR). Populated once the wire is confirmed by the network; null while the payment is in flight or when the rail does not expose it (e.g. ACH).", - "example": "37d10eff-d450-4aba-a5d4-e3978f5a3343" + "description": "Gas fee related to transaction", + "example": "100" }, - "provider_imad": { + "completed_at": { "type": [ "string", "null" ], - "maxLength": 120, - "description": "Fed Input Message Accountability Data (IMAD). Domestic Fedwire payments only; null on ACH and SWIFT.", - "example": "20260526MMQFMP2M008120" + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" }, - "provider_reference": { + "error_message": { "type": [ "string", "null" ], - "maxLength": 120, - "description": "Provider (JPMorgan/Zenus) payment reference captured from the ACCOUNT.ACCOUNT booking webhook (Zenus contractSource.sourceRef). Present for some ACH/wire payouts; a bank-side reference, not the formal ACH network trace number.", - "example": "2084734238TC" - }, - "provider_clearing_system": { - "type": [ - "string", - "null" + "example": "Gas fee is too low" + } + }, + "required": [ + "step" + ] + }, + "tracking_transaction_monitoring": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" ], - "maxLength": 40, - "description": "Clearing system that processed the payment (e.g. FED, CHIPS, ACH, SWIFT).", - "example": "FED" + "description": "Transaction monitoring step", + "example": "processing" }, - "recipient_name": { + "blockchain_screening": { "type": [ - "string", + "number", "null" ], - "description": "Recipient name", - "example": "John Doe" + "minimum": 0, + "maximum": 100, + "description": "Blindpay screening step", + "example": 1 }, - "recipient_tax_id": { + "risk_score": { "type": [ - "string", + "number", "null" ], - "description": "Recipient tax id", - "example": "123.456.789-10" + "minimum": 0, + "maximum": 100, + "description": "Risk score", + "example": 1 }, - "recipient_bank_code": { + "completed_at": { "type": [ "string", "null" ], - "description": "Recipient bank code", - "example": "00416968" - }, - "recipient_branch_code": { - "type": [ - "string", - "null" + "description": "Transfer transaction completed date", + "example": "2011-10-05T14:48:00.000Z" + } + }, + "required": [ + "step" + ] + }, + "tracking_partner_fee": { + "type": [ + "object", + "null" + ], + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" ], - "description": "Recipient branch code", - "example": "0001" + "description": "Complete step", + "example": "on_hold" }, - "recipient_account_number": { + "transaction_hash": { "type": [ "string", "null" ], - "description": "Recipient account number", - "example": "1234567890" + "description": "Complete transaction hash", + "example": "0x123...890" }, - "recipient_account_type": { + "gas_fee": { "type": [ "string", "null" ], - "description": "Recipient account type", - "example": "checking" + "description": "Gas fee related to transaction", + "example": "100" }, - "coelsa_id": { + "completed_at": { "type": [ "string", "null" ], - "description": "COELSA transaction reference ID for ARS transfers (Argentine national banking system)", - "example": "1LMP68NKV46DRDYK2R7OEV" + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" }, - "end_to_end_id": { + "error_message": { "type": [ "string", "null" ], - "description": "BACEN Pix end-to-end transaction ID (govt Pix ID)", - "example": "E20018183202603311320vm6ALFpJpsS" - }, - "estimated_time_of_arrival": { - "type": [ + "example": "Gas fee is too low" + } + }, + "required": [ + "step" + ] + } + }, + "required": [ + "webhook_event", + "id", + "status", + "tracking_bridge_swap", + "tracking_complete", + "tracking_paymaster", + "tracking_transaction_monitoring" + ] + }, + "TransferCompleteWebhookOut": { + "type": "object", + "properties": { + "webhook_event": { + "type": "string", + "enum": [ + "transfer.complete" + ] + }, + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "tr_000000000000" + }, + "status": { + "type": "string", + "enum": [ + "processing", + "failed", + "refunded", + "completed" + ], + "description": "Transfer general status", + "example": "processing" + }, + "tracking_bridge_swap": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "transaction_hash": { + "type": [ "string", "null" ], - "enum": [ - "5_min", - "5_30_min", - "30_min", - "2_hours", - "1_business_day", - "2_business_days", - "5_business_days" + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "gas_fee": { + "type": [ + "string", + "null" ], - "description": "Estimated time of arrival", - "example": "5_min" + "description": "Gas fee related to transaction", + "example": "100" }, "completed_at": { "type": [ "string", "null" ], - "description": "Payment completed date", + "description": "Complete completed date", "example": "2011-10-05T14:48:00.000Z" + }, + "error_message": { + "type": [ + "string", + "null" + ], + "example": "Gas fee is too low" } }, "required": [ "step" ] }, - "tracking_liquidity": { - "type": [ - "object", - "null" - ], + "tracking_complete": { + "type": "object", "properties": { "step": { "type": "string", @@ -13750,63 +15207,49 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], - "description": "Payout liquidity step", - "example": "processing" + "description": "Complete step", + "example": "on_hold" }, - "provider_transaction_id": { + "transaction_hash": { "type": [ "string", "null" ], - "description": "Payment provider transaction id", + "description": "Complete transaction hash", "example": "0x123...890" }, - "provider_status": { + "gas_fee": { "type": [ "string", "null" ], - "enum": [ - "deposited", - "converted", - "withdrawn" - ], - "description": "Payment provider status", - "example": "deposited" + "description": "Gas fee related to transaction", + "example": "100" }, - "estimated_time_of_arrival": { + "completed_at": { "type": [ "string", "null" ], - "enum": [ - "5_min", - "5_30_min", - "30_min", - "2_hours", - "1_business_day", - "2_business_days", - "5_business_days" - ], - "description": "Estimated time of arrival", - "example": "1_business_day" + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" }, - "completed_at": { + "error_message": { "type": [ "string", "null" ], - "description": "Payout transaction completed date", - "example": "2011-10-05T14:48:00.000Z" + "example": "Gas fee is too low" } }, "required": [ "step" ] }, - "tracking_complete": { + "tracking_paymaster": { "type": "object", "properties": { "step": { @@ -13815,53 +15258,89 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Complete step", "example": "on_hold" }, - "status": { + "transaction_hash": { "type": [ "string", "null" ], - "enum": [ - "tokens_refunded", - "paid" - ], - "description": "Complete status", - "example": "tokens_refunded" + "description": "Complete transaction hash", + "example": "0x123...890" }, - "refund_reason": { + "gas_fee": { "type": [ "string", "null" ], - "description": "Reason for refund when tokens are returned to sender", - "example": "fiat_payment_failed" + "description": "Gas fee related to transaction", + "example": "100" }, - "transaction_hash": { + "completed_at": { "type": [ "string", "null" ], - "description": "Complete transaction hash", - "example": "0x123...890" + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" }, - "provider_transaction_id": { + "error_message": { "type": [ "string", "null" ], - "description": "Provider-side handle for the refund transaction (e.g. Circle transaction id)", - "example": "67c12eae-b7bc-31cc-a5ef-623dcea82346" + "example": "Gas fee is too low" + } + }, + "required": [ + "step" + ] + }, + "tracking_transaction_monitoring": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Transaction monitoring step", + "example": "processing" + }, + "blockchain_screening": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 100, + "description": "Blindpay screening step", + "example": 1 + }, + "risk_score": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 100, + "description": "Risk score", + "example": 1 }, "completed_at": { "type": [ "string", "null" ], - "description": "Complete completed date", + "description": "Transfer transaction completed date", "example": "2011-10-05T14:48:00.000Z" } }, @@ -13869,7 +15348,7 @@ "step" ] }, - "tracking_documents": { + "tracking_partner_fee": { "type": [ "object", "null" @@ -13881,196 +15360,403 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], - "description": "Documents step", - "example": "processing" + "description": "Complete step", + "example": "on_hold" }, - "status": { + "transaction_hash": { "type": [ "string", "null" ], - "enum": [ - "waiting_documents", - "compliance_reviewing" - ], - "description": "Documents status", - "example": "waiting_documents" + "description": "Complete transaction hash", + "example": "0x123...890" }, - "reviewed_by": { + "gas_fee": { "type": [ "string", "null" ], - "description": "Reviewer email/name", - "example": "compliance@example.com" + "description": "Gas fee related to transaction", + "example": "100" }, "completed_at": { "type": [ "string", "null" ], - "description": "Documents completed date", + "description": "Complete completed date", "example": "2011-10-05T14:48:00.000Z" + }, + "error_message": { + "type": [ + "string", + "null" + ], + "example": "Gas fee is too low" } }, "required": [ "step" ] + } + }, + "required": [ + "webhook_event", + "id", + "status", + "tracking_bridge_swap", + "tracking_complete", + "tracking_paymaster", + "tracking_transaction_monitoring" + ] + }, + "VirtualAccountNewWebhookOut": { + "type": "object", + "properties": { + "webhook_event": { + "type": "string", + "enum": [ + "virtualAccount.new" + ] }, - "jpm_track_data": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "va_000000000000" + }, + "banking_partner": { + "type": [ + "string", + "null" + ], + "enum": [ + "jpmorgan", + "citi", + "hsbc", + "cfsb", + "portage", + "bre_b", + "spei", + "portage_g" + ], + "example": "jpmorgan" + }, + "kyc_status": { + "type": [ + "string", + "null" + ], + "enum": [ + "verifying", + "approved", + "rejected", + "deprecated", + "pending_review", + "awaiting_contract", + "compliance_request", + "approved_rfi" + ], + "example": "approved" + }, + "us": { "type": [ "object", "null" ], "properties": { - "jpm_trace_number": { + "ach": { "type": [ - "string", + "object", "null" ], - "description": "JPM trace number", - "example": "317802200000565" + "properties": { + "routing_number": { + "type": "string", + "example": "123456789" + }, + "account_number": { + "type": "string", + "example": "123456789" + } + }, + "required": [ + "routing_number", + "account_number" + ] }, - "jpm_processing_status": { + "wire": { + "type": "object", + "properties": { + "routing_number": { + "type": "string", + "example": "123456789" + }, + "account_number": { + "type": "string", + "example": "123456789" + } + }, + "required": [ + "routing_number", + "account_number" + ] + }, + "rtp": { "type": [ - "string", + "object", "null" ], - "description": "JPM processing status", - "example": "Completed" + "properties": { + "routing_number": { + "type": "string", + "example": "123456789" + }, + "account_number": { + "type": "string", + "example": "123456789" + } + }, + "required": [ + "routing_number", + "account_number" + ] }, - "extended_tracking_status": { + "swift_bic_code": { "type": [ "string", "null" ], - "description": "Extended tracking status from JPM", - "example": "Delivered to next bank" + "example": "TCCLGB3L" }, - "jpm_reference_number": { + "swift_account_number": { "type": [ "string", "null" ], - "description": "JPM reference number", - "example": "9483400364JO" + "example": "GB50TCCL04140449730892" }, - "uetr": { + "account_type": { "type": [ "string", "null" ], - "description": "Unique end-to-end transaction reference", - "example": "4ad5f98a-5279-410a-99a2-39a729aceb35" + "enum": [ + "Personal checking", + "Business checking" + ], + "default": "Business checking", + "example": "Business checking" }, - "fed_imad": { + "beneficiary": { "type": [ - "string", + "object", "null" ], - "description": "Fed IMAD number (Wire payments only)", - "example": "1230MMQFMP2L034796" + "properties": { + "name": { + "type": "string", + "example": "Customer Name" + }, + "address_line_1": { + "type": "string", + "example": "8 The Green, #19364" + }, + "address_line_2": { + "type": "string", + "example": "Dover, DE 19901" + } + }, + "required": [ + "name", + "address_line_1", + "address_line_2" + ] }, - "payment_date": { + "receiving_bank": { "type": [ - "string", + "object", "null" ], - "description": "Payment date", - "example": "Dec 30 2025" + "properties": { + "name": { + "type": "string", + "example": "JPMorgan Chase" + }, + "address_line_1": { + "type": "string", + "example": "270 Park Ave" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "New York, NY, 10017-2070" + } + }, + "required": [ + "name", + "address_line_1" + ] }, - "payment_amount": { + "swift_receiving_bank": { "type": [ - "string", + "object", "null" ], - "description": "Payment amount", - "example": "3,914.00" + "properties": { + "name": { + "type": [ + "string", + "null" + ], + "example": "JPMorgan Chase" + }, + "address_line_1": { + "type": [ + "string", + "null" + ], + "example": "270 Park Ave" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "New York, NY, 10017-2070" + } + } }, - "payment_currency": { + "swift_intermediary_bank": { "type": [ - "string", + "object", "null" ], - "description": "Payment currency", - "example": "USD" + "properties": { + "name": { + "type": [ + "string", + "null" + ], + "example": "JP Morgan Chase NA" + }, + "swift_code_bic": { + "type": [ + "string", + "null" + ], + "example": "CHASUS33" + }, + "routing_number": { + "type": [ + "string", + "null" + ], + "example": "021000021" + }, + "address_line_1": { + "type": [ + "string", + "null" + ], + "example": "270 Park Ave" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "New York, NY, 10017-2070" + } + } } - } - }, - "cpn_payment_id": { - "type": [ - "string", - "null" - ], - "description": "Circle CPN payment id", - "example": "f06dbc45-58a4-389f-beb8-581c3fafff3c" + }, + "required": [ + "wire" + ] }, - "created_at": { + "co": { "type": [ - "string", + "object", "null" ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" - }, - "updated_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" - }, - "image_url": { - "type": [ - "string", - "null" - ], - "format": "uri", - "example": "https://example.com/image.png" - }, - "first_name": { - "type": [ - "string", - "null" - ], - "example": "John" - }, - "last_name": { - "type": [ - "string", - "null" - ], - "example": "Doe" + "properties": { + "bre_b": { + "type": "object", + "properties": { + "key": { + "type": "string", + "example": "@BP000000000000" + } + }, + "required": [ + "key" + ] + }, + "beneficiary": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": "string", + "example": "Customer Name" + } + }, + "required": [ + "name" + ] + } + }, + "required": [ + "bre_b" + ] }, - "legal_name": { + "mx": { "type": [ - "string", + "object", "null" ], - "example": "Company Name Inc." - }, - "network": { - "type": "string", - "enum": [ - "base", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "arbitrum", - "polygon", - "polygon_amoy", - "ethereum", - "stellar", - "stellar_testnet", - "tron", - "solana", - "solana_devnet" - ], - "description": "Check blindpay available networks", - "example": "sepolia" + "properties": { + "spei": { + "type": "object", + "properties": { + "clabe": { + "type": "string", + "minLength": 18, + "maxLength": 18, + "example": "710969000000000001" + } + }, + "required": [ + "clabe" + ] + }, + "beneficiary": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": "string", + "example": "BLINDPAY LLC" + } + }, + "required": [ + "name" + ] + } + }, + "required": [ + "spei" + ] }, "token": { "type": "string", @@ -14079,1141 +15765,2347 @@ "USDT", "USDB" ], - "description": "Check blindpay available tokens", "example": "USDC" }, - "description": { + "blockchain_wallet_id": { "type": [ "string", "null" ], - "maxLength": 128, - "example": "Memo code or description, only works with USD and BRL" + "minLength": 15, + "maxLength": 15, + "example": "bw_000000000000" }, - "sender_amount": { + "blockchain_wallet": { "type": [ - "number", + "object", "null" ], - "description": "10.10 USDC needs to be sent to bank account blockchain address", - "example": 1010 + "properties": { + "network": { + "type": "string", + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "polygon" + }, + "address": { + "type": [ + "string", + "null" + ], + "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + } + }, + "required": [ + "network" + ] }, - "receiver_amount": { + "partner_fee_id": { "type": [ - "number", + "string", "null" ], - "description": "52.40 BRL", - "example": 5240 + "minLength": 15, + "maxLength": 15, + "example": "pf_000000000000" }, - "partner_fee_id": { + "customer_id": { "type": [ "string", "null" ], "minLength": 15, "maxLength": 15, - "example": "pf_000000000000" + "example": "re_000000000000" + } + }, + "required": [ + "webhook_event", + "id", + "banking_partner", + "kyc_status", + "token" + ] + }, + "VirtualAccountCompleteWebhookOut": { + "type": "object", + "properties": { + "webhook_event": { + "type": "string", + "enum": [ + "virtualAccount.complete" + ] }, - "partner_fee_amount": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "va_000000000000" + }, + "banking_partner": { "type": [ - "number", + "string", "null" ], - "default": 0, - "description": "1.5 USDC", - "example": 150 + "enum": [ + "jpmorgan", + "citi", + "hsbc", + "cfsb", + "portage", + "bre_b", + "spei", + "portage_g" + ], + "example": "jpmorgan" }, - "commercial_quotation": { + "kyc_status": { "type": [ - "number", + "string", "null" ], - "description": "1 USD = 4.95 BRL", - "example": 495 + "enum": [ + "verifying", + "approved", + "rejected", + "deprecated", + "pending_review", + "awaiting_contract", + "compliance_request", + "approved_rfi" + ], + "example": "approved" }, - "blindpay_quotation": { + "us": { "type": [ - "number", + "object", "null" ], - "description": "1 USD = 4.85 BRL (commercial quotation - (blindpay taxes))", - "example": 485 + "properties": { + "ach": { + "type": [ + "object", + "null" + ], + "properties": { + "routing_number": { + "type": "string", + "example": "123456789" + }, + "account_number": { + "type": "string", + "example": "123456789" + } + }, + "required": [ + "routing_number", + "account_number" + ] + }, + "wire": { + "type": "object", + "properties": { + "routing_number": { + "type": "string", + "example": "123456789" + }, + "account_number": { + "type": "string", + "example": "123456789" + } + }, + "required": [ + "routing_number", + "account_number" + ] + }, + "rtp": { + "type": [ + "object", + "null" + ], + "properties": { + "routing_number": { + "type": "string", + "example": "123456789" + }, + "account_number": { + "type": "string", + "example": "123456789" + } + }, + "required": [ + "routing_number", + "account_number" + ] + }, + "swift_bic_code": { + "type": [ + "string", + "null" + ], + "example": "TCCLGB3L" + }, + "swift_account_number": { + "type": [ + "string", + "null" + ], + "example": "GB50TCCL04140449730892" + }, + "account_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "Personal checking", + "Business checking" + ], + "default": "Business checking", + "example": "Business checking" + }, + "beneficiary": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": "string", + "example": "Customer Name" + }, + "address_line_1": { + "type": "string", + "example": "8 The Green, #19364" + }, + "address_line_2": { + "type": "string", + "example": "Dover, DE 19901" + } + }, + "required": [ + "name", + "address_line_1", + "address_line_2" + ] + }, + "receiving_bank": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": "string", + "example": "JPMorgan Chase" + }, + "address_line_1": { + "type": "string", + "example": "270 Park Ave" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "New York, NY, 10017-2070" + } + }, + "required": [ + "name", + "address_line_1" + ] + }, + "swift_receiving_bank": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": [ + "string", + "null" + ], + "example": "JPMorgan Chase" + }, + "address_line_1": { + "type": [ + "string", + "null" + ], + "example": "270 Park Ave" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "New York, NY, 10017-2070" + } + } + }, + "swift_intermediary_bank": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": [ + "string", + "null" + ], + "example": "JP Morgan Chase NA" + }, + "swift_code_bic": { + "type": [ + "string", + "null" + ], + "example": "CHASUS33" + }, + "routing_number": { + "type": [ + "string", + "null" + ], + "example": "021000021" + }, + "address_line_1": { + "type": [ + "string", + "null" + ], + "example": "270 Park Ave" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "New York, NY, 10017-2070" + } + } + } + }, + "required": [ + "wire" + ] }, - "total_fee_amount": { + "co": { "type": [ - "number", + "object", "null" ], - "default": 0, - "description": "1.5 USDC", - "example": 1.5 + "properties": { + "bre_b": { + "type": "object", + "properties": { + "key": { + "type": "string", + "example": "@BP000000000000" + } + }, + "required": [ + "key" + ] + }, + "beneficiary": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": "string", + "example": "Customer Name" + } + }, + "required": [ + "name" + ] + } + }, + "required": [ + "bre_b" + ] }, - "customer_local_amount": { + "mx": { "type": [ - "number", + "object", "null" ], - "description": "Estimated amount in the currency of recipient bank account", - "example": 1000 + "properties": { + "spei": { + "type": "object", + "properties": { + "clabe": { + "type": "string", + "minLength": 18, + "maxLength": 18, + "example": "710969000000000001" + } + }, + "required": [ + "clabe" + ] + }, + "beneficiary": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": "string", + "example": "BLINDPAY LLC" + } + }, + "required": [ + "name" + ] + } + }, + "required": [ + "spei" + ] }, - "currency": { + "token": { "type": "string", "enum": [ - "BRL", - "USD", - "MXN", - "COP", - "ARS", - "EUR" + "USDC", + "USDT", + "USDB" ], - "description": "ISO 4271 currency code", - "example": "BRL" + "example": "USDC" }, - "transaction_fee_amount": { + "blockchain_wallet_id": { "type": [ - "number", + "string", "null" ], - "description": "Transaction fee in cents (percentage-based fee)", - "example": 100 - }, - "billing_fee_amount": { + "minLength": 15, + "maxLength": 15, + "example": "bw_000000000000" + }, + "blockchain_wallet": { "type": [ - "number", + "object", "null" ], - "description": "Billing fee in cents (charged via invoice at the end of the month)", - "example": 50 + "properties": { + "network": { + "type": "string", + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "polygon" + }, + "address": { + "type": [ + "string", + "null" + ], + "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + } + }, + "required": [ + "network" + ] }, - "transaction_document_file": { + "partner_fee_id": { "type": [ "string", "null" ], - "format": "uri", - "example": "https://example.com/image.png" + "minLength": 15, + "maxLength": 15, + "example": "pf_000000000000" }, - "transaction_document_type": { + "customer_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + } + }, + "required": [ + "webhook_event", + "id", + "banking_partner", + "kyc_status", + "token" + ] + }, + "YieldStatus": { + "type": "string", + "enum": [ + "disabled", + "enabled", + "disabling" + ], + "default": "disabled", + "example": "enabled" + }, + "WalletNewWebhookOut": { + "type": "object", + "properties": { + "webhook_event": { + "type": "string", + "enum": [ + "wallet.new" + ] + }, + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bl_000000000000" + }, + "name": { + "type": "string", + "maxLength": 255, + "example": "Blindpay Wallet" + }, + "external_id": { + "type": [ + "string", + "null" + ], + "maxLength": 255, + "example": "your-database-id" + }, + "address": { "type": [ "string", "null" ], + "maxLength": 64, + "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + }, + "network": { + "type": "string", "enum": [ - "invoice", - "purchase_order", - "delivery_slip", - "contract", - "customs_declaration", - "bill_of_lading", - "others" + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" ], - "example": "invoice" + "example": "polygon" }, - "transaction_document_id": { + "yield_status": { + "$ref": "#/components/schemas/YieldStatus" + }, + "created_at": { "type": [ "string", "null" ], - "maxLength": 512, - "example": "1234567890" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + } + }, + "required": [ + "webhook_event", + "id", + "name", + "network" + ] + }, + "WalletUpdateWebhookOut": { + "type": "object", + "properties": { + "webhook_event": { + "type": "string", + "enum": [ + "wallet.update" + ] + }, + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bl_000000000000" }, "name": { "type": "string", - "example": "Bank Account Name" + "maxLength": 255, + "example": "Blindpay Wallet" + }, + "external_id": { + "type": [ + "string", + "null" + ], + "maxLength": 255, + "example": "your-database-id" + }, + "address": { + "type": [ + "string", + "null" + ], + "maxLength": 64, + "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + }, + "network": { + "type": "string", + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "polygon" + }, + "yield_status": { + "$ref": "#/components/schemas/YieldStatus" + }, + "created_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + } + }, + "required": [ + "webhook_event", + "id", + "name", + "network" + ] + }, + "WalletInboundTokenOut": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "id": { + "type": "string" + }, + "symbol": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB", + "EURC", + "EURB" + ] + }, + "amount": { + "type": "number" + } + }, + "required": [ + "address", + "id", + "symbol", + "amount" + ] + }, + "WalletInboundWebhookOut": { + "type": "object", + "properties": { + "webhook_event": { + "type": "string", + "enum": [ + "wallet.inbound" + ] + }, + "id": { + "type": "string" + }, + "address": { + "type": "string" + }, + "network": { + "type": "string", + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ] + }, + "token": { + "$ref": "#/components/schemas/WalletInboundTokenOut" + }, + "deposit_id": { + "type": "string", + "description": "Matches the id returned by the wallet deposits list", + "example": "wd_000000000000" + }, + "transaction_hash": { + "type": "string", + "example": "0x8f3e1b..." + } + }, + "required": [ + "webhook_event", + "id", + "address", + "network", + "token", + "deposit_id", + "transaction_hash" + ] + }, + "PayableParty": { + "type": [ + "object", + "null" + ], + "properties": { + "legal_name": { + "type": [ + "string", + "null" + ], + "maxLength": 255, + "example": "Empresa de Servicos LTDA" + }, + "address_line_1": { + "type": [ + "string", + "null" + ], + "maxLength": 255 + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "maxLength": 255 + }, + "city": { + "type": [ + "string", + "null" + ], + "maxLength": 128 + }, + "state_province_region": { + "type": [ + "string", + "null" + ], + "maxLength": 128 + }, + "postal_code": { + "type": [ + "string", + "null" + ], + "maxLength": 32 + }, + "country": { + "type": [ + "string", + "null" + ], + "maxLength": 2, + "description": "ISO 3166-1 alpha-2 country code", + "example": "BR" + }, + "tax_id": { + "type": [ + "string", + "null" + ], + "maxLength": 64, + "example": "12.345.678/0001-90" + } + }, + "description": "Who issued the invoice / is paying the bill." + }, + "PayableLineItem": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "example": "Consulting services" }, + "quantity": { + "type": "integer", + "minimum": 1, + "example": 2 + }, + "price": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "Unit price in cents of the payable currency. 150000 represents 1,500.00.", + "example": 150000 + } + }, + "required": [ + "name", + "quantity", + "price" + ] + }, + "PayableBankAccount": { + "type": [ + "object", + "null" + ], + "properties": { "type": { "type": "string", "enum": [ - "wire", "ach", - "pix", - "pix_safe", - "ted", - "spei_bitso", - "transfers_bitso", - "ach_cop_bitso", - "international_swift", - "rtp", - "sepa" + "wire" ], - "example": "wire" + "example": "ach" }, - "pix_key": { + "beneficiary_name": { "type": [ "string", "null" ], - "example": "14947677768" + "example": "Northwind Cloud Services Inc" }, - "pix_safe_bank_code": { + "routing_number": { "type": [ "string", "null" ], - "pattern": "^\\d{4,8}$", - "example": "00416968" + "example": "026009593" }, - "pix_safe_branch_code": { + "account_number": { "type": [ "string", "null" ], - "pattern": "^\\d{4}(-\\d)?$", - "example": "0001" + "example": "000123456789" }, - "pix_safe_cpf_cnpj": { + "account_type": { "type": [ "string", "null" ], - "example": "12345678901" + "example": "checking" + } + }, + "required": [ + "type" + ], + "description": "Destination of an invoice payable, as registered. Null for boleto and PIX payables. The underlying bank account is owned by the payable and is not listed or addressable on its own." + }, + "PayableNewWebhookOut": { + "type": "object", + "properties": { + "webhook_event": { + "type": "string", + "enum": [ + "payable.new" + ] }, - "ted_bank_code": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "pb_000000000000" + }, + "instance_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "customer_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "from": { + "$ref": "#/components/schemas/PayableParty" + }, + "to": { + "allOf": [ + { + "$ref": "#/components/schemas/PayableParty" + }, + { + "description": "The beneficiary being paid." + } + ] + }, + "currency": { + "type": "string", + "enum": [ + "BRL", + "USD", + "MXN", + "COP", + "ARS", + "EUR", + "GBP" + ], + "description": "ISO 4217 currency code of the payable.", + "example": "BRL" + }, + "line_items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PayableLineItem" + }, + "maxItems": 100, + "default": [], + "description": "Invoice line items. The payable total is the line item sum plus taxes minus discount." + }, + "note": { "type": [ "string", "null" ], - "pattern": "^\\d{3,5}$", - "example": "033" + "maxLength": 512, + "example": "August retainer" }, - "ted_branch_code": { + "discount": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "default": 0, + "description": "Discount in cents of the payable currency.", + "example": 0 + }, + "taxes": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "default": 0, + "description": "Taxes in cents of the payable currency.", + "example": 0 + }, + "boleto_barcode": { "type": [ "string", "null" ], - "pattern": "^\\d{4}(-\\d)?$", - "example": "0001" + "minLength": 1, + "maxLength": 512, + "description": "Boleto or arrecadação code (linha digitável or barcode).", + "example": "34191.79001 01043.510047 91020.150008 1 84660000002000" }, - "ted_cpf_cnpj": { + "pix_qrcode": { "type": [ "string", "null" ], - "example": "12345678901" + "minLength": 1, + "maxLength": 512, + "description": "PIX copia e cola (EMV) payload." }, - "account_number": { + "document_file": { "type": [ "string", "null" ], - "example": "1001001234" + "format": "uri", + "description": "The boleto or invoice document, as a file URL returned by POST /upload with bucket `documents`. Not accepted for PIX payables. Read it through POST /presign.", + "example": "https://files.blindpay.com/1712345678901-boleto.pdf" }, - "routing_number": { + "due_date": { "type": [ "string", "null" ], - "example": "012345678" + "example": "2026-08-10" }, - "country": { + "scheduled_at": { "type": [ "string", "null" ], + "description": "When to pay this payable automatically. Not executed yet: stored for the upcoming scheduling feature.", + "example": "2026-08-10T12:00:00.000Z" + }, + "status": { + "type": "string", "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" + "draft", + "processing", + "completed", + "canceled" ], - "example": "US" + "description": "draft until a payout executes this payable, processing while one is in flight, completed when paid, canceled when a draft is deleted. A failed or refunded attempt returns it to draft; follow the payout for the attempt detail.", + "example": "draft" }, - "account_class": { + "created_at": { "type": [ "string", "null" ], - "enum": [ - "individual", - "business" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + }, + "updated_at": { + "type": [ + "string", + "null" ], - "example": "individual" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" }, - "address_line_1": { + "amount": { + "type": [ + "integer", + "null" + ], + "description": "Derived total in cents: line item sum plus taxes minus discount. For boleto/PIX the rail amount is re-resolved from the code at quote time and can differ (fines, interest).", + "example": 300000 + }, + "payout_id": { "type": [ "string", "null" ], - "example": "Address line 1" + "minLength": 15, + "maxLength": 15, + "description": "The payout executing this payable, once one exists. Null while the payable is a draft.", + "example": "po_000000000000" }, - "address_line_2": { + "bank_account": { + "$ref": "#/components/schemas/PayableBankAccount" + }, + "last_attempt_status": { "type": [ "string", "null" ], - "example": "Address line 2" + "enum": [ + "failed", + "refunded" + ], + "description": "Why the payable returned to draft: the attempt in payout_id failed before funding or was refunded after it. Set only on that payable.update event; follow the payout for the detail.", + "example": "failed" }, - "city": { + "first_name": { + "type": [ + "string", + "null" + ] + }, + "last_name": { "type": [ "string", "null" + ] + }, + "legal_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "webhook_event", + "id", + "instance_id", + "customer_id", + "currency", + "status", + "amount" + ] + }, + "PayableUpdateWebhookOut": { + "type": "object", + "properties": { + "webhook_event": { + "type": "string", + "enum": [ + "payable.update" + ] + }, + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "pb_000000000000" + }, + "instance_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "customer_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "from": { + "$ref": "#/components/schemas/PayableParty" + }, + "to": { + "allOf": [ + { + "$ref": "#/components/schemas/PayableParty" + }, + { + "description": "The beneficiary being paid." + } + ] + }, + "currency": { + "type": "string", + "enum": [ + "BRL", + "USD", + "MXN", + "COP", + "ARS", + "EUR", + "GBP" ], - "example": "City" + "description": "ISO 4217 currency code of the payable.", + "example": "BRL" }, - "state_province_region": { + "line_items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PayableLineItem" + }, + "maxItems": 100, + "default": [], + "description": "Invoice line items. The payable total is the line item sum plus taxes minus discount." + }, + "note": { "type": [ "string", "null" ], - "example": "State/Province/Region" + "maxLength": 512, + "example": "August retainer" }, - "postal_code": { + "discount": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "default": 0, + "description": "Discount in cents of the payable currency.", + "example": 0 + }, + "taxes": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "default": 0, + "description": "Taxes in cents of the payable currency.", + "example": 0 + }, + "boleto_barcode": { "type": [ "string", "null" ], - "example": "Postal code" + "minLength": 1, + "maxLength": 512, + "description": "Boleto or arrecadação code (linha digitável or barcode).", + "example": "34191.79001 01043.510047 91020.150008 1 84660000002000" }, - "account_type": { + "pix_qrcode": { "type": [ "string", "null" ], - "enum": [ - "checking", - "saving" + "minLength": 1, + "maxLength": 512, + "description": "PIX copia e cola (EMV) payload." + }, + "document_file": { + "type": [ + "string", + "null" ], - "example": "checking" + "format": "uri", + "description": "The boleto or invoice document, as a file URL returned by POST /upload with bucket `documents`. Not accepted for PIX payables. Read it through POST /presign.", + "example": "https://files.blindpay.com/1712345678901-boleto.pdf" }, - "ach_cop_beneficiary_first_name": { + "due_date": { "type": [ "string", "null" ], - "example": "Fernando" + "example": "2026-08-10" }, - "ach_cop_bank_account": { + "scheduled_at": { "type": [ "string", "null" ], - "example": "12345678" + "description": "When to pay this payable automatically. Not executed yet: stored for the upcoming scheduling feature.", + "example": "2026-08-10T12:00:00.000Z" }, - "ach_cop_bank_code": { + "status": { + "type": "string", + "enum": [ + "draft", + "processing", + "completed", + "canceled" + ], + "description": "draft until a payout executes this payable, processing while one is in flight, completed when paid, canceled when a draft is deleted. A failed or refunded attempt returns it to draft; follow the payout for the attempt detail.", + "example": "draft" + }, + "created_at": { "type": [ "string", "null" ], - "example": "051" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" }, - "ach_cop_beneficiary_last_name": { + "updated_at": { "type": [ "string", "null" ], - "example": "Guzman Alarcón" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" }, - "ach_cop_document_id": { + "amount": { + "type": [ + "integer", + "null" + ], + "description": "Derived total in cents: line item sum plus taxes minus discount. For boleto/PIX the rail amount is re-resolved from the code at quote time and can differ (fines, interest).", + "example": 300000 + }, + "payout_id": { "type": [ "string", "null" ], - "example": "1661105408" + "minLength": 15, + "maxLength": 15, + "description": "The payout executing this payable, once one exists. Null while the payable is a draft.", + "example": "po_000000000000" }, - "ach_cop_document_type": { + "bank_account": { + "$ref": "#/components/schemas/PayableBankAccount" + }, + "last_attempt_status": { "type": [ "string", "null" ], "enum": [ - "CC", - "CE", - "NIT", - "PASS", - "PEP" + "failed", + "refunded" ], - "description": "CC - Cédula de Ciudadanía; CE - Cédula de Extranjería; NIT - Número de Identificación Tributaria; PASS - Passport; PEP - Permiso Especial de Permanencia", - "example": "CC" + "description": "Why the payable returned to draft: the attempt in payout_id failed before funding or was refunded after it. Set only on that payable.update event; follow the payout for the detail.", + "example": "failed" }, - "ach_cop_email": { + "first_name": { + "type": [ + "string", + "null" + ] + }, + "last_name": { + "type": [ + "string", + "null" + ] + }, + "legal_name": { "type": [ "string", "null" + ] + } + }, + "required": [ + "webhook_event", + "id", + "instance_id", + "customer_id", + "currency", + "status", + "amount" + ] + }, + "PayableCompleteWebhookOut": { + "type": "object", + "properties": { + "webhook_event": { + "type": "string", + "enum": [ + "payable.complete" + ] + }, + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "pb_000000000000" + }, + "instance_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "customer_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "from": { + "$ref": "#/components/schemas/PayableParty" + }, + "to": { + "allOf": [ + { + "$ref": "#/components/schemas/PayableParty" + }, + { + "description": "The beneficiary being paid." + } + ] + }, + "currency": { + "type": "string", + "enum": [ + "BRL", + "USD", + "MXN", + "COP", + "ARS", + "EUR", + "GBP" ], - "example": "fernando.guzman@gmail.com" + "description": "ISO 4217 currency code of the payable.", + "example": "BRL" }, - "beneficiary_name": { + "line_items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PayableLineItem" + }, + "maxItems": 100, + "default": [], + "description": "Invoice line items. The payable total is the line item sum plus taxes minus discount." + }, + "note": { "type": [ "string", "null" ], - "maxLength": 128, - "example": "Individual full name or business name" + "maxLength": 512, + "example": "August retainer" }, - "spei_clabe": { + "discount": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "default": 0, + "description": "Discount in cents of the payable currency.", + "example": 0 + }, + "taxes": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "default": 0, + "description": "Taxes in cents of the payable currency.", + "example": 0 + }, + "boleto_barcode": { "type": [ "string", "null" ], - "example": "5482347403740546" + "minLength": 1, + "maxLength": 512, + "description": "Boleto or arrecadação code (linha digitável or barcode).", + "example": "34191.79001 01043.510047 91020.150008 1 84660000002000" }, - "spei_protocol": { + "pix_qrcode": { "type": [ "string", "null" ], - "enum": [ - "clabe", - "debitcard", - "phonenum" + "minLength": 1, + "maxLength": 512, + "description": "PIX copia e cola (EMV) payload." + }, + "document_file": { + "type": [ + "string", + "null" ], - "description": "For debitcard and phonenum the spei_institution_code is required", - "example": "clabe" + "format": "uri", + "description": "The boleto or invoice document, as a file URL returned by POST /upload with bucket `documents`. Not accepted for PIX payables. Read it through POST /presign.", + "example": "https://files.blindpay.com/1712345678901-boleto.pdf" }, - "spei_institution_code": { + "due_date": { "type": [ "string", "null" ], - "minLength": 5, - "maxLength": 5, - "example": "40002" + "example": "2026-08-10" }, - "swift_beneficiary_country": { + "scheduled_at": { "type": [ "string", "null" ], + "description": "When to pay this payable automatically. Not executed yet: stored for the upcoming scheduling feature.", + "example": "2026-08-10T12:00:00.000Z" + }, + "status": { + "type": "string", "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" + "draft", + "processing", + "completed", + "canceled" ], - "example": "MX" + "description": "draft until a payout executes this payable, processing while one is in flight, completed when paid, canceled when a draft is deleted. A failed or refunded attempt returns it to draft; follow the payout for the attempt detail.", + "example": "draft" }, - "swift_code_bic": { + "created_at": { "type": [ "string", "null" ], - "example": "123456789" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" }, - "swift_account_holder_name": { + "updated_at": { "type": [ "string", "null" ], - "maxLength": 50, - "example": "John Doe" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" }, - "swift_account_number_iban": { + "amount": { "type": [ - "string", + "integer", "null" ], - "example": "123456789" + "description": "Derived total in cents: line item sum plus taxes minus discount. For boleto/PIX the rail amount is re-resolved from the code at quote time and can differ (fines, interest).", + "example": 300000 }, - "transfers_account": { + "payout_id": { "type": [ "string", "null" ], - "example": "BM123123123123" + "minLength": 15, + "maxLength": 15, + "description": "The payout executing this payable, once one exists. Null while the payable is a draft.", + "example": "po_000000000000" }, - "transfers_type": { + "bank_account": { + "$ref": "#/components/schemas/PayableBankAccount" + }, + "last_attempt_status": { "type": [ "string", "null" ], "enum": [ - "CVU", - "CBU", - "ALIAS" + "failed", + "refunded" ], - "example": "CVU" + "description": "Why the payable returned to draft: the attempt in payout_id failed before funding or was refunded after it. Set only on that payable.update event; follow the payout for the detail.", + "example": "failed" }, - "has_virtual_account": { + "first_name": { "type": [ - "boolean", + "string", "null" - ], - "description": "Has virtual account", - "example": true + ] }, - "sender_legal_name": { + "last_name": { "type": [ "string", "null" - ], - "description": "Legal name of the sending instance (originator), shown on the receipt", - "example": "LRB TRADING INVESTMENT L.L.C" + ] + }, + "legal_name": { + "type": [ + "string", + "null" + ] } }, "required": [ - "customer_id", + "webhook_event", "id", - "status", - "sender_wallet_address", - "quote_id", "instance_id", - "tracking_transaction", - "tracking_payment", - "tracking_complete", - "network", - "token", - "sender_amount", - "receiver_amount", - "commercial_quotation", - "blindpay_quotation", + "customer_id", "currency", - "name", - "type" + "status", + "amount" ] }, - "PaginationMetadata": { + "Success": { "type": "object", "properties": { - "has_more": { + "success": { "type": "boolean", - "description": "Whether or not there are more elements available after this set.", "example": true + } + }, + "required": [ + "success" + ] + }, + "Error": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "example": false }, - "next_page": { - "type": [ - "string", - "null" - ], - "description": "The ID of the first item in the next page of results.", - "example": "pi_123" + "code": { + "type": "string", + "description": "Stable error code. See the Error codes section for the full list.", + "example": "PAYOUTS_INSUFFICIENT_BALANCE" }, - "prev_page": { - "type": [ - "string", - "null" - ], - "description": "The ID of the first item in the previous page of results.", - "example": "pi_123" + "message": { + "type": "string", + "description": "Legacy machine-readable message. Prefer `code` for programmatic handling.", + "example": "not_enough_balance" + }, + "description": { + "type": "string", + "description": "Human-readable explanation, safe to show to end users.", + "example": "There is not enough balance to complete this payout. Fund your balance and try again." + }, + "errors": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "Bad Request" + ] + }, + "trace_id": { + "type": "string", + "description": "Request trace ID. Include it when contacting support.", + "example": "0af7651916cd43dd8448eb211c80319c" } }, "required": [ - "has_more" + "success", + "message", + "errors" ] }, - "PayoutOnStellarAuthorizeIn": { + "UploadOut": { "type": "object", "properties": { - "quote_id": { + "file_url": { + "type": "string" + } + }, + "required": [ + "file_url" + ] + }, + "UploadIn": { + "type": "object", + "properties": { + "file": {}, + "bucket": { "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "qu_000000000000" + "enum": [ + "avatar", + "onboarding", + "limit_increase", + "documents" + ] + } + }, + "required": [ + "file", + "bucket" + ] + }, + "UploadAnalyzeOut": { + "type": "object", + "properties": { + "approval_rate": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "description": "Confidence that the document should be approved.", + "example": "high" }, - "sender_wallet_address": { + "description": { "type": "string", - "description": "Payout wallet address", - "example": "0x123...890" + "description": "Short explanation of why the document should or should not be approved." } }, "required": [ - "quote_id", - "sender_wallet_address" + "approval_rate", + "description" ] }, - "PayoutOnEvmOut": { + "UploadAnalyzeIn": { "type": "object", "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "pa_000000000000" + "file": { + "description": "The document to analyze (PDF, JPG, or PNG).", + "example": {} }, - "status": { + "type": { "type": "string", "enum": [ - "processing", - "failed", - "refunded", - "completed", - "on_hold" + "proof_of_address", + "identity_document", + "incorporation_document", + "proof_of_ownership", + "source_of_funds", + "selfie", + "bank_statement", + "tax_return", + "proof_of_income", + "financial_statement", + "invoice", + "transaction_document", + "passport", + "pay_stub", + "employment_letter", + "investment", + "crypto_exchange", + "blockchain_wallet", + "contract", + "accounts_receivable", + "merchant_processor", + "shareholder_loan" ], - "description": "Payout general status", - "example": "processing" + "description": "The kind of document being analyzed. Selects the rule set used for the analysis.", + "example": "proof_of_address" }, - "sender_wallet_address": { + "metadata": { "type": "string", - "description": "Payout wallet address", - "example": "0x123...890" - }, - "billing_fee_amount": { + "description": "Optional JSON object of expected values to verify against the document (e.g. {\"full_name\":\"Jane Doe\",\"date_of_birth\":\"1990-01-01\"}). When provided, a clear mismatch caps the rating at low.", + "example": "{\"full_name\":\"Jane Doe\"}" + } + }, + "required": [ + "file", + "type" + ] + }, + "UploadExtractOut": { + "type": "object", + "properties": { + "amount": { "type": [ - "number", + "integer", "null" ], - "description": "Billing fee in cents (charged via invoice at the end of the month)", - "example": 50 + "description": "Total due in cents of `currency`.", + "example": 425000 }, - "transaction_fee_amount": { + "currency": { "type": [ - "number", + "string", "null" ], - "description": "Transaction fee in cents (percentage-based fee)", - "example": 100 + "minLength": 3, + "maxLength": 3, + "example": "USD" }, - "partner_fee": { - "type": "integer", - "minimum": 0, - "default": 0, - "description": "Payout partner fee amount in cents (can be negative for rebates)", - "example": -25000 + "due_date": { + "type": [ + "string", + "null" + ], + "description": "YYYY-MM-DD.", + "example": "2026-09-15" }, - "tracking_complete": { - "type": "object", + "invoice_number": { + "type": [ + "string", + "null" + ], + "maxLength": 64, + "example": "INV-2026-081" + }, + "to": { + "type": "object", "properties": { - "step": { - "type": "string", - "enum": [ - "processing", - "on_hold", - "pending_review", - "completed" + "legal_name": { + "type": [ + "string", + "null" ], - "description": "Complete step", - "example": "on_hold" + "maxLength": 255 }, - "status": { + "tax_id": { "type": [ "string", "null" ], - "enum": [ - "tokens_refunded", - "paid" + "maxLength": 64 + }, + "address_line_1": { + "type": [ + "string", + "null" ], - "description": "Complete status", - "example": "tokens_refunded" + "maxLength": 255 }, - "refund_reason": { + "city": { "type": [ "string", "null" ], - "description": "Reason for refund when tokens are returned to sender", - "example": "fiat_payment_failed" + "maxLength": 128 }, - "transaction_hash": { + "state_province_region": { "type": [ "string", "null" ], - "description": "Complete transaction hash", - "example": "0x123...890" + "maxLength": 64 }, - "provider_transaction_id": { + "country": { "type": [ "string", "null" ], - "description": "Provider-side handle for the refund transaction (e.g. Circle transaction id)", - "example": "67c12eae-b7bc-31cc-a5ef-623dcea82346" + "minLength": 2, + "maxLength": 2 }, - "completed_at": { + "postal_code": { "type": [ "string", "null" ], - "description": "Complete completed date", - "example": "2011-10-05T14:48:00.000Z" + "maxLength": 32 } }, "required": [ - "step" + "legal_name", + "tax_id", + "address_line_1", + "city", + "state_province_region", + "country", + "postal_code" + ], + "description": "The vendor being paid, as printed on the invoice." + }, + "line_items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "maxLength": 255 + }, + "quantity": { + "type": "integer", + "minimum": 1 + }, + "price": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "name", + "quantity", + "price" + ] + }, + "maxItems": 100, + "description": "Unit prices in cents of `currency`." + }, + "payment_options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "ach", + "wire", + "international_swift" + ], + "example": "ach" + }, + "routing_number": { + "type": [ + "string", + "null" + ], + "description": "US rails only." + }, + "account_number": { + "type": [ + "string", + "null" + ], + "description": "US rails only." + }, + "account_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "checking", + "saving" + ] + }, + "iban": { + "type": [ + "string", + "null" + ], + "description": "SWIFT only." + }, + "swift_bic": { + "type": [ + "string", + "null" + ], + "description": "SWIFT only." + }, + "beneficiary_name": { + "type": [ + "string", + "null" + ], + "maxLength": 128 + }, + "bank_name": { + "type": [ + "string", + "null" + ], + "maxLength": 128 + } + }, + "required": [ + "type", + "routing_number", + "account_number", + "account_type", + "iban", + "swift_bic", + "beneficiary_name", + "bank_name" + ] + }, + "maxItems": 5, + "description": "One entry per payment instruction block printed on the invoice, ordered by preference: ach, wire, international_swift. Numbers that fail format checks come back null; an option with no usable number is dropped. Empty when the invoice prints no bank instructions." + } + }, + "required": [ + "amount", + "currency", + "due_date", + "invoice_number", + "to", + "line_items", + "payment_options" + ] + }, + "UploadExtractIn": { + "type": "object", + "properties": { + "file": { + "description": "The invoice to read (PDF, JPG, or PNG).", + "example": {} + } + }, + "required": [ + "file" + ] + }, + "PresignOut": { + "type": "object", + "properties": { + "file_url": { + "type": "string", + "description": "Time-limited signed URL that grants read access to the file." + }, + "expires_at": { + "type": "string", + "description": "ISO 8601 timestamp at which the signed URL stops working (1 hour after issuance).", + "example": "2026-01-01T13:00:00.000Z" + } + }, + "required": [ + "file_url", + "expires_at" + ] + }, + "PresignIn": { + "type": "object", + "properties": { + "file_url": { + "type": "string", + "format": "uri", + "description": "A BlindPay file URL previously returned by POST /upload. URLs from any other host are rejected.", + "example": "https://files.blindpay.com/1712345678901-document.pdf" + } + }, + "required": [ + "file_url" + ] + }, + "QuoteOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "qu_000000000000" + }, + "expires_at": { + "type": [ + "number", + "null" + ], + "description": "Epoch timestamp in milliseconds after which the quote can no longer be executed, 5 minutes after creation. For SEPA payouts this may be shorter if Circle CPN returns an earlier expiry.", + "example": 1712958191000 + }, + "commercial_quotation": { + "type": [ + "number", + "null" + ], + "description": "1 USD = 4.95 BRL", + "example": 495 + }, + "blindpay_quotation": { + "type": [ + "number", + "null" + ], + "description": "1 USD = 4.85 BRL (commercial quotation - (blindpay taxes))", + "example": 485 + }, + "receiver_amount": { + "type": [ + "number", + "null" + ], + "description": "52.40 BRL", + "example": 5240 + }, + "sender_amount": { + "type": [ + "number", + "null" + ], + "description": "10.10 USDC needs to be sent to bank account blockchain address", + "example": 1010 + }, + "partner_fee_amount": { + "type": [ + "number", + "null" + ], + "default": 0, + "description": "1.5 USDC", + "example": 150 + }, + "flat_fee": { + "type": [ + "number", + "null" + ], + "description": "0.5 USDC", + "example": 50 + }, + "billing_fee_amount": { + "type": [ + "number", + "null" + ], + "description": "Billing fee in cents (charged via invoice at the end of the month)", + "example": 50 + }, + "contract": { + "type": [ + "object", + "null" + ], + "properties": { + "abi": { + "type": "array", + "items": { + "type": "object", + "properties": {}, + "description": "Contract abi related to the network you send in request params", + "example": {} + } + }, + "address": { + "type": "string", + "description": "Token address related to the network you send in request params", + "example": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238" + }, + "functionName": { + "type": "string", + "enum": [ + "approve" + ], + "description": "Function name from ERC20 smart contract", + "example": "approve" + }, + "blindpayContractAddress": { + "type": "string", + "description": "Blindpay contract address", + "example": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238" + }, + "amount": { + "type": "string", + "description": "Amount to approve with correct decimal places", + "example": "1000000000000000000" + }, + "network": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "Ethereum" + }, + "chainId": { + "type": "number", + "example": 1 + } + }, + "required": [ + "name", + "chainId" + ] + } + }, + "required": [ + "abi", + "address", + "functionName", + "blindpayContractAddress", + "amount", + "network" ] }, - "tracking_payment": { + "customer_local_amount": { + "type": [ + "number", + "null" + ], + "description": "Estimated amount in the currency of recipient bank account", + "example": 1000 + }, + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 128, + "example": "Memo code or description, only works with USD and BRL" + } + }, + "required": [ + "id", + "expires_at", + "commercial_quotation", + "blindpay_quotation", + "receiver_amount", + "sender_amount" + ] + }, + "QuoteIn": { + "type": "object", + "properties": { + "bank_account_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "description": "The bank account to pay. Exactly one of bank_account_id or payable_id must be set.", + "example": "ba_000000000000" + }, + "payable_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "description": "The payable to pay (boleto / PIX QR code). Exactly one of bank_account_id or payable_id must be set. The amount comes from the payable, so request_amount and currency_type are not accepted.", + "example": "pb_000000000000" + }, + "network": { + "type": "string", + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "description": "Check blindpay available networks", + "example": "sepolia" + }, + "token": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB" + ], + "description": "Check blindpay available tokens", + "example": "USDC" + }, + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 128, + "example": "Memo code or description, only works with USD and BRL" + }, + "partner_fee_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "example": "pf_000000000000" + }, + "refund_wallet_address": { + "type": [ + "string", + "null" + ], + "description": "Optional wallet address to receive the refund if this payout fails or is refunded. Must be a valid address on the quote network. When omitted, refunds are sent back to the sender wallet address.", + "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + }, + "currency_type": { + "type": "string", + "enum": [ + "sender", + "receiver" + ], + "description": "", + "example": "sender" + }, + "cover_fees": { + "type": [ + "boolean", + "null" + ], + "description": "If true, the sender will cover the fees. If false, the customer will cover the fees. Omitting it means false on bank account quotes. Payable quotes are always true.", + "example": true + }, + "request_amount": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "1000 represents 10.00, 2050 represents 20.50. Minimum 500 for bank account quotes; derived from the payable for payable quotes.", + "example": 1000 + } + }, + "required": [ + "network", + "token" + ] + }, + "PayoutOut": { + "type": "object", + "properties": { + "customer_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer id", + "example": "re_000000000000" + }, + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "po_000000000000" + }, + "status": { + "type": "string", + "enum": [ + "processing", + "failed", + "refunded", + "completed", + "on_hold" + ], + "description": "Payout general status", + "example": "processing" + }, + "sender_wallet_address": { + "type": "string", + "description": "Payout wallet address", + "example": "0x123...890" + }, + "signed_transaction": { + "type": [ + "string", + "null" + ], + "description": "Signed transaction", + "example": "AAA...Zey8y0A" + }, + "quote_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "qu_000000000000" + }, + "instance_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "partner_fee": { + "type": "integer", + "minimum": 0, + "default": 0, + "description": "Payout partner fee amount in cents (can be negative for rebates)", + "example": -25000 + }, + "tracking_transaction": { "type": "object", "properties": { "step": { @@ -15222,49 +18114,130 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], - "description": "Payment step", - "example": "on_hold" + "description": "Payout transaction step", + "example": "processing" }, - "provider_name": { + "status": { "type": [ "string", "null" ], "enum": [ - "Nvio Pagos", - "Brex", - "Stark Bank", - "JPMorgan Chase", - "HSBC", - "Inter", - "JP Morgan Chase", - "Bitso", - "Citi", - "CFSB", - "Triple A Technologies", - "Portage Bank", - "SSB Bank" + "failed", + "found" ], - "description": "Payment provider name", - "example": "HSBC" + "description": "Payout transaction status", + "example": "failed" }, - "provider_integration": { + "transaction_hash": { "type": [ "string", "null" ], - "enum": [ - "veem", - "zenus", - "checkbook", - "onemoney", - "bitso", - "starkbank", - "triplea", - "infinitus" - ], + "description": "Blockchain transaction hash", + "example": "0x123...890" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Payout transaction completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "provider_transaction_id": { + "type": [ + "string", + "null" + ], + "description": "Provider-side handle for the on-chain leg (e.g. Circle CPN payment id).", + "example": "67c12eae-b7bc-31cc-a5ef-623dcea82346" + }, + "provider_error_reason": { + "type": [ + "string", + "null" + ], + "description": "Provider error reason when the crypto collection fails (e.g. erc20_allowance_insufficient, ESTIMATION_ERROR: execution reverted)", + "example": "erc20_allowance_insufficient" + }, + "ledger_in_transaction_id": { + "type": [ + "string", + "null" + ], + "description": "Ledger transaction ID for the IN (crypto deposit) transaction" + }, + "ledger_out_transaction_id": { + "type": [ + "string", + "null" + ], + "description": "Ledger transaction ID for the OUT (fiat withdrawal) transaction" + } + }, + "required": [ + "step" + ] + }, + "tracking_payment": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Payment step", + "example": "on_hold" + }, + "provider_name": { + "type": [ + "string", + "null" + ], + "enum": [ + "Nvio Pagos", + "Brex", + "Stark Bank", + "JPMorgan Chase", + "HSBC", + "Inter", + "JP Morgan Chase", + "Bitso", + "Citi", + "CFSB", + "Triple A Technologies", + "BCB Group", + "Portage Bank", + "NMI" + ], + "description": "Payment provider name", + "example": "HSBC" + }, + "provider_integration": { + "type": [ + "string", + "null" + ], + "enum": [ + "veem", + "zenus", + "checkbook", + "onemoney", + "bitso", + "starkbank", + "triplea", + "infinitus", + "portage_g" + ], "description": "Machine-readable integration that executed the fiat leg. Unlike provider_name (a client-facing bank label), this uniquely identifies the integration — e.g. zenus vs checkbook, which share the \"JPMorgan Chase\" label.", "example": "zenus" }, @@ -15298,6 +18271,15 @@ "description": "Provider error reason when payment fails (e.g. invalid_key, wrong_parameters)", "example": "invalid_key" }, + "returned_amount": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "Amount (in cents of the payout currency) the beneficiary bank sent back after the payment was delivered. May be lower than the amount sent when the return is partial.", + "example": 5000 + }, "provider_uetr": { "type": [ "string", @@ -15334,6 +18316,19 @@ "description": "Clearing system that processed the payment (e.g. FED, CHIPS, ACH, SWIFT).", "example": "FED" }, + "forced_provider": { + "type": [ + "string", + "null" + ], + "enum": [ + "zenus", + "veem", + "infinitus_portage" + ], + "description": "Ops-set per-payout provider override (backoffice Reroute tab). When present it wins over the instance payment_route and default routing at send time. Left in place after the send as an audit marker of the forced route.", + "example": "veem" + }, "recipient_name": { "type": [ "string", @@ -15422,83 +18417,69 @@ ], "description": "Payment completed date", "example": "2011-10-05T14:48:00.000Z" - } - }, - "required": [ - "step" - ] - }, - "tracking_transaction": { - "type": "object", - "properties": { - "step": { - "type": "string", - "enum": [ - "processing", - "on_hold", - "pending_review", - "completed" - ], - "description": "Payout transaction step", - "example": "processing" }, - "status": { + "refund_review_reason": { "type": [ "string", "null" ], "enum": [ - "failed", - "found" - ], - "description": "Payout transaction status", - "example": "failed" - }, - "transaction_hash": { - "type": [ - "string", - "null" - ], - "description": "Blockchain transaction hash", - "example": "0x123...890" - }, - "completed_at": { + "amount_threshold", + "time_window", + "late_cancellation_no_live_run", + "master_account_return", + "policy_always_review", + "operator_requested", + "partial_return" + ], + "description": "Why the payout was routed to the Pending Refunds review queue instead of auto-refunding after a provider cancellation", + "example": "amount_threshold" + }, + "refund_review_detected_at": { "type": [ "string", "null" ], - "description": "Payout transaction completed date", + "description": "When the provider cancellation was routed to the Pending Refunds review queue", "example": "2011-10-05T14:48:00.000Z" }, - "provider_transaction_id": { + "refund_review_actioned_at": { "type": [ "string", "null" ], - "description": "Provider-side handle for the on-chain leg (e.g. Circle CPN payment id).", - "example": "67c12eae-b7bc-31cc-a5ef-623dcea82346" + "description": "Atomic claim marker: set the moment an operator approves a Pending Refunds entry, before the refund is sent, so a concurrent approve call cannot re-claim the same payout", + "example": "2011-10-05T14:48:00.000Z" }, - "provider_error_reason": { + "review_source": { "type": [ "string", "null" ], - "description": "Provider error reason when the crypto collection fails (e.g. erc20_allowance_insufficient, ESTIMATION_ERROR: execution reverted)", - "example": "erc20_allowance_insufficient" + "description": "Primary risk source that sent this payout to manual review", + "example": "nested_third_party" }, - "ledger_in_transaction_id": { + "review_sources": { "type": [ - "string", + "array", "null" ], - "description": "Ledger transaction ID for the IN (crypto deposit) transaction" + "items": { + "type": "string" + }, + "description": "Every risk source that sent this payout to manual review", + "example": [ + "nested_third_party", + "seon_review" + ] }, - "ledger_out_transaction_id": { + "review_context": { "type": [ - "string", + "object", "null" ], - "description": "Ledger transaction ID for the OUT (fiat withdrawal) transaction" + "additionalProperties": {}, + "description": "Structured risk context for manual review" } }, "required": [ @@ -15517,6 +18498,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Payout liquidity step", @@ -15573,6 +18555,70 @@ "step" ] }, + "tracking_complete": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "status": { + "type": [ + "string", + "null" + ], + "enum": [ + "tokens_refunded", + "paid" + ], + "description": "Complete status", + "example": "tokens_refunded" + }, + "refund_reason": { + "type": [ + "string", + "null" + ], + "description": "Reason for refund when tokens are returned to sender", + "example": "fiat_payment_failed" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "provider_transaction_id": { + "type": [ + "string", + "null" + ], + "description": "Provider-side handle for the refund transaction (e.g. Circle transaction id)", + "example": "67c12eae-b7bc-31cc-a5ef-623dcea82346" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + } + }, + "required": [ + "step" + ] + }, "tracking_documents": { "type": [ "object", @@ -15585,6 +18631,7 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], "description": "Documents step", @@ -15623,2423 +18670,1869 @@ "step" ] }, - "customer_id": { + "jpm_track_data": { + "type": [ + "object", + "null" + ], + "properties": { + "jpm_trace_number": { + "type": [ + "string", + "null" + ], + "description": "JPM trace number", + "example": "317802200000565" + }, + "jpm_processing_status": { + "type": [ + "string", + "null" + ], + "description": "JPM processing status", + "example": "Completed" + }, + "extended_tracking_status": { + "type": [ + "string", + "null" + ], + "description": "Extended tracking status from JPM", + "example": "Delivered to next bank" + }, + "jpm_reference_number": { + "type": [ + "string", + "null" + ], + "description": "JPM reference number", + "example": "9483400364JO" + }, + "uetr": { + "type": [ + "string", + "null" + ], + "description": "Unique end-to-end transaction reference", + "example": "4ad5f98a-5279-410a-99a2-39a729aceb35" + }, + "fed_imad": { + "type": [ + "string", + "null" + ], + "description": "Fed IMAD number (Wire payments only)", + "example": "1230MMQFMP2L034796" + }, + "payment_date": { + "type": [ + "string", + "null" + ], + "description": "Payment date", + "example": "Dec 30 2025" + }, + "payment_amount": { + "type": [ + "string", + "null" + ], + "description": "Payment amount", + "example": "3,914.00" + }, + "payment_currency": { + "type": [ + "string", + "null" + ], + "description": "Payment currency", + "example": "USD" + } + } + }, + "cpn_payment_id": { "type": [ "string", "null" ], - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" + "description": "Circle CPN payment id", + "example": "f06dbc45-58a4-389f-beb8-581c3fafff3c" }, - "bank_account_id": { + "created_at": { "type": [ "string", "null" ], - "minLength": 15, - "maxLength": 15, - "example": "ba_000000000000" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" }, - "offramp_wallet_id": { + "updated_at": { "type": [ "string", "null" ], - "minLength": 15, - "maxLength": 15, - "example": "ow_000000000000" - } - }, - "required": [ - "id", - "status", - "sender_wallet_address", - "tracking_complete", - "tracking_payment", - "tracking_transaction" - ] - }, - "PayoutOnStellarIn": { - "type": "object", - "properties": { - "quote_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "qu_000000000000" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" }, - "signed_transaction": { + "image_url": { "type": [ "string", "null" ], - "description": "Signed transaction", - "example": "AAA...Zey8y0A" + "format": "uri", + "example": "https://example.com/image.png" }, - "sender_wallet_address": { - "type": "string", - "description": "Payout wallet address", - "example": "0x123...890" - } - }, - "required": [ - "quote_id", - "sender_wallet_address" - ] - }, - "PayoutOnSolanaIn": { - "type": "object", - "properties": { - "quote_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "qu_000000000000" + "first_name": { + "type": [ + "string", + "null" + ], + "example": "John" }, - "signed_transaction": { + "last_name": { "type": [ "string", "null" ], - "description": "Signed transaction", - "example": "AAA...Zey8y0A" + "example": "Doe" }, - "sender_wallet_address": { - "type": "string", - "description": "Payout wallet address", - "example": "0x123...890" - } - }, - "required": [ - "quote_id", - "sender_wallet_address" - ] - }, - "PayoutOnEvmIn": { - "type": "object", - "properties": { - "quote_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "qu_000000000000" + "legal_name": { + "type": [ + "string", + "null" + ], + "example": "Company Name Inc." }, - "sender_wallet_address": { - "type": "string", - "description": "Payout wallet address", - "example": "0x123...890" - } - }, - "required": [ - "quote_id", - "sender_wallet_address" - ] - }, - "SubmitPayoutDocumentsIn": { - "type": "object", - "properties": { - "transaction_document_type": { + "network": { "type": "string", "enum": [ - "invoice", - "purchase_order", - "delivery_slip", - "contract", - "customs_declaration", - "bill_of_lading", - "others" + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" ], - "description": "Document type", - "example": "invoice" - }, - "transaction_document_id": { - "type": "string", - "minLength": 1, - "maxLength": 512, - "description": "Document identifier (invoice number, contract ID, etc.)", - "example": "INV-12345" + "description": "Check blindpay available networks", + "example": "sepolia" }, - "transaction_document_file": { + "token": { "type": "string", - "format": "uri", - "description": "URL to the uploaded document", - "example": "https://example.com/document.pdf" + "enum": [ + "USDC", + "USDT", + "USDB" + ], + "description": "Check blindpay available tokens", + "example": "USDC" }, "description": { - "type": "string", + "type": [ + "string", + "null" + ], "maxLength": 128, - "description": "Optional payment description/memo (max 128 chars)", - "example": "Payment for services - Invoice #12345" - } - }, - "required": [ - "transaction_document_type", - "transaction_document_id", - "transaction_document_file" - ] - }, - "AvailableBankDetails": { - "type": "array", - "items": { - "type": "object", - "properties": { - "label": { - "type": "string", - "example": "Account Number" - }, - "regex": { - "type": "string", - "example": "^[0-9]{9}$" - }, - "key": { - "type": "string", - "enum": [ - "type", - "name", - "status", - "recipient_relationship", - "swift_payment_code", - "pix_key", - "force_cpf_cnpj", - "beneficiary_name", - "routing_number", - "account_number", - "account_type", - "account_class", - "address_line_1", - "address_line_2", - "city", - "state_province_region", - "country", - "postal_code", - "checkbook_account_id", - "checkbook_user_key", - "onemoney_external_account_id", - "pix_safe_bank_code", - "pix_safe_branch_code", - "pix_safe_cpf_cnpj", - "ted_bank_code", - "ted_branch_code", - "ted_cpf_cnpj", - "spei_protocol", - "spei_institution_code", - "spei_clabe", - "transfers_type", - "transfers_account", - "ach_cop_beneficiary_first_name", - "ach_cop_beneficiary_last_name", - "ach_cop_document_id", - "ach_cop_document_type", - "ach_cop_email", - "ach_cop_bank_code", - "ach_cop_bank_account", - "swift_code_bic", - "swift_account_holder_name", - "swift_account_number_iban", - "swift_beneficiary_address_line_1", - "swift_beneficiary_address_line_2", - "swift_beneficiary_country", - "swift_beneficiary_city", - "swift_beneficiary_state_province_region", - "swift_beneficiary_postal_code", - "swift_bank_name", - "swift_bank_address_line_1", - "swift_bank_address_line_2", - "swift_bank_country", - "swift_bank_city", - "swift_bank_state_province_region", - "swift_bank_postal_code", - "swift_ifsc_branch_code", - "swift_intermediary_bank_swift_code_bic", - "swift_intermediary_bank_account_number_iban", - "swift_intermediary_bank_name", - "swift_intermediary_bank_country", - "sepa_iban", - "sepa_beneficiary_bic", - "sepa_beneficiary_legal_name", - "sepa_beneficiary_address_line_1", - "sepa_beneficiary_address_line_2", - "sepa_beneficiary_city", - "sepa_beneficiary_state_province_region", - "sepa_beneficiary_postal_code", - "sepa_beneficiary_country", - "business_industry", - "phone_number", - "tax_id", - "date_of_birth" - ], - "example": "account_number" - }, - "items": { - "type": "array", - "items": { - "type": "object", - "properties": { - "label": { - "type": "string", - "example": "United States of America" - }, - "value": { - "type": "string", - "example": "US" - }, - "is_active": { - "type": "boolean", - "example": true - } - }, - "required": [ - "label", - "value" - ] - } - }, - "required": { - "type": [ - "boolean", - "null" - ], - "example": false - }, - "requiredWhen": { - "type": "object", - "properties": { - "field": { - "type": "string", - "enum": [ - "type", - "name", - "status", - "recipient_relationship", - "swift_payment_code", - "pix_key", - "force_cpf_cnpj", - "beneficiary_name", - "routing_number", - "account_number", - "account_type", - "account_class", - "address_line_1", - "address_line_2", - "city", - "state_province_region", - "country", - "postal_code", - "checkbook_account_id", - "checkbook_user_key", - "onemoney_external_account_id", - "pix_safe_bank_code", - "pix_safe_branch_code", - "pix_safe_cpf_cnpj", - "ted_bank_code", - "ted_branch_code", - "ted_cpf_cnpj", - "spei_protocol", - "spei_institution_code", - "spei_clabe", - "transfers_type", - "transfers_account", - "ach_cop_beneficiary_first_name", - "ach_cop_beneficiary_last_name", - "ach_cop_document_id", - "ach_cop_document_type", - "ach_cop_email", - "ach_cop_bank_code", - "ach_cop_bank_account", - "swift_code_bic", - "swift_account_holder_name", - "swift_account_number_iban", - "swift_beneficiary_address_line_1", - "swift_beneficiary_address_line_2", - "swift_beneficiary_country", - "swift_beneficiary_city", - "swift_beneficiary_state_province_region", - "swift_beneficiary_postal_code", - "swift_bank_name", - "swift_bank_address_line_1", - "swift_bank_address_line_2", - "swift_bank_country", - "swift_bank_city", - "swift_bank_state_province_region", - "swift_bank_postal_code", - "swift_ifsc_branch_code", - "swift_intermediary_bank_swift_code_bic", - "swift_intermediary_bank_account_number_iban", - "swift_intermediary_bank_name", - "swift_intermediary_bank_country", - "sepa_iban", - "sepa_beneficiary_bic", - "sepa_beneficiary_legal_name", - "sepa_beneficiary_address_line_1", - "sepa_beneficiary_address_line_2", - "sepa_beneficiary_city", - "sepa_beneficiary_state_province_region", - "sepa_beneficiary_postal_code", - "sepa_beneficiary_country", - "business_industry", - "phone_number", - "tax_id", - "date_of_birth" - ], - "example": "country" - }, - "operator": { - "type": "string", - "enum": [ - "in", - "eq", - "notIn", - "notEq" - ], - "example": "in" - }, - "values": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "US", - "GB" - ] - } - }, - "required": [ - "field", - "operator", - "values" - ], - "example": { - "field": "country", - "operator": "in", - "values": [ - "US", - "GB" - ] - } - } + "example": "Memo code or description, only works with USD and BRL" }, - "required": [ - "label", - "regex", - "key" - ] - } - }, - "AvailableRails": { - "type": "array", - "items": { - "type": "object", - "properties": { - "label": { - "type": "string", - "example": "Domestic Wire" - }, - "value": { - "type": "string", - "enum": [ - "wire", - "ach", - "pix", - "pix_safe", - "ted", - "spei_bitso", - "transfers_bitso", - "ach_cop_bitso", - "international_swift", - "rtp", - "sepa" - ], - "example": "wire" - }, - "country": { - "type": "string", - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "US" - } + "sender_amount": { + "type": [ + "number", + "null" + ], + "description": "10.10 USDC needs to be sent to bank account blockchain address", + "example": 1010 }, - "required": [ - "label", - "value", - "country" - ] - } - }, - "AvailableNaicsList": { - "type": "array", - "items": { - "type": "object", - "properties": { - "label": { - "type": "string", - "example": "(339910) Jewelry and Silverware Manufacturing" - }, - "value": { - "type": "string", - "example": "339910" - } - }, - "required": [ - "label", - "value" - ] - } - }, - "SwiftCodeItem": { - "type": "object", - "properties": { - "id": { - "type": "string", - "example": "416" - }, - "bank": { - "type": "string", - "example": "BANK OF AMERICA, N.A." - }, - "city": { - "type": "string", - "example": "NEW JERSEY" - }, - "branch": { - "type": "string", - "example": "LENDING SERVICES AND OPERATIONS (LSOP)" - }, - "swiftCode": { - "type": "string", - "example": "BOFAUS3NLMA" - }, - "swiftCodeLink": { - "type": "string", - "example": "https://bank.codes/swift-code/united-states/bofaus3nlma/" + "receiver_amount": { + "type": [ + "number", + "null" + ], + "description": "52.40 BRL", + "example": 5240 }, - "country": { - "type": "string", - "example": "United States" + "partner_fee_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "example": "pf_000000000000" }, - "countrySlug": { - "type": "string", - "example": "united-states" - } - }, - "required": [ - "id", - "bank", - "city", - "branch", - "swiftCode", - "swiftCodeLink", - "country", - "countrySlug" - ] - }, - "SwiftCodeResponse": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SwiftCodeItem" - } - }, - "UpdateInstanceIn": { - "type": "object", - "properties": { - "name": { - "type": "string", - "minLength": 3, - "maxLength": 100, - "example": "My Instance" + "partner_fee_amount": { + "type": [ + "number", + "null" + ], + "default": 0, + "description": "1.5 USDC", + "example": 150 }, - "customer_invite_redirect_url": { + "commercial_quotation": { "type": [ - "string", + "number", "null" ], - "format": "uri", - "example": "https://blindpay.com" + "description": "1 USD = 4.95 BRL", + "example": 495 }, - "email_notifications": { - "type": "boolean", - "default": true, - "description": "Whether email notifications are enabled for this instance", - "example": true + "blindpay_quotation": { + "type": [ + "number", + "null" + ], + "description": "1 USD = 4.85 BRL (commercial quotation - (blindpay taxes))", + "example": 485 }, - "require_passkey": { - "type": "boolean", - "default": false, - "description": "Whether passkey verification is required for protected actions", - "example": false + "total_fee_amount": { + "type": [ + "number", + "null" + ], + "default": 0, + "description": "1.5 USDC", + "example": 1.5 }, - "compliance_emails": { + "customer_local_amount": { "type": [ - "array", + "number", "null" ], - "items": { - "type": "string", - "format": "email" - }, - "maxItems": 20, - "description": "When non-empty, compliance Request for Information emails are sent only to these addresses instead of all instance members", - "example": [ - "compliance@example.com" - ] + "description": "Estimated amount in the currency of recipient bank account", + "example": 1000 }, - "customer_rfi_emails_enabled": { - "type": "boolean", - "description": "Whether customer (customer) Request for Information notification emails are sent for this instance. Omit to leave unchanged.", - "example": true - } - }, - "required": [ - "name" - ] - }, - "UpdateInstanceMemberIn": { - "type": "object", - "properties": { - "user_role": { + "currency": { "type": "string", "enum": [ - "owner", - "admin", - "finance", - "checker", - "operations", - "developer", - "viewer" + "BRL", + "USD", + "MXN", + "COP", + "ARS", + "EUR", + "GBP" ], - "example": "admin" - } - }, - "required": [ - "user_role" - ] - }, - "MigrateInstanceOwnershipIn": { - "type": "object", - "properties": { - "user_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "us_000000000000" - } - }, - "required": [ - "user_id" - ] - }, - "FeeOptions": { - "type": "object", - "properties": { - "payin_flat": { - "type": "integer", - "description": "Payin flat fee in cents", - "example": 40 - }, - "payin_percentage": { - "type": "integer", - "description": "Payin percentage fee in basis points", - "example": 50 + "description": "ISO 4271 currency code", + "example": "BRL" }, - "payout_flat": { - "type": "integer", - "description": "Payout flat fee in cents", - "example": 40 + "transaction_fee_amount": { + "type": [ + "number", + "null" + ], + "description": "Transaction fee in cents (percentage-based fee)", + "example": 100 }, - "payout_percentage": { - "type": "integer", - "description": "Payout percentage fee in basis points", + "billing_fee_amount": { + "type": [ + "number", + "null" + ], + "description": "Billing fee in cents (charged via invoice at the end of the month)", "example": 50 - } - }, - "required": [ - "payin_flat", - "payin_percentage", - "payout_flat", - "payout_percentage" - ] - }, - "GetFeesOut": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "fe_000000000000" - }, - "instance_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "ach": { - "$ref": "#/components/schemas/FeeOptions" - }, - "domestic_wire": { - "$ref": "#/components/schemas/FeeOptions" - }, - "rtp": { - "$ref": "#/components/schemas/FeeOptions" - }, - "international_swift": { - "$ref": "#/components/schemas/FeeOptions" - }, - "pix": { - "$ref": "#/components/schemas/FeeOptions" - }, - "pix_safe": { - "$ref": "#/components/schemas/FeeOptions" - }, - "ted": { - "allOf": [ - { - "$ref": "#/components/schemas/FeeOptions" - }, - { - "type": [ - "object", - "null" - ] - } - ] - }, - "ach_colombia": { - "$ref": "#/components/schemas/FeeOptions" }, - "transfers_3": { - "$ref": "#/components/schemas/FeeOptions" + "transaction_document_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "example": "https://example.com/image.png" }, - "spei": { - "$ref": "#/components/schemas/FeeOptions" + "transaction_document_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "invoice", + "purchase_order", + "delivery_slip", + "contract", + "customs_declaration", + "bill_of_lading", + "others" + ], + "example": "invoice" }, - "sepa": { - "$ref": "#/components/schemas/FeeOptions" + "transaction_document_id": { + "type": [ + "string", + "null" + ], + "maxLength": 512, + "example": "1234567890" }, - "tron": { - "$ref": "#/components/schemas/FeeOptions" + "name": { + "type": [ + "string", + "null" + ], + "example": "Bank Account Name" }, - "ethereum": { - "$ref": "#/components/schemas/FeeOptions" + "type": { + "type": [ + "string", + "null" + ], + "enum": [ + "wire", + "ach", + "pix", + "pix_safe", + "ted", + "spei_bitso", + "transfers_bitso", + "ach_cop_bitso", + "international_swift", + "rtp", + "sepa", + "faster_payments" + ], + "example": "wire" }, - "polygon": { - "$ref": "#/components/schemas/FeeOptions" + "pix_key": { + "type": [ + "string", + "null" + ], + "example": "14947677768" }, - "base": { - "$ref": "#/components/schemas/FeeOptions" + "pix_safe_bank_code": { + "type": [ + "string", + "null" + ], + "pattern": "^\\d{4,8}$", + "example": "00416968" }, - "arbitrum": { - "$ref": "#/components/schemas/FeeOptions" + "pix_safe_branch_code": { + "type": [ + "string", + "null" + ], + "pattern": "^\\d{4}(-\\d)?$", + "example": "0001" }, - "stellar": { - "$ref": "#/components/schemas/FeeOptions" + "pix_safe_cpf_cnpj": { + "type": [ + "string", + "null" + ], + "example": "12345678901" }, - "solana": { - "$ref": "#/components/schemas/FeeOptions" + "ted_bank_code": { + "type": [ + "string", + "null" + ], + "pattern": "^\\d{3,5}$", + "example": "033" }, - "created_at": { + "ted_branch_code": { "type": [ "string", "null" ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" + "pattern": "^\\d{4}(-\\d)?$", + "example": "0001" }, - "updated_at": { + "ted_cpf_cnpj": { "type": [ "string", "null" ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" - } - }, - "required": [ - "id", - "instance_id", - "ach", - "domestic_wire", - "rtp", - "international_swift", - "pix", - "pix_safe", - "ach_colombia", - "transfers_3", - "spei", - "sepa", - "tron", - "ethereum", - "polygon", - "base", - "arbitrum", - "stellar", - "solana" - ] - }, - "InitiateTosOut": { - "type": "object", - "properties": { - "url": { - "type": "string", - "format": "uri", - "example": "https://app.blindpay.com/e/terms-of-service?session_token=SESSION_TOKEN_FROM_INITIATE_TOS_RESPONSE" - } - }, - "required": [ - "url" - ] - }, - "InitiateTosIn": { - "type": "object", - "properties": { - "idempotency_key": { - "type": "string", - "format": "uuid", - "example": "123e4567-e89b-12d3-a456-426614174000" + "example": "12345678901" }, - "customer_id": { + "account_number": { "type": [ "string", "null" ], - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" + "example": "1001001234" }, - "redirect_url": { + "routing_number": { "type": [ "string", "null" ], - "format": "uri" - } - }, - "required": [ - "idempotency_key" - ] - }, - "WebhookEndpointOut": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "we_000000000000" - } - }, - "required": [ - "id" - ] - }, - "WebhookEndpointIn": { - "type": "object", - "properties": { - "url": { - "type": "string", - "format": "uri", - "example": "https://example.com/webhook" + "example": "012345678" }, - "events": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "customer.new", - "customer.update", - "customer.delete", - "bankAccount.new", - "payout.new", - "payout.update", - "payout.complete", - "payout.partnerFee", - "blockchainWallet.new", - "payin.new", - "payin.update", - "payin.complete", - "payin.partnerFee", - "tos.accept", - "limitIncrease.new", - "limitIncrease.update", - "virtualAccount.new", - "virtualAccount.complete", - "transfer.new", - "transfer.update", - "transfer.complete", - "wallet.new", - "wallet.inbound" - ] - }, - "example": [ - "customer.new" - ] - } - }, - "required": [ - "url", - "events" - ] - }, - "WebhookEndpoint": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "we_000000000000" + "country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "US" }, - "url": { - "type": "string", - "format": "uri", - "example": "https://example.com/webhook" + "account_class": { + "type": [ + "string", + "null" + ], + "enum": [ + "individual", + "business" + ], + "example": "individual" }, - "events": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "customer.new", - "customer.update", - "customer.delete", - "bankAccount.new", - "payout.new", - "payout.update", - "payout.complete", - "payout.partnerFee", - "blockchainWallet.new", - "payin.new", - "payin.update", - "payin.complete", - "payin.partnerFee", - "tos.accept", - "limitIncrease.new", - "limitIncrease.update", - "virtualAccount.new", - "virtualAccount.complete", - "transfer.new", - "transfer.update", - "transfer.complete", - "wallet.new", - "wallet.inbound" - ] - }, - "example": [ - "customer.new" - ] + "address_line_1": { + "type": [ + "string", + "null" + ], + "example": "Address line 1" }, - "last_event_at": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "string" - }, - { - "type": "null" - } + "address_line_2": { + "type": [ + "string", + "null" ], - "example": "2024-01-01T00:00:00.000Z" + "example": "Address line 2" }, - "instance_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" + "city": { + "type": [ + "string", + "null" + ], + "example": "City" }, - "created_at": { + "state_province_region": { "type": [ "string", "null" ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" + "example": "State/Province/Region" }, - "updated_at": { + "postal_code": { "type": [ "string", "null" ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" - } - }, - "required": [ - "id", - "url", - "events", - "instance_id" - ] - }, - "PortalAccessOut": { - "type": "object", - "properties": { - "url": { - "type": "string", - "format": "uri", - "example": "https://example.com/webhook" - } - }, - "required": [ - "url" - ] - }, - "PayinOut": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" + "example": "Postal code" }, - "pix_code": { + "account_type": { "type": [ "string", "null" ], - "description": "PIX code", - "example": "00020101021226790014br.gov.bcb.pix2557brcode.starkinfra.com/v2/bcf07f6c4110454e9fd6f120bab13e835204000053039865802BR5915Blind Pay, Inc.6010Vila Velha62070503***6304BCAB" + "enum": [ + "checking", + "saving" + ], + "example": "checking" }, - "memo_code": { + "ach_cop_beneficiary_first_name": { "type": [ "string", "null" ], - "description": "Memo code", - "example": "8K45GHBNT6BQ6462" + "example": "Fernando" }, - "clabe": { + "ach_cop_bank_account": { "type": [ "string", "null" ], - "description": "CLABE code", - "example": "014027000000000008" + "example": "12345678" }, - "status": { - "type": "string", - "enum": [ - "processing", - "on_hold", - "failed", - "refunded", - "completed" + "ach_cop_bank_code": { + "type": [ + "string", + "null" ], - "description": "Payin general status", - "example": "processing" + "example": "051" }, - "payin_quote_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "pq_000000000000" + "ach_cop_beneficiary_last_name": { + "type": [ + "string", + "null" + ], + "example": "Guzman Alarcón" }, - "instance_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" + "ach_cop_document_id": { + "type": [ + "string", + "null" + ], + "example": "1661105408" }, - "customer_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" + "ach_cop_document_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "CC", + "CE", + "NIT", + "PASS", + "PEP" + ], + "description": "CC - Cédula de Ciudadanía; CE - Cédula de Extranjería; NIT - Número de Identificación Tributaria; PASS - Passport; PEP - Permiso Especial de Permanencia", + "example": "CC" }, - "partner_fee": { - "type": "integer", - "minimum": 0, - "default": 0, - "description": "Payin partner fee amount in cents", - "example": 25000 + "ach_cop_email": { + "type": [ + "string", + "null" + ], + "example": "fernando.guzman@gmail.com" }, - "tracking_transaction": { - "type": "object", - "properties": { - "step": { - "type": "string", - "enum": [ - "processing", - "on_hold", - "pending_review", - "completed" - ], - "description": "Payin transaction step", - "example": "processing" - }, - "status": { - "type": [ - "string", - "null" - ], - "enum": [ - "failed", - "completed" - ], - "description": "Payin transaction status", - "example": "failed" - }, - "external_id": { - "type": [ - "string", - "null" - ], - "description": "Payin transaction external id", - "example": "12345678" - }, - "completed_at": { - "type": [ - "string", - "null" - ], - "description": "Payin transaction completed date", - "example": "2011-10-05T14:48:00.000Z" - }, - "transaction_hash": { - "type": [ - "string", - "null" - ], - "description": "Blockchain transaction hash", - "example": "0x123...890" - }, - "provider_name": { - "type": [ - "string", - "null" - ], - "enum": [ - "Nvio Pagos", - "Brex", - "Stark Bank", - "JPMorgan Chase", - "HSBC", - "Inter", - "JP Morgan Chase", - "Bitso", - "Citi", - "CFSB", - "Triple A Technologies", - "Portage Bank", - "SSB Bank" - ], - "description": "Payment provider name", - "example": "HSBC" - }, - "provider_transaction_id": { - "type": [ - "string", - "null" - ], - "description": "Payment provider transaction id", - "example": "" - }, - "sender_name": { - "type": [ - "string", - "null" - ], - "example": "John Doe Smith" - }, - "sender_bank_name": { - "type": [ - "string", - "null" - ], - "example": "Bank of America" - }, - "sender_tax_id": { - "type": [ - "string", - "null" - ], - "example": "123.456.789-10" - }, - "sender_bank_code": { - "type": [ - "string", - "null" - ], - "example": "00416968" - }, - "sender_account_number": { - "type": [ - "string", - "null" - ], - "example": "1234567890" - }, - "end_to_end_id": { - "type": [ - "string", - "null" - ], - "description": "BACEN Pix end-to-end transaction ID (govt Pix ID)", - "example": "E20018183202603311320vm6ALFpJpsS" - }, - "trace_number": { - "type": [ - "string", - "null" - ], - "example": "1234567890" - }, - "transaction_reference": { - "type": [ - "string", - "null" - ], - "example": "1234567890" - }, - "description": { - "type": [ - "string", - "null" - ], - "example": "Payment from John Doe Smith" - }, - "pse_instruction": { - "type": [ - "object", - "null" - ], - "properties": { - "payment_link": { - "type": "string", - "description": "PSE payment link URL", - "example": "https://pse.example.com/payment/abc123" - }, - "fid": { - "type": "string", - "description": "PSE funding identifier for webhook matching", - "example": "fid_abc123" - }, - "full_name": { - "type": "string", - "description": "PSE payer full name", - "example": "Juan Pérez García" - }, - "tax_id": { - "type": "string", - "description": "PSE payer document number", - "example": "1234567890" - }, - "document_type": { - "type": "string", - "enum": [ - "CC", - "NIT" - ], - "description": "PSE payer document type", - "example": "CC" - }, - "phone": { - "type": "string", - "description": "PSE payer phone number", - "example": "+573001234567" - }, - "email": { - "type": "string", - "description": "PSE payer email", - "example": "juan@example.com" - }, - "bank_code": { - "type": [ - "string", - "null" - ], - "description": "PSE payer bank code", - "example": "1007" - } - }, - "required": [ - "payment_link", - "fid", - "full_name", - "tax_id", - "document_type", - "phone", - "email" - ] - }, - "transfers_instruction": { - "type": [ - "object", - "null" - ], - "properties": { - "account": { - "type": "string", - "description": "CVU/CBU/Alias account number", - "example": "0000003100012389237485" - }, - "type": { - "type": "string", - "enum": [ - "CVU", - "CBU", - "ALIAS" - ], - "description": "Account type (CVU, CBU, or ALIAS)", - "example": "CVU" - }, - "tax_id": { - "type": [ - "string", - "null" - ], - "description": "CUIT/CUIL (normalized, digits only)", - "example": "20123456783" - } - }, - "required": [ - "account", - "type" - ] - }, - "ted_instruction": { - "type": [ - "object", - "null" - ], - "properties": { - "beneficiary_name": { - "type": "string", - "example": "Blind Pay, Inc." - }, - "tax_id": { - "type": "string", - "example": "57.599.376/0001-81" - }, - "bank_code": { - "type": "string", - "example": "665" - }, - "bank_name": { - "type": "string", - "example": "STARK BANK S.A." - }, - "branch_code": { - "type": "string", - "example": "5340" - }, - "account_number": { - "type": "string", - "example": "01011707084-8" - }, - "account_type": { - "type": "string", - "example": "checking" - } - }, - "required": [ - "beneficiary_name", - "tax_id", - "bank_code", - "bank_name", - "branch_code", - "account_number", - "account_type" - ] - } - }, - "required": [ - "step" - ] - }, - "tracking_payment": { - "type": "object", - "properties": { - "step": { - "type": "string", - "enum": [ - "processing", - "on_hold", - "pending_review", - "completed" - ], - "description": "Payment step", - "example": "on_hold" - }, - "provider_name": { - "type": [ - "string", - "null" - ], - "description": "Payment provider name", - "example": "blockchain" - }, - "completed_at": { - "type": [ - "string", - "null" - ], - "description": "Payment completed date", - "example": "2011-10-05T14:48:00.000Z" - }, - "review_source": { - "type": [ - "string", - "null" - ], - "description": "Primary risk source that sent this payin to manual review", - "example": "seon_review" - }, - "review_context": { - "type": [ - "object", - "null" - ], - "additionalProperties": {}, - "description": "Structured risk context for manual review" - }, - "review_sources": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Every risk source that flagged this payin on the pending review", - "example": [ - "seon_review", - "new_instance" - ] - }, - "review_contexts": { - "type": [ - "object", - "null" - ], - "additionalProperties": {}, - "description": "Structured risk context per flagging source" - }, - "approved_risk_sources": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Risk sources already approved by an analyst", - "example": [ - "seon_review" - ] - } - }, - "required": [ - "step" - ] - }, - "tracking_complete": { - "type": "object", - "properties": { - "step": { - "type": "string", - "enum": [ - "processing", - "on_hold", - "pending_review", - "completed" - ], - "description": "Complete step", - "example": "on_hold" - }, - "transaction_hash": { - "type": [ - "string", - "null" - ], - "description": "Complete transaction hash", - "example": "0x123...890" - }, - "completed_at": { - "type": [ - "string", - "null" - ], - "description": "Complete completed date", - "example": "2011-10-05T14:48:00.000Z" - } - }, - "required": [ - "step" - ] - }, - "manual_execution_status": { - "type": [ - "string", - "null" - ], - "enum": [ - "pending", - "concluded", - "failed" - ], - "description": "When non-null, the payin was created while the manual OTC liquidity toggle was ON. `pending` means an operator must convert BRL→USDT manually and click \"Mark concluded\"; `concluded` closes the internal flow. Customer-facing behavior is identical in either mode.", - "example": null - }, - "manual_concluded_at": { - "description": "When `manual_execution_status` transitioned to `concluded`. Postgres returns a Date; this transform normalizes to an ISO string for the SDK.", - "example": null - }, - "manual_concluded_by": { - "type": [ - "string", - "null" - ], - "description": "Identifier of the operator who marked the manual OTC concluded.", - "example": null - }, - "created_at": { + "beneficiary_name": { "type": [ "string", "null" ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" + "maxLength": 128, + "example": "Individual full name or business name" }, - "updated_at": { + "spei_clabe": { "type": [ "string", "null" ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" + "example": "5482347403740546" }, - "image_url": { + "spei_protocol": { "type": [ "string", "null" ], - "format": "uri", - "example": "https://example.com/image.png" - }, - "first_name": { - "type": [ - "string", - "null" + "enum": [ + "clabe", + "debitcard", + "phonenum" ], - "example": "John" + "description": "For debitcard and phonenum the spei_institution_code is required", + "example": "clabe" }, - "last_name": { + "spei_institution_code": { "type": [ "string", "null" ], - "example": "Doe" + "minLength": 5, + "maxLength": 5, + "example": "40002" }, - "legal_name": { + "swift_beneficiary_country": { "type": [ "string", "null" ], - "example": "Company Name Inc." - }, - "type": { - "type": "string", - "enum": [ - "individual", - "business" - ], - "example": "individual" - }, - "payment_method": { - "type": "string", - "enum": [ - "ach", - "wire", - "pix", - "ted", - "spei", - "transfers", - "pse", - "international_swift", - "rtp" - ], - "example": "pix" - }, - "sender_amount": { - "type": [ - "number", - "null" - ], - "description": "52.40 BRL needs to be sent in a pix transfer", - "example": 5240 - }, - "receiver_amount": { - "type": [ - "number", - "null" - ], - "description": "10.10 USDC", - "example": 1010 - }, - "token": { - "type": "string", "enum": [ - "USDC", - "USDT", - "USDB" - ], - "example": "USDC" - }, - "partner_fee_id": { - "type": [ - "string", - "null" - ], - "minLength": 15, - "maxLength": 15, - "example": "pf_000000000000" - }, - "partner_fee_amount": { - "type": [ - "number", - "null" + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" ], - "default": 0, - "description": "1.5 USDC", - "example": 150 + "example": "MX" }, - "total_fee_amount": { + "swift_code_bic": { "type": [ - "number", + "string", "null" ], - "default": 0, - "description": "1.53 USDC", - "example": 1.53 + "example": "123456789" }, - "commercial_quotation": { + "swift_account_holder_name": { "type": [ - "number", + "string", "null" ], - "description": "1 USD = 4.95 BRL", - "example": 495 + "example": "John Doe" }, - "blindpay_quotation": { + "swift_account_number_iban": { "type": [ - "number", + "string", "null" ], - "description": "1 USD = 5.05 BRL (commercial quotation + (blindpay taxes))", - "example": 505 - }, - "currency": { - "type": "string", - "enum": [ - "BRL", - "USD", - "MXN", - "COP", - "ARS", - "EUR" - ], - "description": "ISO 4271 currency code", - "example": "BRL" + "example": "123456789" }, - "billing_fee_amount": { + "sepa_iban": { "type": [ - "number", + "string", "null" ], - "description": "Billing fee in cents (charged at the end of the month)", - "example": 50 + "example": "DE89370400440532013000" }, - "transaction_fee_amount": { + "sepa_beneficiary_legal_name": { "type": [ - "number", + "string", "null" ], - "description": "Transaction fee in cents (percentage-based fee)", - "example": 100 + "maxLength": 128, + "example": "Hans Müller" }, - "is_otc": { + "sepa_beneficiary_address_line_1": { "type": [ - "boolean", + "string", "null" ], - "description": "If true, the payin quote is for an OTC (Over the Counter) transaction", - "example": false + "example": "Friedrichstraße 12" }, - "payer_rules": { + "sepa_beneficiary_city": { "type": [ - "object", + "string", "null" ], - "properties": { - "pix_allowed_tax_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string", - "example": "123.456.789-09" - } - }, - "transfers_allowed_tax_id": { - "type": [ - "string", - "null" - ], - "example": "20-12345678-3" - }, - "pse_allowed_tax_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string", - "example": "1234567890" - } - }, - "pse_full_name": { - "type": [ - "string", - "null" - ], - "maxLength": 50 - }, - "pse_document_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "CC", - "NIT" - ] - }, - "pse_document_number": { - "type": [ - "string", - "null" - ] - }, - "pse_email": { - "type": [ - "string", - "null" - ], - "format": "email" - }, - "pse_phone": { - "type": [ - "string", - "null" - ], - "pattern": "^\\+573\\d{9}$" - }, - "pse_bank_code": { - "type": [ - "string", - "null" - ] - } - }, - "example": { - "pix_allowed_tax_ids": [ - "123.456.789-09" - ], - "transfers_allowed_tax_id": "20-12345678-3", - "pse_allowed_tax_ids": [ - "1234567890" - ] - } - }, - "name": { - "type": "string", - "example": "Wallet Display Name" + "example": "Berlin" }, - "address": { + "sepa_beneficiary_postal_code": { "type": [ "string", "null" ], - "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" - }, - "network": { - "type": "string", - "enum": [ - "base", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "arbitrum", - "polygon", - "polygon_amoy", - "ethereum", - "stellar", - "stellar_testnet", - "tron", - "solana", - "solana_devnet" - ], - "example": "polygon" + "example": "10117" }, - "blindpay_bank_details": { + "sepa_beneficiary_country": { "type": [ - "object", + "string", "null" ], - "properties": { - "routing_number": { - "type": "string", - "default": "121145349", - "example": "121145349" - }, - "account_number": { - "type": "string", - "default": "621327727210181", - "example": "621327727210181" - }, - "account_type": { - "type": "string", - "default": "Business checking", - "example": "Business checking" - }, - "swift_bic_code": { - "type": [ - "string", - "null" - ], - "default": "CHASUS33", - "example": "CHASUS33" - }, - "ach": { - "type": [ - "object", - "null" - ], - "properties": { - "routing_number": { - "type": "string", - "example": "123456789" - }, - "account_number": { - "type": "string", - "example": "123456789" - } - }, - "required": [ - "routing_number", - "account_number" - ] - }, - "wire": { - "type": [ - "object", - "null" - ], - "properties": { - "routing_number": { - "type": "string", - "example": "123456789" - }, - "account_number": { - "type": "string", - "example": "123456789" - } - }, - "required": [ - "routing_number", - "account_number" - ] - }, - "rtp": { - "type": [ - "object", - "null" - ], - "properties": { - "routing_number": { - "type": "string", - "example": "123456789" - }, - "account_number": { - "type": "string", - "example": "123456789" - } - }, - "required": [ - "routing_number", - "account_number" - ] - }, - "beneficiary": { - "type": "object", - "properties": { - "name": { - "type": "string", - "default": "BlindPay, Inc.", - "example": "BlindPay, Inc." - }, - "address_line_1": { - "type": "string", - "default": "8 The Green, #19364", - "example": "8 The Green, #19364" - }, - "address_line_2": { - "type": "string", - "default": "Dover, DE 19901", - "example": "Dover, DE 19901" - } - } - }, - "receiving_bank": { - "type": "object", - "properties": { - "name": { - "type": "string", - "default": "CFSB", - "example": "CFSB" - }, - "address_line_1": { - "type": "string", - "default": "1 Letterman Drive, Building A, Suite A4-700", - "example": "1 Letterman Drive, Building A, Suite A4-700" - }, - "address_line_2": { - "type": "string", - "default": "San Francisco, CA 94129", - "example": "San Francisco, CA 94129" - } - } - }, - "swift_account_number": { - "type": [ - "string", - "null" - ], - "example": "GB50TCCL04140449730892" - }, - "swift_receiving_bank": { - "type": [ - "object", - "null" - ], - "properties": { - "name": { - "type": [ - "string", - "null" - ], - "example": "JPMorgan Chase" - }, - "address_line_1": { - "type": [ - "string", - "null" - ], - "example": "270 Park Ave" - }, - "address_line_2": { - "type": [ - "string", - "null" - ], - "example": "New York, NY, 10017-2070" - } - } - } - }, - "required": [ - "beneficiary", - "receiving_bank" - ] + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "DE" }, - "pse_payment_link": { + "faster_payments_sort_code": { "type": [ "string", "null" ], - "description": "PSE payment link (derived from tracking_transaction.pse_instruction)", - "example": "https://pse.example.com/payment/abc123" + "description": "UK bank sort code, 6 digits. Dashes and spaces are stripped.", + "example": "040004" }, - "pse_full_name": { + "faster_payments_account_number": { "type": [ "string", "null" ], - "description": "PSE payer full name", - "example": "Juan Pérez García" + "description": "UK bank account number, 8 digits.", + "example": "12345678" }, - "pse_tax_id": { + "faster_payments_beneficiary_legal_name": { "type": [ "string", "null" ], - "description": "PSE payer document number", - "example": "1234567890" + "maxLength": 128, + "example": "Oliver Smith" }, - "pse_document_type": { + "faster_payments_beneficiary_address_line_1": { "type": [ "string", "null" ], - "enum": [ - "CC", - "NIT" - ], - "description": "PSE payer document type", - "example": "CC" - } - }, - "required": [ - "id", - "status", - "payin_quote_id", - "instance_id", - "customer_id", - "tracking_transaction", - "tracking_payment", - "tracking_complete", - "type", - "payment_method", - "sender_amount", - "receiver_amount", - "token", - "commercial_quotation", - "blindpay_quotation", - "currency", - "name", - "network" - ] - }, - "CreatePayinOut": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "pi_000000000000" - }, - "status": { - "type": "string", - "enum": [ - "processing", - "on_hold", - "failed", - "refunded", - "completed" - ], - "description": "Payin general status", - "example": "processing" + "example": "221B Baker Street" }, - "pix_code": { + "faster_payments_beneficiary_city": { "type": [ "string", "null" ], - "description": "PIX code", - "example": "00020101021226790014br.gov.bcb.pix2557brcode.starkinfra.com/v2/bcf07f6c4110454e9fd6f120bab13e835204000053039865802BR5915Blind Pay, Inc.6010Vila Velha62070503***6304BCAB" + "example": "London" }, - "memo_code": { + "faster_payments_beneficiary_postal_code": { "type": [ "string", "null" ], - "description": "Memo code", - "example": "8K45GHBNT6BQ6462" + "example": "NW1 6XE" }, - "clabe": { + "faster_payments_beneficiary_country": { "type": [ "string", "null" ], - "description": "CLABE code", - "example": "014027000000000008" - }, - "partner_fee": { - "type": "integer", - "minimum": 0, - "default": 0, - "description": "Payin partner fee amount in cents", - "example": 25000 - }, - "tracking_complete": { - "type": "object", - "properties": { - "step": { - "type": "string", - "enum": [ - "processing", - "on_hold", - "pending_review", - "completed" - ], - "description": "Complete step", - "example": "on_hold" - }, - "transaction_hash": { - "type": [ - "string", - "null" - ], - "description": "Complete transaction hash", - "example": "0x123...890" - }, - "completed_at": { - "type": [ - "string", - "null" - ], - "description": "Complete completed date", - "example": "2011-10-05T14:48:00.000Z" - } - }, - "required": [ - "step" - ] - }, - "tracking_payment": { - "type": "object", - "properties": { - "step": { - "type": "string", - "enum": [ - "processing", - "on_hold", - "pending_review", - "completed" - ], - "description": "Payment step", - "example": "on_hold" - }, - "provider_name": { - "type": [ - "string", - "null" - ], - "description": "Payment provider name", - "example": "blockchain" - }, - "completed_at": { - "type": [ - "string", - "null" - ], - "description": "Payment completed date", - "example": "2011-10-05T14:48:00.000Z" - }, - "review_source": { - "type": [ - "string", - "null" - ], - "description": "Primary risk source that sent this payin to manual review", - "example": "seon_review" - }, - "review_context": { - "type": [ - "object", - "null" - ], - "additionalProperties": {}, - "description": "Structured risk context for manual review" - }, - "review_sources": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Every risk source that flagged this payin on the pending review", - "example": [ - "seon_review", - "new_instance" - ] - }, - "review_contexts": { - "type": [ - "object", - "null" - ], - "additionalProperties": {}, - "description": "Structured risk context per flagging source" - }, - "approved_risk_sources": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Risk sources already approved by an analyst", - "example": [ - "seon_review" - ] - } - }, - "required": [ - "step" - ] + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "GB" }, - "tracking_transaction": { + "transfers_account": { + "type": [ + "string", + "null" + ], + "example": "BM123123123123" + }, + "transfers_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "CVU", + "CBU", + "ALIAS" + ], + "example": "CVU" + }, + "bank_account_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "example": "ba_000000000000" + }, + "payable_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "description": "The payable this payout executes, when it pays a payable instead of a bank account.", + "example": "pb_000000000000" + }, + "has_virtual_account": { + "type": [ + "boolean", + "null" + ], + "description": "Has virtual account", + "example": true + }, + "sender_legal_name": { + "type": [ + "string", + "null" + ], + "description": "Legal name of the sending instance (originator), shown on the receipt", + "example": "LRB TRADING INVESTMENT L.L.C" + } + }, + "required": [ + "customer_id", + "id", + "status", + "sender_wallet_address", + "quote_id", + "instance_id", + "tracking_transaction", + "tracking_payment", + "tracking_complete", + "network", + "token", + "sender_amount", + "receiver_amount", + "commercial_quotation", + "blindpay_quotation", + "currency" + ] + }, + "PaginationMetadata": { + "type": "object", + "properties": { + "has_more": { + "type": "boolean", + "description": "Whether or not there are more elements available after this set.", + "example": true + }, + "next_page": { + "type": [ + "string", + "null" + ], + "description": "The ID of the first item in the next page of results.", + "example": "pi_123" + }, + "prev_page": { + "type": [ + "string", + "null" + ], + "description": "The ID of the first item in the previous page of results.", + "example": "pi_123" + } + }, + "required": [ + "has_more" + ] + }, + "PayoutOnStellarAuthorizeIn": { + "type": "object", + "properties": { + "quote_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "qu_000000000000" + }, + "sender_wallet_address": { + "type": "string", + "description": "Sender wallet address. Provide this OR wallet_id, not both.", + "example": "0x123...890" + }, + "wallet_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "BlindPay-managed wallet ID to send from. Provide this OR sender_wallet_address, not both.", + "example": "bl_000000000000" + } + }, + "required": [ + "quote_id" + ] + }, + "PayoutOnEvmOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "po_000000000000" + }, + "status": { + "type": "string", + "enum": [ + "processing", + "failed", + "refunded", + "completed", + "on_hold" + ], + "description": "Payout general status", + "example": "processing" + }, + "sender_wallet_address": { + "type": "string", + "description": "Payout wallet address", + "example": "0x123...890" + }, + "billing_fee_amount": { + "type": [ + "number", + "null" + ], + "description": "Billing fee in cents (charged via invoice at the end of the month)", + "example": 50 + }, + "transaction_fee_amount": { + "type": [ + "number", + "null" + ], + "description": "Transaction fee in cents (percentage-based fee)", + "example": 100 + }, + "partner_fee": { + "type": "integer", + "minimum": 0, + "default": 0, + "description": "Payout partner fee amount in cents (can be negative for rebates)", + "example": -25000 + }, + "tracking_complete": { "type": "object", "properties": { "step": { @@ -18048,10 +20541,11 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], - "description": "Payin transaction step", - "example": "processing" + "description": "Complete step", + "example": "on_hold" }, "status": { "type": [ @@ -18059,35 +20553,63 @@ "null" ], "enum": [ - "failed", - "completed" + "tokens_refunded", + "paid" ], - "description": "Payin transaction status", - "example": "failed" + "description": "Complete status", + "example": "tokens_refunded" }, - "external_id": { + "refund_reason": { "type": [ "string", "null" ], - "description": "Payin transaction external id", - "example": "12345678" + "description": "Reason for refund when tokens are returned to sender", + "example": "fiat_payment_failed" }, - "completed_at": { + "transaction_hash": { "type": [ "string", "null" ], - "description": "Payin transaction completed date", - "example": "2011-10-05T14:48:00.000Z" + "description": "Complete transaction hash", + "example": "0x123...890" }, - "transaction_hash": { + "provider_transaction_id": { "type": [ "string", "null" ], - "description": "Blockchain transaction hash", - "example": "0x123...890" + "description": "Provider-side handle for the refund transaction (e.g. Circle transaction id)", + "example": "67c12eae-b7bc-31cc-a5ef-623dcea82346" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + } + }, + "required": [ + "step" + ] + }, + "tracking_payment": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Payment step", + "example": "on_hold" }, "provider_name": { "type": [ @@ -18106,55 +20628,176 @@ "Citi", "CFSB", "Triple A Technologies", + "BCB Group", "Portage Bank", - "SSB Bank" + "NMI" ], "description": "Payment provider name", "example": "HSBC" }, - "provider_transaction_id": { + "provider_integration": { "type": [ "string", "null" ], - "description": "Payment provider transaction id", - "example": "" + "enum": [ + "veem", + "zenus", + "checkbook", + "onemoney", + "bitso", + "starkbank", + "triplea", + "infinitus", + "portage_g" + ], + "description": "Machine-readable integration that executed the fiat leg. Unlike provider_name (a client-facing bank label), this uniquely identifies the integration — e.g. zenus vs checkbook, which share the \"JPMorgan Chase\" label.", + "example": "zenus" }, - "sender_name": { + "provider_transaction_id": { "type": [ "string", "null" ], - "example": "John Doe Smith" - }, - "sender_bank_name": { + "description": "Payment provider transaction id", + "example": "0x123...890" + }, + "provider_status": { "type": [ "string", "null" ], - "example": "Bank of America" + "enum": [ + "canceled", + "failed", + "returned", + "sent" + ], + "description": "Payment provider status", + "example": "canceled" }, - "sender_tax_id": { + "provider_error_reason": { + "type": [ + "string", + "null" + ], + "description": "Provider error reason when payment fails (e.g. invalid_key, wrong_parameters)", + "example": "invalid_key" + }, + "returned_amount": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "Amount (in cents of the payout currency) the beneficiary bank sent back after the payment was delivered. May be lower than the amount sent when the return is partial.", + "example": 5000 + }, + "provider_uetr": { + "type": [ + "string", + "null" + ], + "maxLength": 120, + "description": "Unique end-to-end transaction reference (UETR). Populated once the wire is confirmed by the network; null while the payment is in flight or when the rail does not expose it (e.g. ACH).", + "example": "37d10eff-d450-4aba-a5d4-e3978f5a3343" + }, + "provider_imad": { + "type": [ + "string", + "null" + ], + "maxLength": 120, + "description": "Fed Input Message Accountability Data (IMAD). Domestic Fedwire payments only; null on ACH and SWIFT.", + "example": "20260526MMQFMP2M008120" + }, + "provider_reference": { + "type": [ + "string", + "null" + ], + "maxLength": 120, + "description": "Provider (JPMorgan/Zenus) payment reference captured from the ACCOUNT.ACCOUNT booking webhook (Zenus contractSource.sourceRef). Present for some ACH/wire payouts; a bank-side reference, not the formal ACH network trace number.", + "example": "2084734238TC" + }, + "provider_clearing_system": { + "type": [ + "string", + "null" + ], + "maxLength": 40, + "description": "Clearing system that processed the payment (e.g. FED, CHIPS, ACH, SWIFT).", + "example": "FED" + }, + "forced_provider": { "type": [ "string", "null" ], + "enum": [ + "zenus", + "veem", + "infinitus_portage" + ], + "description": "Ops-set per-payout provider override (backoffice Reroute tab). When present it wins over the instance payment_route and default routing at send time. Left in place after the send as an audit marker of the forced route.", + "example": "veem" + }, + "recipient_name": { + "type": [ + "string", + "null" + ], + "description": "Recipient name", + "example": "John Doe" + }, + "recipient_tax_id": { + "type": [ + "string", + "null" + ], + "description": "Recipient tax id", "example": "123.456.789-10" }, - "sender_bank_code": { + "recipient_bank_code": { "type": [ "string", "null" ], + "description": "Recipient bank code", "example": "00416968" }, - "sender_account_number": { + "recipient_branch_code": { + "type": [ + "string", + "null" + ], + "description": "Recipient branch code", + "example": "0001" + }, + "recipient_account_number": { "type": [ "string", "null" ], + "description": "Recipient account number", "example": "1234567890" }, + "recipient_account_type": { + "type": [ + "string", + "null" + ], + "description": "Recipient account type", + "example": "checking" + }, + "coelsa_id": { + "type": [ + "string", + "null" + ], + "description": "COELSA transaction reference ID for ARS transfers (Argentine national banking system)", + "example": "1LMP68NKV46DRDYK2R7OEV" + }, "end_to_end_id": { "type": [ "string", @@ -18163,734 +20806,182 @@ "description": "BACEN Pix end-to-end transaction ID (govt Pix ID)", "example": "E20018183202603311320vm6ALFpJpsS" }, - "trace_number": { + "estimated_time_of_arrival": { "type": [ "string", "null" ], - "example": "1234567890" + "enum": [ + "5_min", + "5_30_min", + "30_min", + "2_hours", + "1_business_day", + "2_business_days", + "5_business_days" + ], + "description": "Estimated time of arrival", + "example": "5_min" }, - "transaction_reference": { + "completed_at": { "type": [ "string", "null" ], - "example": "1234567890" + "description": "Payment completed date", + "example": "2011-10-05T14:48:00.000Z" }, - "description": { + "refund_review_reason": { "type": [ "string", "null" ], - "example": "Payment from John Doe Smith" + "enum": [ + "amount_threshold", + "time_window", + "late_cancellation_no_live_run", + "master_account_return", + "policy_always_review", + "operator_requested", + "partial_return" + ], + "description": "Why the payout was routed to the Pending Refunds review queue instead of auto-refunding after a provider cancellation", + "example": "amount_threshold" + }, + "refund_review_detected_at": { + "type": [ + "string", + "null" + ], + "description": "When the provider cancellation was routed to the Pending Refunds review queue", + "example": "2011-10-05T14:48:00.000Z" }, - "pse_instruction": { + "refund_review_actioned_at": { "type": [ - "object", + "string", "null" ], - "properties": { - "payment_link": { - "type": "string", - "description": "PSE payment link URL", - "example": "https://pse.example.com/payment/abc123" - }, - "fid": { - "type": "string", - "description": "PSE funding identifier for webhook matching", - "example": "fid_abc123" - }, - "full_name": { - "type": "string", - "description": "PSE payer full name", - "example": "Juan Pérez García" - }, - "tax_id": { - "type": "string", - "description": "PSE payer document number", - "example": "1234567890" - }, - "document_type": { - "type": "string", - "enum": [ - "CC", - "NIT" - ], - "description": "PSE payer document type", - "example": "CC" - }, - "phone": { - "type": "string", - "description": "PSE payer phone number", - "example": "+573001234567" - }, - "email": { - "type": "string", - "description": "PSE payer email", - "example": "juan@example.com" - }, - "bank_code": { - "type": [ - "string", - "null" - ], - "description": "PSE payer bank code", - "example": "1007" - } - }, - "required": [ - "payment_link", - "fid", - "full_name", - "tax_id", - "document_type", - "phone", - "email" - ] + "description": "Atomic claim marker: set the moment an operator approves a Pending Refunds entry, before the refund is sent, so a concurrent approve call cannot re-claim the same payout", + "example": "2011-10-05T14:48:00.000Z" }, - "transfers_instruction": { + "review_source": { "type": [ - "object", + "string", "null" ], - "properties": { - "account": { - "type": "string", - "description": "CVU/CBU/Alias account number", - "example": "0000003100012389237485" - }, - "type": { - "type": "string", - "enum": [ - "CVU", - "CBU", - "ALIAS" - ], - "description": "Account type (CVU, CBU, or ALIAS)", - "example": "CVU" - }, - "tax_id": { - "type": [ - "string", - "null" - ], - "description": "CUIT/CUIL (normalized, digits only)", - "example": "20123456783" - } + "description": "Primary risk source that sent this payout to manual review", + "example": "nested_third_party" + }, + "review_sources": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" }, - "required": [ - "account", - "type" + "description": "Every risk source that sent this payout to manual review", + "example": [ + "nested_third_party", + "seon_review" ] }, - "ted_instruction": { + "review_context": { "type": [ "object", "null" ], - "properties": { - "beneficiary_name": { - "type": "string", - "example": "Blind Pay, Inc." - }, - "tax_id": { - "type": "string", - "example": "57.599.376/0001-81" - }, - "bank_code": { - "type": "string", - "example": "665" - }, - "bank_name": { - "type": "string", - "example": "STARK BANK S.A." - }, - "branch_code": { - "type": "string", - "example": "5340" - }, - "account_number": { - "type": "string", - "example": "01011707084-8" - }, - "account_type": { - "type": "string", - "example": "checking" - } - }, - "required": [ - "beneficiary_name", - "tax_id", - "bank_code", - "bank_name", - "branch_code", - "account_number", - "account_type" - ] + "additionalProperties": {}, + "description": "Structured risk context for manual review" } }, "required": [ "step" ] }, - "billing_fee_amount": { - "type": [ - "number", - "null" - ], - "description": "Billing fee in cents (charged at the end of the month)", - "example": 50 - }, - "transaction_fee_amount": { - "type": [ - "number", - "null" - ], - "description": "Transaction fee in cents (percentage-based fee)", - "example": 100 - }, - "blindpay_bank_details": { + "tracking_transaction": { "type": "object", "properties": { - "routing_number": { - "type": "string", - "default": "121145349", - "example": "121145349" - }, - "account_number": { - "type": "string", - "default": "621327727210181", - "example": "621327727210181" - }, - "account_type": { + "step": { "type": "string", - "default": "Business checking", - "example": "Business checking" + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Payout transaction step", + "example": "processing" }, - "swift_bic_code": { + "status": { "type": [ "string", "null" ], - "default": "CHASUS33", - "example": "CHASUS33" + "enum": [ + "failed", + "found" + ], + "description": "Payout transaction status", + "example": "failed" }, - "ach": { + "transaction_hash": { "type": [ - "object", + "string", "null" ], - "properties": { - "routing_number": { - "type": "string", - "example": "123456789" - }, - "account_number": { - "type": "string", - "example": "123456789" - } - }, - "required": [ - "routing_number", - "account_number" - ] + "description": "Blockchain transaction hash", + "example": "0x123...890" }, - "wire": { + "completed_at": { "type": [ - "object", + "string", "null" ], - "properties": { - "routing_number": { - "type": "string", - "example": "123456789" - }, - "account_number": { - "type": "string", - "example": "123456789" - } - }, - "required": [ - "routing_number", - "account_number" - ] + "description": "Payout transaction completed date", + "example": "2011-10-05T14:48:00.000Z" }, - "rtp": { + "provider_transaction_id": { "type": [ - "object", + "string", "null" ], - "properties": { - "routing_number": { - "type": "string", - "example": "123456789" - }, - "account_number": { - "type": "string", - "example": "123456789" - } - }, - "required": [ - "routing_number", - "account_number" - ] - }, - "beneficiary": { - "type": "object", - "properties": { - "name": { - "type": "string", - "default": "BlindPay, Inc.", - "example": "BlindPay, Inc." - }, - "address_line_1": { - "type": "string", - "default": "8 The Green, #19364", - "example": "8 The Green, #19364" - }, - "address_line_2": { - "type": "string", - "default": "Dover, DE 19901", - "example": "Dover, DE 19901" - } - } + "description": "Provider-side handle for the on-chain leg (e.g. Circle CPN payment id).", + "example": "67c12eae-b7bc-31cc-a5ef-623dcea82346" }, - "receiving_bank": { - "type": "object", - "properties": { - "name": { - "type": "string", - "default": "CFSB", - "example": "CFSB" - }, - "address_line_1": { - "type": "string", - "default": "1 Letterman Drive, Building A, Suite A4-700", - "example": "1 Letterman Drive, Building A, Suite A4-700" - }, - "address_line_2": { - "type": "string", - "default": "San Francisco, CA 94129", - "example": "San Francisco, CA 94129" - } - } + "provider_error_reason": { + "type": [ + "string", + "null" + ], + "description": "Provider error reason when the crypto collection fails (e.g. erc20_allowance_insufficient, ESTIMATION_ERROR: execution reverted)", + "example": "erc20_allowance_insufficient" }, - "swift_account_number": { + "ledger_in_transaction_id": { "type": [ "string", "null" ], - "example": "GB50TCCL04140449730892" + "description": "Ledger transaction ID for the IN (crypto deposit) transaction" }, - "swift_receiving_bank": { + "ledger_out_transaction_id": { "type": [ - "object", + "string", "null" ], - "properties": { - "name": { - "type": [ - "string", - "null" - ], - "example": "JPMorgan Chase" - }, - "address_line_1": { - "type": [ - "string", - "null" - ], - "example": "270 Park Ave" - }, - "address_line_2": { - "type": [ - "string", - "null" - ], - "example": "New York, NY, 10017-2070" - } - } + "description": "Ledger transaction ID for the OUT (fiat withdrawal) transaction" } }, "required": [ - "beneficiary", - "receiving_bank" + "step" ] }, - "customer_id": { - "type": [ - "string", - "null" - ], - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" - }, - "receiver_amount": { - "type": [ - "number", - "null" - ], - "description": "10.10 USDC", - "example": 1010 - }, - "payment_method": { - "type": [ - "string", - "null" - ], - "enum": [ - "ach", - "wire", - "pix", - "ted", - "spei", - "transfers", - "pse", - "international_swift", - "rtp" - ], - "example": "pix" - }, - "sender_amount": { + "tracking_liquidity": { "type": [ - "number", + "object", "null" ], - "description": "52.40 BRL needs to be sent in a pix transfer", - "example": 5240 - } - }, - "required": [ - "id", - "status", - "tracking_complete", - "tracking_payment", - "tracking_transaction", - "blindpay_bank_details" - ] - }, - "CreatePayinIn": { - "type": "object", - "properties": { - "payin_quote_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "pq_000000000000" - } - }, - "required": [ - "payin_quote_id" - ] - }, - "CreatePayinQuoteOut": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "qu_000000000000" - }, - "expires_at": { - "type": [ - "number", - "null" - ], - "description": "Epoch unix timestamp that represents the final datetime to transaction be received on blockchain", - "example": 1712958191 - }, - "commercial_quotation": { - "type": [ - "number", - "null" - ], - "description": "1 USD = 4.95 BRL", - "example": 495 - }, - "blindpay_quotation": { - "type": [ - "number", - "null" - ], - "description": "1 USD = 5.05 BRL (commercial quotation + (blindpay taxes))", - "example": 505 - }, - "receiver_amount": { - "type": [ - "number", - "null" - ], - "description": "10.10 USDC", - "example": 1010 - }, - "sender_amount": { - "type": [ - "number", - "null" - ], - "description": "52.40 BRL needs to be sent in a pix transfer", - "example": 5240 - }, - "partner_fee_amount": { - "type": [ - "number", - "null" - ], - "default": 0, - "description": "1.5 USDC", - "example": 150 - }, - "flat_fee": { - "type": [ - "number", - "null" - ], - "description": "0.5 USDC", - "example": 50 - }, - "billing_fee_amount": { - "type": [ - "number", - "null" - ], - "description": "Billing fee in cents (charged at the end of the month)", - "example": 50 - }, - "is_otc": { - "type": [ - "boolean", - "null" - ], - "description": "If true, the payin quote is for an OTC (Over the Counter) transaction", - "example": false - } - }, - "required": [ - "id", - "expires_at", - "commercial_quotation", - "blindpay_quotation", - "receiver_amount", - "sender_amount", - "flat_fee" - ] - }, - "CreatePayinQuoteIn": { - "type": "object", - "properties": { - "blockchain_wallet_id": { - "type": [ - "string", - "null" - ], - "minLength": 15, - "maxLength": 15, - "example": "bw_000000000000" - }, - "wallet_id": { - "type": [ - "string", - "null" - ], - "minLength": 15, - "maxLength": 15, - "example": "bl_000000000000" - }, - "currency_type": { - "type": "string", - "enum": [ - "sender", - "receiver" - ], - "description": "", - "example": "sender" - }, - "cover_fees": { - "type": [ - "boolean", - "null" - ], - "description": "If true, the sender will cover the fees. If false, the customer will cover the fees.", - "example": true - }, - "request_amount": { - "type": "integer", - "minimum": 500, - "description": "1000 represents 10.00, 2050 represents 20.50", - "example": 1000 - }, - "payment_method": { - "type": "string", - "enum": [ - "ach", - "wire", - "pix", - "ted", - "spei", - "transfers", - "pse", - "international_swift", - "rtp" - ], - "example": "pix" - }, - "token": { - "type": "string", - "enum": [ - "USDC", - "USDT", - "USDB" - ], - "example": "USDC" - }, - "partner_fee_id": { - "type": [ - "string", - "null" - ], - "minLength": 15, - "maxLength": 15, - "example": "pf_000000000000" - }, - "payer_rules": { - "type": [ - "object", - "null" - ], - "properties": { - "pix_allowed_tax_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string", - "example": "123.456.789-09" - } - }, - "transfers_allowed_tax_id": { - "type": [ - "string", - "null" - ], - "example": "20-12345678-3" - }, - "pse_allowed_tax_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string", - "example": "1234567890" - } - }, - "pse_full_name": { - "type": [ - "string", - "null" - ], - "maxLength": 50 - }, - "pse_document_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "CC", - "NIT" - ] - }, - "pse_document_number": { - "type": [ - "string", - "null" - ] - }, - "pse_email": { - "type": [ - "string", - "null" - ], - "format": "email" - }, - "pse_phone": { - "type": [ - "string", - "null" - ], - "pattern": "^\\+573\\d{9}$" - }, - "pse_bank_code": { - "type": [ - "string", - "null" - ] - } - }, - "example": { - "pix_allowed_tax_ids": [ - "123.456.789-09" - ], - "transfers_allowed_tax_id": "20-12345678-3", - "pse_allowed_tax_ids": [ - "1234567890" - ] - } - }, - "is_otc": { - "type": [ - "boolean", - "null" - ], - "description": "If true, the payin quote is for an OTC (Over the Counter) transaction", - "example": false - } - }, - "required": [ - "currency_type", - "request_amount", - "payment_method", - "token" - ] - }, - "TransferOut": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "bl_000000000000" - }, - "status": { - "type": "string", - "enum": [ - "processing", - "failed", - "refunded", - "completed" - ], - "description": "Transfer general status", - "example": "processing" - }, - "transfer_quote_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "pq_000000000000" - }, - "instance_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "tracking_transaction_monitoring": { - "type": "object", "properties": { "step": { "type": "string", @@ -18898,146 +20989,68 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], - "description": "Transaction monitoring step", + "description": "Payout liquidity step", "example": "processing" }, - "blockchain_screening": { - "type": [ - "number", - "null" - ], - "minimum": 0, - "maximum": 100, - "description": "Blindpay screening step", - "example": 1 - }, - "risk_score": { - "type": [ - "number", - "null" - ], - "minimum": 0, - "maximum": 100, - "description": "Risk score", - "example": 1 - }, - "completed_at": { - "type": [ - "string", - "null" - ], - "description": "Transfer transaction completed date", - "example": "2011-10-05T14:48:00.000Z" - } - }, - "required": [ - "step" - ] - }, - "tracking_paymaster": { - "type": "object", - "properties": { - "step": { - "type": "string", - "enum": [ - "processing", - "on_hold", - "pending_review", - "completed" - ], - "description": "Complete step", - "example": "on_hold" - }, - "transaction_hash": { + "provider_transaction_id": { "type": [ "string", "null" ], - "description": "Complete transaction hash", + "description": "Payment provider transaction id", "example": "0x123...890" }, - "gas_fee": { - "type": [ - "string", - "null" - ], - "description": "Gas fee related to transaction", - "example": "100" - }, - "completed_at": { - "type": [ - "string", - "null" - ], - "description": "Complete completed date", - "example": "2011-10-05T14:48:00.000Z" - }, - "error_message": { + "provider_status": { "type": [ "string", "null" ], - "example": "Gas fee is too low" - } - }, - "required": [ - "step" - ] - }, - "tracking_bridge_swap": { - "type": "object", - "properties": { - "step": { - "type": "string", "enum": [ - "processing", - "on_hold", - "pending_review", - "completed" + "deposited", + "converted", + "withdrawn" ], - "description": "Complete step", - "example": "on_hold" + "description": "Payment provider status", + "example": "deposited" }, - "transaction_hash": { + "estimated_time_of_arrival": { "type": [ "string", "null" ], - "description": "Complete transaction hash", - "example": "0x123...890" - }, - "gas_fee": { - "type": [ - "string", - "null" + "enum": [ + "5_min", + "5_30_min", + "30_min", + "2_hours", + "1_business_day", + "2_business_days", + "5_business_days" ], - "description": "Gas fee related to transaction", - "example": "100" + "description": "Estimated time of arrival", + "example": "1_business_day" }, "completed_at": { "type": [ "string", "null" ], - "description": "Complete completed date", + "description": "Payout transaction completed date", "example": "2011-10-05T14:48:00.000Z" - }, - "error_message": { - "type": [ - "string", - "null" - ], - "example": "Gas fee is too low" } }, "required": [ "step" ] }, - "tracking_complete": { - "type": "object", + "tracking_documents": { + "type": [ + "object", + "null" + ], "properties": { "step": { "type": "string", @@ -19045,3187 +21058,4211 @@ "processing", "on_hold", "pending_review", + "pending_refund_review", "completed" ], - "description": "Complete step", - "example": "on_hold" + "description": "Documents step", + "example": "processing" }, - "transaction_hash": { + "status": { "type": [ "string", "null" ], - "description": "Complete transaction hash", - "example": "0x123...890" + "enum": [ + "waiting_documents", + "compliance_reviewing" + ], + "description": "Documents status", + "example": "waiting_documents" }, - "gas_fee": { + "reviewed_by": { "type": [ "string", "null" ], - "description": "Gas fee related to transaction", - "example": "100" + "description": "Reviewer email/name", + "example": "compliance@example.com" }, "completed_at": { "type": [ "string", "null" ], - "description": "Complete completed date", + "description": "Documents completed date", "example": "2011-10-05T14:48:00.000Z" - }, - "error_message": { - "type": [ - "string", - "null" - ], - "example": "Gas fee is too low" } }, "required": [ "step" ] }, - "created_at": { + "customer_id": { "type": [ "string", "null" ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" }, - "updated_at": { + "bank_account_id": { "type": [ "string", "null" ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" + "minLength": 15, + "maxLength": 15, + "example": "ba_000000000000" }, - "image_url": { + "offramp_wallet_id": { "type": [ "string", "null" ], - "format": "uri", - "example": "https://example.com/image.png" + "minLength": 15, + "maxLength": 15, + "example": "ow_000000000000" }, - "first_name": { + "payable_id": { "type": [ "string", "null" ], - "example": "John" - }, - "last_name": { - "type": [ - "string", - "null" - ], - "example": "Doe" - }, - "legal_name": { - "type": [ - "string", - "null" - ], - "example": "Company Name Inc." - }, - "wallet_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "bl_000000000000" - }, - "sender_token": { - "type": "string", - "enum": [ - "USDC", - "USDT", - "USDB" - ], - "example": "USDC" - }, - "sender_amount": { - "type": "number", - "description": "52.40 BRL needs to be sent in a pix transfer", - "example": 5240 - }, - "receiver_amount": { - "type": "number", - "description": "10.10 USDC", - "example": 1010 - }, - "customer_network": { - "type": "string", - "enum": [ - "base", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "arbitrum", - "polygon", - "polygon_amoy", - "ethereum", - "stellar", - "stellar_testnet", - "tron", - "solana", - "solana_devnet" - ], - "example": "polygon" - }, - "customer_token": { - "type": "string", - "enum": [ - "USDC", - "USDT", - "USDB" - ], - "example": "USDC" - }, - "customer_wallet_address": { - "type": "string", - "minLength": 32, - "maxLength": 64, - "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" - }, - "partner_fee_amount": { - "type": [ - "number", - "null" - ], - "default": 0, - "description": "1.5 USDC", - "example": 150 - }, - "external_id": { - "type": [ - "string", - "null" - ], - "maxLength": 255, - "example": "your-database-id" - }, - "customer_id": { - "type": "string", "minLength": 15, "maxLength": 15, - "example": "re_000000000000" - }, - "address": { - "type": [ - "string", - "null" - ], - "maxLength": 64, - "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" - }, - "network": { - "type": "string", - "enum": [ - "base", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "arbitrum", - "polygon", - "polygon_amoy", - "ethereum", - "stellar", - "stellar_testnet", - "tron", - "solana", - "solana_devnet" - ], - "example": "polygon" + "description": "The payable this payout executes, when it pays a payable instead of a bank account.", + "example": "pb_000000000000" } }, "required": [ "id", "status", - "transfer_quote_id", - "instance_id", - "tracking_transaction_monitoring", - "tracking_paymaster", - "tracking_bridge_swap", + "sender_wallet_address", "tracking_complete", - "wallet_id", - "sender_token", - "sender_amount", - "receiver_amount", - "customer_network", - "customer_token", - "customer_wallet_address", - "customer_id", - "network" + "tracking_payment", + "tracking_transaction" ] }, - "CreateTransferOut": { + "PayoutOnStellarIn": { "type": "object", "properties": { - "id": { + "quote_id": { "type": "string", "minLength": 15, "maxLength": 15, - "example": "pa_000000000000" + "example": "qu_000000000000" }, - "status": { - "type": "string", - "enum": [ - "processing", - "failed", - "refunded", - "completed" + "signed_transaction": { + "type": [ + "string", + "null" ], - "description": "Transfer general status", - "example": "processing" - }, - "tracking_bridge_swap": { - "type": "object", - "properties": { - "step": { - "type": "string", - "enum": [ - "processing", - "on_hold", - "pending_review", - "completed" - ], - "description": "Complete step", - "example": "on_hold" - }, - "transaction_hash": { - "type": [ - "string", - "null" - ], - "description": "Complete transaction hash", - "example": "0x123...890" - }, - "gas_fee": { - "type": [ - "string", - "null" - ], - "description": "Gas fee related to transaction", - "example": "100" - }, - "completed_at": { - "type": [ - "string", - "null" - ], - "description": "Complete completed date", - "example": "2011-10-05T14:48:00.000Z" - }, - "error_message": { - "type": [ - "string", - "null" - ], - "example": "Gas fee is too low" - } - }, - "required": [ - "step" - ] - }, - "tracking_complete": { - "type": "object", - "properties": { - "step": { - "type": "string", - "enum": [ - "processing", - "on_hold", - "pending_review", - "completed" - ], - "description": "Complete step", - "example": "on_hold" - }, - "transaction_hash": { - "type": [ - "string", - "null" - ], - "description": "Complete transaction hash", - "example": "0x123...890" - }, - "gas_fee": { - "type": [ - "string", - "null" - ], - "description": "Gas fee related to transaction", - "example": "100" - }, - "completed_at": { - "type": [ - "string", - "null" - ], - "description": "Complete completed date", - "example": "2011-10-05T14:48:00.000Z" - }, - "error_message": { - "type": [ - "string", - "null" - ], - "example": "Gas fee is too low" - } - }, - "required": [ - "step" - ] + "description": "Signed transaction", + "example": "AAA...Zey8y0A" }, - "tracking_paymaster": { - "type": "object", - "properties": { - "step": { - "type": "string", - "enum": [ - "processing", - "on_hold", - "pending_review", - "completed" - ], - "description": "Complete step", - "example": "on_hold" - }, - "transaction_hash": { - "type": [ - "string", - "null" - ], - "description": "Complete transaction hash", - "example": "0x123...890" - }, - "gas_fee": { - "type": [ - "string", - "null" - ], - "description": "Gas fee related to transaction", - "example": "100" - }, - "completed_at": { - "type": [ - "string", - "null" - ], - "description": "Complete completed date", - "example": "2011-10-05T14:48:00.000Z" - }, - "error_message": { - "type": [ - "string", - "null" - ], - "example": "Gas fee is too low" - } - }, - "required": [ - "step" - ] + "sender_wallet_address": { + "type": "string", + "description": "Sender wallet address. Provide this OR wallet_id, not both.", + "example": "0x123...890" }, - "tracking_transaction_monitoring": { - "type": "object", - "properties": { - "step": { - "type": "string", - "enum": [ - "processing", - "on_hold", - "pending_review", - "completed" - ], - "description": "Transaction monitoring step", - "example": "processing" - }, - "blockchain_screening": { - "type": [ - "number", - "null" - ], - "minimum": 0, - "maximum": 100, - "description": "Blindpay screening step", - "example": 1 - }, - "risk_score": { - "type": [ - "number", - "null" - ], - "minimum": 0, - "maximum": 100, - "description": "Risk score", - "example": 1 - }, - "completed_at": { - "type": [ - "string", - "null" - ], - "description": "Transfer transaction completed date", - "example": "2011-10-05T14:48:00.000Z" - } - }, - "required": [ - "step" - ] - } - }, - "required": [ - "id", - "status", - "tracking_bridge_swap", - "tracking_complete", - "tracking_paymaster", - "tracking_transaction_monitoring" - ] - }, - "CreateTransferIn": { - "type": "object", - "properties": { - "transfer_quote_id": { + "wallet_id": { "type": "string", "minLength": 15, "maxLength": 15, - "example": "pq_000000000000" + "description": "BlindPay-managed wallet ID to send from. Provide this OR sender_wallet_address, not both.", + "example": "bl_000000000000" } }, "required": [ - "transfer_quote_id" + "quote_id" ] }, - "CreateTransferQuoteOut": { + "PayoutOnSolanaIn": { "type": "object", "properties": { - "id": { + "quote_id": { "type": "string", "minLength": 15, "maxLength": 15, "example": "qu_000000000000" }, - "expires_at": { - "type": [ - "number", - "null" - ], - "description": "Epoch unix timestamp that represents the final datetime to transaction be received on blockchain", - "example": 1712958191 - }, - "commercial_quotation": { - "type": [ - "number", - "null" - ], - "description": "1 USD = 4.95 BRL", - "example": 495 - }, - "blindpay_quotation": { + "signed_transaction": { "type": [ - "number", + "string", "null" ], - "description": "1 USD = 5.05 BRL (commercial quotation + (blindpay taxes))", - "example": 505 - }, - "receiver_amount": { - "type": "number", - "description": "10.10 USDC", - "example": 1010 - }, - "sender_amount": { - "type": "number", - "description": "52.40 BRL needs to be sent in a pix transfer", - "example": 5240 + "description": "Signed transaction", + "example": "AAA...Zey8y0A" }, - "partner_fee_amount": { - "type": [ - "number", - "null" - ], - "default": 0, - "description": "1.5 USDC", - "example": 150 + "sender_wallet_address": { + "type": "string", + "description": "Sender wallet address. Provide this OR wallet_id, not both.", + "example": "0x123...890" }, - "flat_fee": { - "type": "number", - "description": "0.5 USDC", - "example": 50 + "wallet_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "BlindPay-managed wallet ID to send from. Provide this OR sender_wallet_address, not both.", + "example": "bl_000000000000" } }, "required": [ - "id", - "expires_at", - "commercial_quotation", - "blindpay_quotation", - "receiver_amount", - "sender_amount", - "flat_fee" + "quote_id" ] }, - "CreateTransferQuoteIn": { + "PayoutOnEvmIn": { "type": "object", "properties": { + "quote_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "qu_000000000000" + }, + "sender_wallet_address": { + "type": "string", + "description": "Sender wallet address. Provide this OR wallet_id, not both.", + "example": "0x123...890" + }, "wallet_id": { "type": "string", "minLength": 15, "maxLength": 15, + "description": "BlindPay-managed wallet ID to send from. Provide this OR sender_wallet_address, not both.", "example": "bl_000000000000" - }, - "amount_reference": { + } + }, + "required": [ + "quote_id" + ] + }, + "SubmitPayoutDocumentsIn": { + "type": "object", + "properties": { + "transaction_document_type": { "type": "string", "enum": [ - "sender", - "receiver" - ], - "description": "", - "example": "sender" - }, - "cover_fees": { - "type": [ - "boolean", - "null" + "invoice", + "purchase_order", + "delivery_slip", + "contract", + "customs_declaration", + "bill_of_lading", + "others" ], - "description": "If true, the sender will cover the fees. If false, the customer will cover the fees.", - "example": true - }, - "request_amount": { - "type": "integer", - "minimum": 1, - "description": "100 represents 1, 2050 represents 20.50", - "example": 1000 + "description": "Document type", + "example": "invoice" }, - "sender_token": { + "transaction_document_id": { "type": "string", - "enum": [ - "USDC", - "USDT", - "USDB" - ], - "example": "USDC" + "minLength": 1, + "maxLength": 512, + "description": "Document identifier (invoice number, contract ID, etc.)", + "example": "INV-12345" }, - "customer_wallet_address": { + "transaction_document_file": { "type": "string", - "minLength": 32, - "maxLength": 64, - "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + "format": "uri", + "description": "URL to the uploaded document", + "example": "https://example.com/document.pdf" }, - "customer_token": { + "description": { "type": "string", - "enum": [ - "USDC", - "USDT", - "USDB" - ], - "example": "USDC" - }, - "customer_network": { - "type": "string", - "enum": [ - "base", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "arbitrum", - "polygon", - "polygon_amoy", - "ethereum", - "stellar", - "stellar_testnet", - "tron", - "solana", - "solana_devnet" - ], - "example": "polygon" - }, - "partner_fee_id": { - "type": [ - "string", - "null" - ], - "minLength": 15, - "maxLength": 15, - "example": "pf_000000000000" - } - }, - "required": [ - "wallet_id", - "amount_reference", - "request_amount", - "sender_token", - "customer_wallet_address", - "customer_token", - "customer_network" - ] - }, - "CustomerLimitIncreaseOut": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "rl_000000000000" - } - }, - "required": [ - "id" - ] - }, - "CustomerLimitIncreaseIn": { - "type": "object", - "properties": { - "per_transaction": { - "type": [ - "integer", - "null" - ], - "maximum": 100000000000, - "example": 100000 - }, - "daily": { - "type": [ - "integer", - "null" - ], - "maximum": 100000000000, - "example": 200000 - }, - "monthly": { - "type": [ - "integer", - "null" - ], - "maximum": 100000000000, - "example": 1000000 - }, - "supporting_document_type": { - "type": "string", - "enum": [ - "individual_bank_statement", - "individual_tax_return", - "individual_proof_of_income", - "individual_pay_stub", - "individual_employment_letter", - "individual_investment_statement", - "individual_crypto_exchange_statement", - "individual_blockchain_wallet_statement", - "business_bank_statement", - "business_financial_statements", - "business_tax_return", - "business_contract", - "business_accounts_receivable", - "business_merchant_processor_statement", - "business_shareholder_loan" - ], - "example": "individual_bank_statement" - }, - "supporting_document_file": { - "type": "string", - "format": "uri", - "example": "https://example.com/document.pdf" + "maxLength": 128, + "description": "Optional payment description/memo for SWIFT payouts only (max 128 chars). Ignored for other rails.", + "example": "Payment for services - Invoice #12345" } }, "required": [ - "per_transaction", - "daily", - "monthly", - "supporting_document_type", - "supporting_document_file" + "transaction_document_type", + "transaction_document_id", + "transaction_document_file" ] }, - "GetCustomerLimitIncreaseOut": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "rl_000000000000" - }, - "status": { - "type": "string", - "enum": [ - "in_review", - "approved", - "rejected" - ], - "example": "in_review" - }, - "per_transaction": { - "type": [ - "integer", - "null" - ], - "maximum": 100000000000, - "example": 100000 - }, - "daily": { - "type": [ - "integer", - "null" - ], - "maximum": 100000000000, - "example": 200000 - }, - "monthly": { - "type": [ - "integer", - "null" - ], - "maximum": 100000000000, - "example": 1000000 - }, - "approved_per_transaction": { - "type": [ - "integer", - "null" - ], - "maximum": 100000000000, - "example": 70000 - }, - "approved_daily": { - "type": [ - "integer", - "null" - ], - "maximum": 100000000000, - "example": 140000 - }, - "approved_monthly": { - "type": [ - "integer", - "null" - ], - "maximum": 100000000000, - "example": 700000 - }, - "supporting_document_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "individual_bank_statement", - "individual_tax_return", - "individual_proof_of_income", - "individual_pay_stub", - "individual_employment_letter", - "individual_investment_statement", - "individual_crypto_exchange_statement", - "individual_blockchain_wallet_statement", - "business_bank_statement", - "business_financial_statements", - "business_tax_return", - "business_contract", - "business_accounts_receivable", - "business_merchant_processor_statement", - "business_shareholder_loan" - ], - "example": "individual_bank_statement" - }, - "supporting_document_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "example": "https://example.com/document.pdf" - }, - "customer_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" - }, - "created_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" + "AvailableBankDetails": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string", + "example": "Account Number" + }, + "regex": { + "type": "string", + "example": "^[0-9]{9}$" + }, + "key": { + "type": "string", + "enum": [ + "type", + "name", + "status", + "recipient_relationship", + "swift_payment_code", + "pix_key", + "force_cpf_cnpj", + "beneficiary_name", + "routing_number", + "account_number", + "account_type", + "account_class", + "address_line_1", + "address_line_2", + "city", + "state_province_region", + "country", + "postal_code", + "checkbook_account_id", + "checkbook_user_key", + "onemoney_external_account_id", + "pix_safe_bank_code", + "pix_safe_branch_code", + "pix_safe_cpf_cnpj", + "ted_bank_code", + "ted_branch_code", + "ted_cpf_cnpj", + "spei_protocol", + "spei_institution_code", + "spei_clabe", + "transfers_type", + "transfers_account", + "ach_cop_beneficiary_first_name", + "ach_cop_beneficiary_last_name", + "ach_cop_document_id", + "ach_cop_document_type", + "ach_cop_email", + "ach_cop_bank_code", + "ach_cop_bank_account", + "swift_code_bic", + "swift_account_holder_name", + "swift_account_number_iban", + "swift_beneficiary_address_line_1", + "swift_beneficiary_address_line_2", + "swift_beneficiary_country", + "swift_beneficiary_city", + "swift_beneficiary_state_province_region", + "swift_beneficiary_postal_code", + "swift_bank_name", + "swift_bank_address_line_1", + "swift_bank_address_line_2", + "swift_bank_country", + "swift_bank_city", + "swift_bank_state_province_region", + "swift_bank_postal_code", + "swift_ifsc_branch_code", + "swift_intermediary_bank_swift_code_bic", + "swift_intermediary_bank_account_number_iban", + "swift_intermediary_bank_name", + "swift_intermediary_bank_country", + "swift_intermediary_bank_routing_number", + "sepa_iban", + "sepa_beneficiary_bic", + "sepa_beneficiary_legal_name", + "sepa_beneficiary_address_line_1", + "sepa_beneficiary_address_line_2", + "sepa_beneficiary_city", + "sepa_beneficiary_state_province_region", + "sepa_beneficiary_postal_code", + "sepa_beneficiary_country", + "faster_payments_sort_code", + "faster_payments_account_number", + "faster_payments_beneficiary_legal_name", + "faster_payments_beneficiary_address_line_1", + "faster_payments_beneficiary_address_line_2", + "faster_payments_beneficiary_city", + "faster_payments_beneficiary_state_province_region", + "faster_payments_beneficiary_postal_code", + "faster_payments_beneficiary_country", + "business_industry", + "phone_number", + "tax_id", + "date_of_birth" + ], + "example": "account_number" + }, + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string", + "example": "United States of America" + }, + "value": { + "type": "string", + "example": "US" + }, + "is_active": { + "type": "boolean", + "example": true + } + }, + "required": [ + "label", + "value" + ] + } + }, + "required": { + "type": [ + "boolean", + "null" + ], + "example": false + }, + "requiredWhen": { + "type": "object", + "properties": { + "field": { + "type": "string", + "enum": [ + "type", + "name", + "status", + "recipient_relationship", + "swift_payment_code", + "pix_key", + "force_cpf_cnpj", + "beneficiary_name", + "routing_number", + "account_number", + "account_type", + "account_class", + "address_line_1", + "address_line_2", + "city", + "state_province_region", + "country", + "postal_code", + "checkbook_account_id", + "checkbook_user_key", + "onemoney_external_account_id", + "pix_safe_bank_code", + "pix_safe_branch_code", + "pix_safe_cpf_cnpj", + "ted_bank_code", + "ted_branch_code", + "ted_cpf_cnpj", + "spei_protocol", + "spei_institution_code", + "spei_clabe", + "transfers_type", + "transfers_account", + "ach_cop_beneficiary_first_name", + "ach_cop_beneficiary_last_name", + "ach_cop_document_id", + "ach_cop_document_type", + "ach_cop_email", + "ach_cop_bank_code", + "ach_cop_bank_account", + "swift_code_bic", + "swift_account_holder_name", + "swift_account_number_iban", + "swift_beneficiary_address_line_1", + "swift_beneficiary_address_line_2", + "swift_beneficiary_country", + "swift_beneficiary_city", + "swift_beneficiary_state_province_region", + "swift_beneficiary_postal_code", + "swift_bank_name", + "swift_bank_address_line_1", + "swift_bank_address_line_2", + "swift_bank_country", + "swift_bank_city", + "swift_bank_state_province_region", + "swift_bank_postal_code", + "swift_ifsc_branch_code", + "swift_intermediary_bank_swift_code_bic", + "swift_intermediary_bank_account_number_iban", + "swift_intermediary_bank_name", + "swift_intermediary_bank_country", + "swift_intermediary_bank_routing_number", + "sepa_iban", + "sepa_beneficiary_bic", + "sepa_beneficiary_legal_name", + "sepa_beneficiary_address_line_1", + "sepa_beneficiary_address_line_2", + "sepa_beneficiary_city", + "sepa_beneficiary_state_province_region", + "sepa_beneficiary_postal_code", + "sepa_beneficiary_country", + "faster_payments_sort_code", + "faster_payments_account_number", + "faster_payments_beneficiary_legal_name", + "faster_payments_beneficiary_address_line_1", + "faster_payments_beneficiary_address_line_2", + "faster_payments_beneficiary_city", + "faster_payments_beneficiary_state_province_region", + "faster_payments_beneficiary_postal_code", + "faster_payments_beneficiary_country", + "business_industry", + "phone_number", + "tax_id", + "date_of_birth" + ], + "example": "country" + }, + "operator": { + "type": "string", + "enum": [ + "in", + "eq", + "notIn", + "notEq" + ], + "example": "in" + }, + "values": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "US", + "GB" + ] + } + }, + "required": [ + "field", + "operator", + "values" + ], + "example": { + "field": "country", + "operator": "in", + "values": [ + "US", + "GB" + ] + } + } }, - "updated_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" - } - }, - "required": [ - "id", - "status", - "customer_id" - ] + "required": [ + "label", + "regex", + "key" + ] + } }, - "OfframpWallet": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "ow_000000000000" - }, - "external_id": { - "type": [ - "string", - "null" - ], - "example": "your_external_id" - }, - "instance_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "customer_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" + "AvailableRails": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string", + "example": "Domestic Wire" + }, + "value": { + "type": "string", + "enum": [ + "wire", + "ach", + "pix", + "pix_safe", + "ted", + "spei_bitso", + "transfers_bitso", + "ach_cop_bitso", + "international_swift", + "rtp", + "sepa", + "faster_payments" + ], + "example": "wire" + }, + "country": { + "type": "string", + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "US" + } }, - "bank_account_id": { + "required": [ + "label", + "value", + "country" + ] + } + }, + "AvailableNaicsList": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string", + "example": "(339910) Jewelry and Silverware Manufacturing" + }, + "value": { + "type": "string", + "example": "339910" + } + }, + "required": [ + "label", + "value" + ] + } + }, + "SwiftCodeItem": { + "type": "object", + "properties": { + "id": { "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "ba_000000000000" + "example": "416" }, - "circle_wallet_id": { - "type": [ - "string", - "null" - ], - "example": "01234567-abcd-efgh-ijkl-012345678901" + "bank": { + "type": "string", + "example": "BANK OF AMERICA, N.A." }, - "network": { + "city": { "type": "string", - "enum": [ - "tron", - "solana", - "solana_devnet", - "arbitrum", - "base", - "ethereum", - "polygon", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "polygon_amoy" - ], - "example": "tron" + "example": "NEW JERSEY" }, - "address": { + "branch": { "type": "string", - "example": "TALJN9zTTEL9TVBb4WuTt6wLvPqJZr3hvb" + "example": "LENDING SERVICES AND OPERATIONS (LSOP)" }, - "created_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" + "swiftCode": { + "type": "string", + "example": "BOFAUS3NLMA" }, - "updated_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" + "swiftCodeLink": { + "type": "string", + "example": "https://bank.codes/swift-code/united-states/bofaus3nlma/" + }, + "country": { + "type": "string", + "example": "United States" + }, + "countrySlug": { + "type": "string", + "example": "united-states" } }, "required": [ "id", - "instance_id", - "customer_id", - "bank_account_id", - "network", - "address" + "bank", + "city", + "branch", + "swiftCode", + "swiftCodeLink", + "country", + "countrySlug" ] }, - "WalletOut": { + "SwiftCodeResponse": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SwiftCodeItem" + } + }, + "RetrieveInstanceOut": { "type": "object", "properties": { "id": { "type": "string", "minLength": 15, "maxLength": 15, - "example": "bl_000000000000" + "example": "in_000000000000" }, "name": { "type": "string", - "maxLength": 255, - "example": "Blindpay Wallet" + "minLength": 3, + "maxLength": 100, + "example": "My Instance" }, - "external_id": { + "type": { + "type": "string", + "enum": [ + "production", + "development" + ], + "description": "development instances simulate settlement with test tokens (USDB) and move no real money; production instances move real funds", + "example": "development" + }, + "onboarding_step": { + "type": "string", + "enum": [ + "initial", + "business_details", + "business_profile", + "documents", + "applicant", + "completed", + "blocked" + ], + "description": "completed once the instance can move money; anything else means onboarding is still open in the dashboard", + "example": "initial" + } + }, + "required": [ + "id", + "name", + "type", + "onboarding_step" + ] + }, + "UpdateInstanceIn": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 3, + "maxLength": 100, + "example": "My Instance" + }, + "customer_invite_redirect_url": { "type": [ "string", "null" ], - "maxLength": 255, - "example": "your-database-id" + "format": "uri", + "example": "https://blindpay.com" }, - "address": { + "logo_url": { "type": [ "string", "null" ], - "maxLength": 64, - "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + "format": "uri", + "description": "Logo shown to your customers on hosted pages such as the Terms of Service acceptance page", + "example": "https://files-avatar.blindpay.com/in_000000000000/logo.jpg" }, - "network": { - "type": "string", - "enum": [ - "base", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "arbitrum", - "polygon", - "polygon_amoy", - "ethereum", - "stellar", - "stellar_testnet", - "tron", - "solana", - "solana_devnet" + "accent_color": { + "type": [ + "string", + "null" ], - "example": "polygon" + "pattern": "^#[0-9a-f]{6}$", + "description": "Accent color applied to hosted pages such as the Terms of Service accept button", + "example": "#1d4ed8" }, - "created_at": { + "email_notifications": { + "type": "boolean", + "default": true, + "description": "Whether email notifications are enabled for this instance", + "example": true + }, + "require_passkey": { + "type": "boolean", + "default": false, + "description": "Whether passkey verification is required for protected actions", + "example": false + }, + "compliance_emails": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string", + "format": "email" + }, + "maxItems": 20, + "description": "When non-empty, compliance Request for Information emails are sent only to these addresses instead of all instance members", + "example": [ + "compliance@example.com" + ] + }, + "partner_tos_link": { "type": [ "string", "null" ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" + "format": "uri", + "description": "Passthrough Terms of Service: the page where your customers are presented with the BlindPay Terms of Service", + "example": "https://example.com/sign-up" + }, + "partner_tos_screenshot": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "Passthrough Terms of Service: a screenshot of how the BlindPay Terms of Service are displayed to your customers. Must be a file_url returned by POST /upload with bucket documents.", + "example": "https://files-documents.blindpay.com/1790000000000-tos-screenshot.png" + }, + "customer_rfi_emails_enabled": { + "type": "boolean", + "description": "Whether customer (customer) Request for Information notification emails are sent for this instance. Omit to leave unchanged.", + "example": true + }, + "partner_tos_terms_accepted": { + "type": "boolean", + "enum": [ + true + ], + "description": "Passthrough Terms of Service: accept the current Passthrough Terms of Service Partner Agreement (https://blindpay.com/passthrough-tos-partner-agreement). Dashboard users only; requires partner_tos_link and partner_tos_screenshot.", + "example": true } }, "required": [ - "id", - "name", - "network" + "name" ] }, - "CreateWalletIn": { + "UpdateInstanceMemberIn": { "type": "object", "properties": { - "network": { + "user_role": { "type": "string", "enum": [ - "base", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "arbitrum", - "polygon", - "polygon_amoy", - "ethereum", - "stellar", - "stellar_testnet", - "tron", - "solana", - "solana_devnet" - ], - "example": "polygon" - }, - "external_id": { - "type": [ - "string", - "null" + "owner", + "admin", + "finance", + "checker", + "operations", + "developer", + "viewer" ], - "maxLength": 255, - "example": "your-database-id" - }, - "name": { + "example": "admin" + } + }, + "required": [ + "user_role" + ] + }, + "MigrateInstanceOwnershipIn": { + "type": "object", + "properties": { + "user_id": { "type": "string", - "maxLength": 255, - "example": "Blindpay Wallet" + "minLength": 15, + "maxLength": 15, + "example": "us_000000000000" } }, "required": [ - "network", - "name" + "user_id" ] }, - "WalletBalanceOut": { + "FeeOptions": { "type": "object", "properties": { - "USDC": { - "$ref": "#/components/schemas/WalletTokenOut" + "payin_flat": { + "type": "integer", + "description": "Payin flat fee in cents", + "example": 40 }, - "USDT": { - "$ref": "#/components/schemas/WalletTokenOut" + "payin_percentage": { + "type": "integer", + "description": "Payin percentage fee in basis points", + "example": 50 }, - "USDB": { - "$ref": "#/components/schemas/WalletTokenOut" + "payout_flat": { + "type": "integer", + "description": "Payout flat fee in cents", + "example": 40 + }, + "payout_percentage": { + "type": "integer", + "description": "Payout percentage fee in basis points", + "example": 50 } }, "required": [ - "USDC", - "USDT", - "USDB" + "payin_flat", + "payin_percentage", + "payout_flat", + "payout_percentage" ] }, - "BlockchainWalletMessageOut": { - "type": "object", + "YieldFee": { + "type": [ + "object", + "null" + ], "properties": { - "message": { - "type": "string" + "blindpay_share_bps": { + "type": "integer", + "minimum": 0, + "maximum": 10000, + "example": 1500 + }, + "partner_share_bps": { + "type": "integer", + "minimum": 0, + "maximum": 10000, + "example": 0 + }, + "partner_wallet_address": { + "type": [ + "string", + "null" + ], + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "EVM address that receives the instance share", + "example": "0x0000000000000000000000000000000000000000" } }, "required": [ - "message" + "blindpay_share_bps", + "partner_share_bps" ] }, - "BlockchainWalletOut": { + "GetFeesOut": { "type": "object", "properties": { "id": { "type": "string", "minLength": 15, "maxLength": 15, - "example": "bw_000000000000" + "example": "fe_000000000000" }, - "name": { - "type": [ - "string", - "null" - ], - "example": "Wallet Display Name" + "instance_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" }, - "network": { + "ach": { + "$ref": "#/components/schemas/FeeOptions" + }, + "domestic_wire": { + "$ref": "#/components/schemas/FeeOptions" + }, + "rtp": { + "$ref": "#/components/schemas/FeeOptions" + }, + "international_swift": { + "$ref": "#/components/schemas/FeeOptions" + }, + "pix": { + "$ref": "#/components/schemas/FeeOptions" + }, + "pix_safe": { + "$ref": "#/components/schemas/FeeOptions" + }, + "ted": { + "allOf": [ + { + "$ref": "#/components/schemas/FeeOptions" + }, + { + "type": [ + "object", + "null" + ] + } + ] + }, + "ach_colombia": { + "$ref": "#/components/schemas/FeeOptions" + }, + "transfers_3": { + "$ref": "#/components/schemas/FeeOptions" + }, + "spei": { + "$ref": "#/components/schemas/FeeOptions" + }, + "sepa": { + "$ref": "#/components/schemas/FeeOptions" + }, + "faster_payments": { + "$ref": "#/components/schemas/FeeOptions" + }, + "tron": { + "$ref": "#/components/schemas/FeeOptions" + }, + "ethereum": { + "$ref": "#/components/schemas/FeeOptions" + }, + "polygon": { + "$ref": "#/components/schemas/FeeOptions" + }, + "base": { + "$ref": "#/components/schemas/FeeOptions" + }, + "arbitrum": { + "$ref": "#/components/schemas/FeeOptions" + }, + "stellar": { + "$ref": "#/components/schemas/FeeOptions" + }, + "solana": { + "$ref": "#/components/schemas/FeeOptions" + }, + "yield": { + "$ref": "#/components/schemas/YieldFee" + }, + "created_at": { "type": [ "string", "null" ], - "enum": [ - "base", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "arbitrum", - "polygon", - "polygon_amoy", - "ethereum", - "stellar", - "stellar_testnet", - "tron", - "solana", - "solana_devnet" - ], - "example": "polygon" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" }, - "address": { + "updated_at": { "type": [ "string", "null" ], - "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + } + }, + "required": [ + "id", + "instance_id", + "ach", + "domestic_wire", + "rtp", + "international_swift", + "pix", + "pix_safe", + "ach_colombia", + "transfers_3", + "spei", + "sepa", + "faster_payments", + "tron", + "ethereum", + "polygon", + "base", + "arbitrum", + "stellar", + "solana" + ] + }, + "InitiateTosOut": { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "example": "https://app.blindpay.com/e/terms-of-service?session_token=SESSION_TOKEN_FROM_INITIATE_TOS_RESPONSE" + } + }, + "required": [ + "url" + ] + }, + "InitiateTosIn": { + "type": "object", + "properties": { + "idempotency_key": { + "type": "string", + "format": "uuid", + "example": "123e4567-e89b-12d3-a456-426614174000" }, - "signature_tx_hash": { + "customer_id": { "type": [ "string", "null" ], - "example": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359" + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" }, - "is_account_abstraction": { + "redirect_url": { "type": [ - "boolean", + "string", "null" ], - "example": false - }, - "customer_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" + "format": "uri" } }, "required": [ - "id", - "name", - "network", - "customer_id" + "idempotency_key" ] }, - "CreateBlockchainWalletIn": { + "AcceptTosOut": { "type": "object", "properties": { - "name": { + "tos_id": { "type": "string", - "example": "Wallet Display Name" + "minLength": 15, + "maxLength": 15, + "example": "to_000000000000" }, - "network": { + "idempotency_key": { "type": "string", - "enum": [ - "base", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "arbitrum", - "polygon", - "polygon_amoy", - "ethereum", - "stellar", - "stellar_testnet", - "tron", - "solana", - "solana_devnet" - ], - "example": "polygon" + "format": "uuid", + "example": "123e4567-e89b-12d3-a456-426614174000" }, - "signature_tx_hash": { + "customer_id": { "type": [ "string", "null" ], - "example": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359" + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" }, - "address": { + "version": { "type": [ "string", "null" ], - "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + "enum": [ + "1.0.0", + "1.0.1" + ], + "example": "1.0.0" + } + }, + "required": [ + "tos_id", + "idempotency_key" + ] + }, + "CreatePassthroughTosIn": { + "type": "object", + "properties": { + "idempotency_key": { + "type": "string", + "format": "uuid", + "example": "123e4567-e89b-12d3-a456-426614174000" }, - "is_account_abstraction": { + "customer_id": { "type": [ - "boolean", + "string", "null" ], - "example": false + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "ip_address": { + "type": "string", + "format": "ip", + "description": "Public IP address of the customer device, as seen by your edge. Not the IP address of your servers.", + "example": "191.34.12.8" + }, + "user_agent": { + "type": "string", + "minLength": 1, + "maxLength": 1024, + "description": "The complete, unmodified User-Agent header sent by the browser of the customer", + "example": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36" } }, "required": [ - "name", - "network" + "idempotency_key", + "ip_address", + "user_agent" ] }, - "BankAccountOut": { + "WebhookEndpointOut": { "type": "object", "properties": { "id": { "type": "string", "minLength": 15, "maxLength": 15, - "example": "ba_000000000000" - }, - "type": { + "example": "we_000000000000" + } + }, + "required": [ + "id" + ] + }, + "WebhookEndpointIn": { + "type": "object", + "properties": { + "url": { "type": "string", - "enum": [ - "wire", - "ach", - "pix", - "pix_safe", - "ted", - "spei_bitso", - "transfers_bitso", - "ach_cop_bitso", - "international_swift", - "rtp", - "sepa" - ], - "example": "wire" + "format": "uri", + "example": "https://example.com/webhook" }, - "name": { + "events": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "customer.new", + "customer.update", + "customer.delete", + "bankAccount.new", + "payout.new", + "payout.update", + "payout.complete", + "payout.partnerFee", + "blockchainWallet.new", + "blockchainWallet.update", + "payin.new", + "payin.update", + "payin.complete", + "payin.partnerFee", + "tos.accept", + "limitIncrease.new", + "limitIncrease.update", + "virtualAccount.new", + "virtualAccount.complete", + "transfer.new", + "transfer.update", + "transfer.complete", + "wallet.new", + "wallet.update", + "wallet.inbound", + "payable.new", + "payable.update", + "payable.complete" + ] + }, + "example": [ + "customer.new" + ] + } + }, + "required": [ + "url", + "events" + ] + }, + "WebhookEndpoint": { + "type": "object", + "properties": { + "id": { "type": "string", - "example": "Bank Account Name" + "minLength": 15, + "maxLength": 15, + "example": "we_000000000000" }, - "pix_key": { - "type": [ - "string", - "null" - ], - "example": "14947677768" + "url": { + "type": "string", + "format": "uri", + "example": "https://example.com/webhook" }, - "beneficiary_name": { - "type": [ - "string", - "null" - ], - "maxLength": 128, - "example": "Individual full name or business name" + "events": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "customer.new", + "customer.update", + "customer.delete", + "bankAccount.new", + "payout.new", + "payout.update", + "payout.complete", + "payout.partnerFee", + "blockchainWallet.new", + "blockchainWallet.update", + "payin.new", + "payin.update", + "payin.complete", + "payin.partnerFee", + "tos.accept", + "limitIncrease.new", + "limitIncrease.update", + "virtualAccount.new", + "virtualAccount.complete", + "transfer.new", + "transfer.update", + "transfer.complete", + "wallet.new", + "wallet.update", + "wallet.inbound", + "payable.new", + "payable.update", + "payable.complete" + ] + }, + "example": [ + "customer.new" + ] }, - "routing_number": { - "type": [ - "string", - "null" + "last_event_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + }, + { + "type": "null" + } ], - "example": "012345678" + "example": "2024-01-01T00:00:00.000Z" }, - "account_number": { - "type": [ - "string", - "null" - ], - "example": "1001001234" + "instance_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" }, - "account_type": { + "created_at": { "type": [ "string", "null" ], - "enum": [ - "checking", - "saving" - ], - "example": "checking" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" }, - "account_class": { + "updated_at": { "type": [ "string", "null" ], - "enum": [ - "individual", - "business" - ], - "example": "individual" - }, - "address_line_1": { - "type": [ - "string", - "null" - ], - "example": "Address line 1" - }, - "address_line_2": { - "type": [ - "string", - "null" - ], - "example": "Address line 2" - }, - "city": { - "type": [ - "string", - "null" - ], - "example": "City" - }, - "state_province_region": { - "type": [ - "string", - "null" - ], - "example": "State/Province/Region" - }, - "country": { - "type": [ - "string", - "null" - ], - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "US" - }, - "postal_code": { - "type": [ - "string", - "null" - ], - "example": "Postal code" - }, - "spei_protocol": { - "type": [ - "string", - "null" - ], - "enum": [ - "clabe", - "debitcard", - "phonenum" - ], - "description": "For debitcard and phonenum the spei_institution_code is required", - "example": "clabe" - }, - "spei_institution_code": { - "type": [ - "string", - "null" - ], - "minLength": 5, - "maxLength": 5, - "example": "40002" - }, - "spei_clabe": { - "type": [ - "string", - "null" - ], - "example": "5482347403740546" - }, - "transfers_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "CVU", - "CBU", - "ALIAS" - ], - "example": "CVU" - }, - "transfers_account": { - "type": [ - "string", - "null" - ], - "example": "BM123123123123" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + } + }, + "required": [ + "id", + "url", + "events", + "instance_id" + ] + }, + "PortalAccessOut": { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "example": "https://example.com/webhook" + } + }, + "required": [ + "url" + ] + }, + "PayinOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" }, - "ach_cop_beneficiary_first_name": { + "pix_code": { "type": [ "string", "null" ], - "example": "Fernando" + "description": "PIX code", + "example": "00020101021226790014br.gov.bcb.pix2557brcode.starkinfra.com/v2/bcf07f6c4110454e9fd6f120bab13e835204000053039865802BR5915Blind Pay, Inc.6010Vila Velha62070503***6304BCAB" }, - "ach_cop_beneficiary_last_name": { + "memo_code": { "type": [ "string", "null" ], - "example": "Guzman Alarcón" + "description": "Memo code", + "example": "8K45GHBNT6BQ6462" }, - "ach_cop_document_id": { + "clabe": { "type": [ "string", "null" ], - "example": "1661105408" + "description": "CLABE code", + "example": "014027000000000008" }, - "ach_cop_document_type": { - "type": [ - "string", - "null" - ], + "status": { + "type": "string", "enum": [ - "CC", - "CE", - "NIT", - "PASS", - "PEP" - ], - "description": "CC - Cédula de Ciudadanía; CE - Cédula de Extranjería; NIT - Número de Identificación Tributaria; PASS - Passport; PEP - Permiso Especial de Permanencia", - "example": "CC" - }, - "ach_cop_email": { - "type": [ - "string", - "null" - ], - "example": "fernando.guzman@gmail.com" - }, - "ach_cop_bank_code": { - "type": [ - "string", - "null" - ], - "example": "051" - }, - "ach_cop_bank_account": { - "type": [ - "string", - "null" - ], - "example": "12345678" - }, - "swift_code_bic": { - "type": [ - "string", - "null" + "processing", + "on_hold", + "failed", + "refunded", + "completed" ], - "example": "123456789" + "description": "Payin general status", + "example": "processing" }, - "swift_account_holder_name": { - "type": [ - "string", - "null" - ], - "maxLength": 50, - "example": "John Doe" + "payin_quote_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "pq_000000000000" }, - "swift_account_number_iban": { - "type": [ - "string", - "null" - ], - "example": "123456789" + "instance_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" }, - "swift_beneficiary_address_line_1": { - "type": [ - "string", - "null" - ], - "example": "123 MAIN STREET SUITE 100" + "customer_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" }, - "swift_beneficiary_address_line_2": { - "type": [ - "string", - "null" - ], - "example": "BUILDING A FLOOR 5" + "partner_fee": { + "type": "integer", + "minimum": 0, + "default": 0, + "description": "Payin partner fee amount in cents", + "example": 25000 }, - "swift_beneficiary_country": { - "type": [ - "string", - "null" - ], - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" + "tracking_transaction": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Payin transaction step", + "example": "processing" + }, + "status": { + "type": [ + "string", + "null" + ], + "enum": [ + "failed", + "completed" + ], + "description": "Payin transaction status", + "example": "failed" + }, + "external_id": { + "type": [ + "string", + "null" + ], + "description": "Payin transaction external id", + "example": "12345678" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Payin transaction completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Blockchain transaction hash", + "example": "0x123...890" + }, + "provider_name": { + "type": [ + "string", + "null" + ], + "enum": [ + "Nvio Pagos", + "Brex", + "Stark Bank", + "JPMorgan Chase", + "HSBC", + "Inter", + "JP Morgan Chase", + "Bitso", + "Citi", + "CFSB", + "Triple A Technologies", + "BCB Group", + "Portage Bank", + "NMI" + ], + "description": "Payment provider name", + "example": "HSBC" + }, + "provider_transaction_id": { + "type": [ + "string", + "null" + ], + "description": "Payment provider transaction id", + "example": "" + }, + "sender_name": { + "type": [ + "string", + "null" + ], + "example": "John Doe Smith" + }, + "sender_bank_name": { + "type": [ + "string", + "null" + ], + "example": "Bank of America" + }, + "sender_tax_id": { + "type": [ + "string", + "null" + ], + "example": "123.456.789-10" + }, + "sender_bank_code": { + "type": [ + "string", + "null" + ], + "example": "00416968" + }, + "sender_account_number": { + "type": [ + "string", + "null" + ], + "example": "1234567890" + }, + "end_to_end_id": { + "type": [ + "string", + "null" + ], + "description": "BACEN Pix end-to-end transaction ID (govt Pix ID)", + "example": "E20018183202603311320vm6ALFpJpsS" + }, + "trace_number": { + "type": [ + "string", + "null" + ], + "example": "1234567890" + }, + "transaction_reference": { + "type": [ + "string", + "null" + ], + "example": "1234567890" + }, + "description": { + "type": [ + "string", + "null" + ], + "example": "Payment from John Doe Smith" + }, + "pse_instruction": { + "type": [ + "object", + "null" + ], + "properties": { + "payment_link": { + "type": "string", + "description": "PSE payment link URL", + "example": "https://pse.example.com/payment/abc123" + }, + "fid": { + "type": "string", + "description": "PSE provider reference used for webhook matching (the payin intent id)", + "example": "be6185ad-afdf-d682-2ca7-d447250f5e96" + }, + "payin_intent_id": { + "type": [ + "string", + "null" + ], + "description": "PSE payin intent id at the provider", + "example": "be6185ad-afdf-d682-2ca7-d447250f5e96" + }, + "expires_at": { + "type": [ + "string", + "null" + ], + "description": "When the PSE payment link expires", + "example": "2026-02-26T23:59:59Z" + }, + "full_name": { + "type": "string", + "description": "PSE payer full name", + "example": "Juan Pérez García" + }, + "tax_id": { + "type": "string", + "description": "PSE payer document number", + "example": "1234567890" + }, + "document_type": { + "type": "string", + "enum": [ + "CC", + "NIT" + ], + "description": "PSE payer document type", + "example": "CC" + }, + "phone": { + "type": "string", + "description": "PSE payer phone number", + "example": "+573001234567" + }, + "email": { + "type": "string", + "description": "PSE payer email", + "example": "juan@example.com" + }, + "bank_code": { + "type": [ + "string", + "null" + ], + "description": "PSE payer bank code", + "example": "1007" + } + }, + "required": [ + "payment_link", + "fid", + "full_name", + "tax_id", + "document_type", + "phone", + "email" + ] + }, + "transfers_instruction": { + "type": [ + "object", + "null" + ], + "properties": { + "account": { + "type": "string", + "description": "CVU/CBU/Alias account number", + "example": "0000003100012389237485" + }, + "type": { + "type": "string", + "enum": [ + "CVU", + "CBU", + "ALIAS" + ], + "description": "Account type (CVU, CBU, or ALIAS)", + "example": "CVU" + }, + "tax_id": { + "type": [ + "string", + "null" + ], + "description": "CUIT/CUIL (normalized, digits only)", + "example": "20123456786" + } + }, + "required": [ + "account", + "type" + ] + }, + "ted_instruction": { + "type": [ + "object", + "null" + ], + "properties": { + "beneficiary_name": { + "type": "string", + "example": "Blind Pay, Inc." + }, + "tax_id": { + "type": "string", + "example": "57.599.376/0001-81" + }, + "bank_code": { + "type": "string", + "example": "665" + }, + "bank_name": { + "type": "string", + "example": "STARK BANK S.A." + }, + "branch_code": { + "type": "string", + "example": "5340" + }, + "account_number": { + "type": "string", + "example": "01011707084-8" + }, + "account_type": { + "type": "string", + "example": "checking" + } + }, + "required": [ + "beneficiary_name", + "tax_id", + "bank_code", + "bank_name", + "branch_code", + "account_number", + "account_type" + ] + }, + "card_instruction": { + "type": [ + "object", + "null" + ], + "properties": { + "provider": { + "type": "string", + "description": "Which card gateway issued the tokenization key, so the checkout knows which tokenization library to load.", + "example": "nmi" + }, + "tokenization_key": { + "type": "string", + "description": "NMI Collect.js public tokenization key. Load https://secure.nmi.com/token/Collect.js with this key, tokenize the card in the browser, and submit the payment_token to the card-payment endpoint.", + "example": "KXypee-Vq3y2f-K6c7Dy-Wq92R5" + } + }, + "required": [ + "provider", + "tokenization_key" + ] + }, + "card_evidence": { + "type": [ + "object", + "null" + ], + "properties": { + "eci": { + "type": [ + "string", + "null" + ], + "description": "3DS ECI value returned by payer authentication", + "example": "05" + }, + "cavv": { + "type": [ + "string", + "null" + ], + "description": "3DS cardholder authentication verification value", + "example": "AAABBWcSNIdjeUZThmNHAAAAAAA=" + }, + "avs_response": { + "type": [ + "string", + "null" + ], + "description": "Gateway AVS result code", + "example": "Y" + }, + "cvv_response": { + "type": [ + "string", + "null" + ], + "description": "Gateway CVV result code", + "example": "M" + }, + "auth_code": { + "type": [ + "string", + "null" + ], + "description": "Issuer authorization code", + "example": "123456" + }, + "cardholder_name": { + "type": [ + "string", + "null" + ], + "description": "Cardholder name as submitted with the charge", + "example": "Jane Doe" + }, + "three_ds_version": { + "type": [ + "string", + "null" + ], + "description": "3DS protocol version used", + "example": "2.2.0" + } + } + }, + "card_failed_attempts": { + "type": [ + "integer", + "null" + ], + "description": "How many card charge attempts on this payin were declined. A payin stops accepting charges after the limit.", + "example": 0 + }, + "card_claim_at": { + "type": [ + "string", + "null" + ], + "description": "Set while a card charge attempt is in flight for this payin; guards against a double charge (NMI has no idempotency key).", + "example": null + }, + "card_gates_failed_at": { + "type": [ + "string", + "null" + ], + "description": "Set when an approved card sale failed the post-capture risk gates (CVV/AVS) and was voided; blocks any later confirmation of that charge.", + "example": null + } + }, + "required": [ + "step" + ] + }, + "tracking_payment": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Payment step", + "example": "on_hold" + }, + "provider_name": { + "type": [ + "string", + "null" + ], + "description": "Payment provider name", + "example": "blockchain" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Payment completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "review_source": { + "type": [ + "string", + "null" + ], + "description": "Primary risk source that sent this payin to manual review", + "example": "seon_review" + }, + "review_context": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "Structured risk context for manual review" + }, + "review_sources": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Every risk source that flagged this payin on the pending review", + "example": [ + "seon_review", + "new_instance" + ] + }, + "review_contexts": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "Structured risk context per flagging source" + }, + "approved_risk_sources": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Risk sources already approved by an analyst", + "example": [ + "seon_review" + ] + } + }, + "required": [ + "step" + ] + }, + "tracking_complete": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + } + }, + "required": [ + "step" + ] + }, + "manual_execution_status": { + "type": [ + "string", + "null" + ], + "enum": [ + "pending", + "concluded", + "failed" + ], + "description": "When non-null, the payin was created while the manual OTC liquidity toggle was ON. `pending` means an operator must convert BRL→USDT manually and click \"Mark concluded\"; `concluded` closes the internal flow. Customer-facing behavior is identical in either mode.", + "example": null + }, + "manual_concluded_at": { + "description": "When `manual_execution_status` transitioned to `concluded`. Postgres returns a Date; this transform normalizes to an ISO string for the SDK.", + "example": null + }, + "manual_concluded_by": { + "type": [ + "string", + "null" + ], + "description": "Identifier of the operator who marked the manual OTC concluded.", + "example": null + }, + "created_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + }, + "updated_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + }, + "image_url": { + "type": [ + "string", + "null" + ], + "format": "uri", + "example": "https://example.com/image.png" + }, + "first_name": { + "type": [ + "string", + "null" + ], + "example": "John" + }, + "last_name": { + "type": [ + "string", + "null" + ], + "example": "Doe" + }, + "legal_name": { + "type": [ + "string", + "null" + ], + "example": "Company Name Inc." + }, + "type": { + "type": "string", + "enum": [ + "individual", + "business" + ], + "example": "individual" + }, + "payment_method": { + "type": "string", + "enum": [ + "ach", + "ach_pull", + "wire", + "pix", + "card", + "ted", + "spei", + "transfers", + "pse", + "bre_b", + "international_swift", + "rtp" + ], + "example": "pix" + }, + "sender_amount": { + "type": [ + "number", + "null" + ], + "description": "52.40 BRL needs to be sent in a pix transfer", + "example": 5240 + }, + "receiver_amount": { + "type": [ + "number", + "null" + ], + "description": "10.10 USDC", + "example": 1010 + }, + "token": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB" + ], + "example": "USDC" + }, + "partner_fee_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "example": "pf_000000000000" + }, + "partner_fee_amount": { + "type": [ + "number", + "null" + ], + "default": 0, + "description": "1.5 USDC", + "example": 150 + }, + "total_fee_amount": { + "type": [ + "number", + "null" + ], + "default": 0, + "description": "1.53 USDC", + "example": 1.53 + }, + "commercial_quotation": { + "type": [ + "number", + "null" + ], + "description": "1 USD = 4.95 BRL", + "example": 495 + }, + "blindpay_quotation": { + "type": [ + "number", + "null" + ], + "description": "1 USD = 5.05 BRL (commercial quotation + (blindpay taxes))", + "example": 505 + }, + "currency": { + "type": "string", + "enum": [ + "BRL", + "USD", + "MXN", + "COP", + "ARS", + "EUR", + "GBP" + ], + "description": "ISO 4271 currency code", + "example": "BRL" + }, + "billing_fee_amount": { + "type": [ + "number", + "null" + ], + "description": "BlindPay fee in cents accrued to your billing cycle (charged at the end of the month). Virtual account deposits below $100.00 always accrue here, so small deposits are delivered in full.", + "example": 50 + }, + "transaction_fee_amount": { + "type": [ + "number", + "null" + ], + "description": "BlindPay fee in cents deducted from the transaction at the time it is processed. Virtual account deposits of $100.00 or more are charged here (unless your instance is configured for end-of-month billing, in which case every fee accrues to billing_fee_amount).", + "example": 100 + }, + "is_otc": { + "type": [ + "boolean", + "null" + ], + "description": "If true, the payin quote is for an OTC (Over the Counter) transaction", + "example": false + }, + "payer_rules": { + "type": [ + "object", + "null" + ], + "properties": { + "pix_allowed_tax_ids": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string", + "example": "123.456.789-09" + } + }, + "transfers_allowed_tax_id": { + "type": [ + "string", + "null" + ], + "example": "20-12345678-6" + }, + "pse_allowed_tax_ids": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string", + "example": "1234567890" + } + }, + "pse_full_name": { + "type": [ + "string", + "null" + ], + "maxLength": 50 + }, + "pse_document_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "CC", + "NIT" + ] + }, + "pse_document_number": { + "type": [ + "string", + "null" + ] + }, + "pse_email": { + "type": [ + "string", + "null" + ], + "format": "email" + }, + "pse_phone": { + "type": [ + "string", + "null" + ], + "pattern": "^\\+573\\d{9}$" + }, + "pse_bank_code": { + "type": [ + "string", + "null" + ] + } + }, + "example": { + "pix_allowed_tax_ids": [ + "123.456.789-09" + ], + "transfers_allowed_tax_id": "20-12345678-6", + "pse_allowed_tax_ids": [ + "1234567890" + ] + } + }, + "name": { + "type": "string", + "example": "Wallet Display Name" + }, + "address": { + "type": [ + "string", + "null" + ], + "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + }, + "network": { + "type": "string", + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "polygon" + }, + "blindpay_bank_details": { + "type": [ + "object", + "null" + ], + "properties": { + "routing_number": { + "type": "string", + "default": "121145349", + "example": "121145349" + }, + "account_number": { + "type": "string", + "default": "621327727210181", + "example": "621327727210181" + }, + "account_type": { + "type": "string", + "default": "Business checking", + "example": "Business checking" + }, + "swift_bic_code": { + "type": [ + "string", + "null" + ], + "default": "CHASUS33", + "example": "CHASUS33" + }, + "ach": { + "type": [ + "object", + "null" + ], + "properties": { + "routing_number": { + "type": "string", + "example": "123456789" + }, + "account_number": { + "type": "string", + "example": "123456789" + } + }, + "required": [ + "routing_number", + "account_number" + ] + }, + "wire": { + "type": [ + "object", + "null" + ], + "properties": { + "routing_number": { + "type": "string", + "example": "123456789" + }, + "account_number": { + "type": "string", + "example": "123456789" + } + }, + "required": [ + "routing_number", + "account_number" + ] + }, + "rtp": { + "type": [ + "object", + "null" + ], + "properties": { + "routing_number": { + "type": "string", + "example": "123456789" + }, + "account_number": { + "type": "string", + "example": "123456789" + } + }, + "required": [ + "routing_number", + "account_number" + ] + }, + "beneficiary": { + "type": "object", + "properties": { + "name": { + "type": "string", + "default": "BlindPay, Inc.", + "example": "BlindPay, Inc." + }, + "address_line_1": { + "type": "string", + "default": "8 The Green, #19364", + "example": "8 The Green, #19364" + }, + "address_line_2": { + "type": "string", + "default": "Dover, DE 19901", + "example": "Dover, DE 19901" + } + } + }, + "receiving_bank": { + "type": "object", + "properties": { + "name": { + "type": "string", + "default": "CFSB", + "example": "CFSB" + }, + "address_line_1": { + "type": "string", + "default": "1 Letterman Drive, Building A, Suite A4-700", + "example": "1 Letterman Drive, Building A, Suite A4-700" + }, + "address_line_2": { + "type": "string", + "default": "San Francisco, CA 94129", + "example": "San Francisco, CA 94129" + } + } + }, + "swift_account_number": { + "type": [ + "string", + "null" + ], + "example": "GB50TCCL04140449730892" + }, + "swift_receiving_bank": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": [ + "string", + "null" + ], + "example": "JPMorgan Chase" + }, + "address_line_1": { + "type": [ + "string", + "null" + ], + "example": "270 Park Ave" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "New York, NY, 10017-2070" + } + } + } + }, + "required": [ + "beneficiary", + "receiving_bank" + ] + }, + "pse_payment_link": { + "type": [ + "string", + "null" ], - "example": "MX" + "description": "PSE payment link (derived from tracking_transaction.pse_instruction)", + "example": "https://pse.example.com/payment/abc123" }, - "swift_beneficiary_city": { + "pse_full_name": { "type": [ "string", "null" ], - "example": "MEXICO CITY" + "description": "PSE payer full name", + "example": "Juan Pérez García" }, - "swift_beneficiary_state_province_region": { + "pse_tax_id": { "type": [ "string", "null" ], - "example": "MX" + "description": "PSE payer document number", + "example": "1234567890" }, - "swift_beneficiary_postal_code": { + "pse_document_type": { "type": [ "string", "null" ], - "example": "11530" + "enum": [ + "CC", + "NIT" + ], + "description": "PSE payer document type", + "example": "CC" + } + }, + "required": [ + "id", + "status", + "payin_quote_id", + "instance_id", + "customer_id", + "tracking_transaction", + "tracking_payment", + "tracking_complete", + "type", + "payment_method", + "sender_amount", + "receiver_amount", + "token", + "commercial_quotation", + "blindpay_quotation", + "currency", + "name", + "network" + ] + }, + "CreatePayinOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "pi_000000000000" }, - "swift_bank_name": { + "status": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "failed", + "refunded", + "completed" + ], + "description": "Payin general status", + "example": "processing" + }, + "pix_code": { "type": [ "string", "null" ], - "example": "Banco Regional SA" + "description": "PIX code", + "example": "00020101021226790014br.gov.bcb.pix2557brcode.starkinfra.com/v2/bcf07f6c4110454e9fd6f120bab13e835204000053039865802BR5915Blind Pay, Inc.6010Vila Velha62070503***6304BCAB" + }, + "memo_code": { + "type": [ + "string", + "null" + ], + "description": "Memo code", + "example": "8K45GHBNT6BQ6462" + }, + "clabe": { + "type": [ + "string", + "null" + ], + "description": "CLABE code", + "example": "014027000000000008" + }, + "partner_fee": { + "type": "integer", + "minimum": 0, + "default": 0, + "description": "Payin partner fee amount in cents", + "example": 25000 + }, + "tracking_complete": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + } + }, + "required": [ + "step" + ] + }, + "tracking_payment": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Payment step", + "example": "on_hold" + }, + "provider_name": { + "type": [ + "string", + "null" + ], + "description": "Payment provider name", + "example": "blockchain" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Payment completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "review_source": { + "type": [ + "string", + "null" + ], + "description": "Primary risk source that sent this payin to manual review", + "example": "seon_review" + }, + "review_context": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "Structured risk context for manual review" + }, + "review_sources": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Every risk source that flagged this payin on the pending review", + "example": [ + "seon_review", + "new_instance" + ] + }, + "review_contexts": { + "type": [ + "object", + "null" + ], + "additionalProperties": {}, + "description": "Structured risk context per flagging source" + }, + "approved_risk_sources": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Risk sources already approved by an analyst", + "example": [ + "seon_review" + ] + } + }, + "required": [ + "step" + ] + }, + "tracking_transaction": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Payin transaction step", + "example": "processing" + }, + "status": { + "type": [ + "string", + "null" + ], + "enum": [ + "failed", + "completed" + ], + "description": "Payin transaction status", + "example": "failed" + }, + "external_id": { + "type": [ + "string", + "null" + ], + "description": "Payin transaction external id", + "example": "12345678" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Payin transaction completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Blockchain transaction hash", + "example": "0x123...890" + }, + "provider_name": { + "type": [ + "string", + "null" + ], + "enum": [ + "Nvio Pagos", + "Brex", + "Stark Bank", + "JPMorgan Chase", + "HSBC", + "Inter", + "JP Morgan Chase", + "Bitso", + "Citi", + "CFSB", + "Triple A Technologies", + "BCB Group", + "Portage Bank", + "NMI" + ], + "description": "Payment provider name", + "example": "HSBC" + }, + "provider_transaction_id": { + "type": [ + "string", + "null" + ], + "description": "Payment provider transaction id", + "example": "" + }, + "sender_name": { + "type": [ + "string", + "null" + ], + "example": "John Doe Smith" + }, + "sender_bank_name": { + "type": [ + "string", + "null" + ], + "example": "Bank of America" + }, + "sender_tax_id": { + "type": [ + "string", + "null" + ], + "example": "123.456.789-10" + }, + "sender_bank_code": { + "type": [ + "string", + "null" + ], + "example": "00416968" + }, + "sender_account_number": { + "type": [ + "string", + "null" + ], + "example": "1234567890" + }, + "end_to_end_id": { + "type": [ + "string", + "null" + ], + "description": "BACEN Pix end-to-end transaction ID (govt Pix ID)", + "example": "E20018183202603311320vm6ALFpJpsS" + }, + "trace_number": { + "type": [ + "string", + "null" + ], + "example": "1234567890" + }, + "transaction_reference": { + "type": [ + "string", + "null" + ], + "example": "1234567890" + }, + "description": { + "type": [ + "string", + "null" + ], + "example": "Payment from John Doe Smith" + }, + "pse_instruction": { + "type": [ + "object", + "null" + ], + "properties": { + "payment_link": { + "type": "string", + "description": "PSE payment link URL", + "example": "https://pse.example.com/payment/abc123" + }, + "fid": { + "type": "string", + "description": "PSE provider reference used for webhook matching (the payin intent id)", + "example": "be6185ad-afdf-d682-2ca7-d447250f5e96" + }, + "payin_intent_id": { + "type": [ + "string", + "null" + ], + "description": "PSE payin intent id at the provider", + "example": "be6185ad-afdf-d682-2ca7-d447250f5e96" + }, + "expires_at": { + "type": [ + "string", + "null" + ], + "description": "When the PSE payment link expires", + "example": "2026-02-26T23:59:59Z" + }, + "full_name": { + "type": "string", + "description": "PSE payer full name", + "example": "Juan Pérez García" + }, + "tax_id": { + "type": "string", + "description": "PSE payer document number", + "example": "1234567890" + }, + "document_type": { + "type": "string", + "enum": [ + "CC", + "NIT" + ], + "description": "PSE payer document type", + "example": "CC" + }, + "phone": { + "type": "string", + "description": "PSE payer phone number", + "example": "+573001234567" + }, + "email": { + "type": "string", + "description": "PSE payer email", + "example": "juan@example.com" + }, + "bank_code": { + "type": [ + "string", + "null" + ], + "description": "PSE payer bank code", + "example": "1007" + } + }, + "required": [ + "payment_link", + "fid", + "full_name", + "tax_id", + "document_type", + "phone", + "email" + ] + }, + "transfers_instruction": { + "type": [ + "object", + "null" + ], + "properties": { + "account": { + "type": "string", + "description": "CVU/CBU/Alias account number", + "example": "0000003100012389237485" + }, + "type": { + "type": "string", + "enum": [ + "CVU", + "CBU", + "ALIAS" + ], + "description": "Account type (CVU, CBU, or ALIAS)", + "example": "CVU" + }, + "tax_id": { + "type": [ + "string", + "null" + ], + "description": "CUIT/CUIL (normalized, digits only)", + "example": "20123456786" + } + }, + "required": [ + "account", + "type" + ] + }, + "ted_instruction": { + "type": [ + "object", + "null" + ], + "properties": { + "beneficiary_name": { + "type": "string", + "example": "Blind Pay, Inc." + }, + "tax_id": { + "type": "string", + "example": "57.599.376/0001-81" + }, + "bank_code": { + "type": "string", + "example": "665" + }, + "bank_name": { + "type": "string", + "example": "STARK BANK S.A." + }, + "branch_code": { + "type": "string", + "example": "5340" + }, + "account_number": { + "type": "string", + "example": "01011707084-8" + }, + "account_type": { + "type": "string", + "example": "checking" + } + }, + "required": [ + "beneficiary_name", + "tax_id", + "bank_code", + "bank_name", + "branch_code", + "account_number", + "account_type" + ] + }, + "card_instruction": { + "type": [ + "object", + "null" + ], + "properties": { + "provider": { + "type": "string", + "description": "Which card gateway issued the tokenization key, so the checkout knows which tokenization library to load.", + "example": "nmi" + }, + "tokenization_key": { + "type": "string", + "description": "NMI Collect.js public tokenization key. Load https://secure.nmi.com/token/Collect.js with this key, tokenize the card in the browser, and submit the payment_token to the card-payment endpoint.", + "example": "KXypee-Vq3y2f-K6c7Dy-Wq92R5" + } + }, + "required": [ + "provider", + "tokenization_key" + ] + }, + "card_evidence": { + "type": [ + "object", + "null" + ], + "properties": { + "eci": { + "type": [ + "string", + "null" + ], + "description": "3DS ECI value returned by payer authentication", + "example": "05" + }, + "cavv": { + "type": [ + "string", + "null" + ], + "description": "3DS cardholder authentication verification value", + "example": "AAABBWcSNIdjeUZThmNHAAAAAAA=" + }, + "avs_response": { + "type": [ + "string", + "null" + ], + "description": "Gateway AVS result code", + "example": "Y" + }, + "cvv_response": { + "type": [ + "string", + "null" + ], + "description": "Gateway CVV result code", + "example": "M" + }, + "auth_code": { + "type": [ + "string", + "null" + ], + "description": "Issuer authorization code", + "example": "123456" + }, + "cardholder_name": { + "type": [ + "string", + "null" + ], + "description": "Cardholder name as submitted with the charge", + "example": "Jane Doe" + }, + "three_ds_version": { + "type": [ + "string", + "null" + ], + "description": "3DS protocol version used", + "example": "2.2.0" + } + } + }, + "card_failed_attempts": { + "type": [ + "integer", + "null" + ], + "description": "How many card charge attempts on this payin were declined. A payin stops accepting charges after the limit.", + "example": 0 + }, + "card_claim_at": { + "type": [ + "string", + "null" + ], + "description": "Set while a card charge attempt is in flight for this payin; guards against a double charge (NMI has no idempotency key).", + "example": null + }, + "card_gates_failed_at": { + "type": [ + "string", + "null" + ], + "description": "Set when an approved card sale failed the post-capture risk gates (CVV/AVS) and was voided; blocks any later confirmation of that charge.", + "example": null + } + }, + "required": [ + "step" + ] }, - "swift_bank_address_line_1": { + "billing_fee_amount": { "type": [ - "string", + "number", "null" ], - "example": "123 Main Street, Suite 100, Downtown District, City Center CP 12345" + "description": "BlindPay fee in cents accrued to your billing cycle (charged at the end of the month). Virtual account deposits below $100.00 always accrue here, so small deposits are delivered in full.", + "example": 50 }, - "swift_bank_address_line_2": { + "transaction_fee_amount": { "type": [ - "string", + "number", "null" ], - "example": "456 Oak Avenue, Building 7, Financial District, Business Center CP 54321" + "description": "BlindPay fee in cents deducted from the transaction at the time it is processed. Virtual account deposits of $100.00 or more are charged here (unless your instance is configured for end-of-month billing, in which case every fee accrues to billing_fee_amount).", + "example": 100 }, - "swift_bank_country": { - "type": [ - "string", - "null" - ], - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "MX" + "blindpay_bank_details": { + "type": "object", + "properties": { + "routing_number": { + "type": "string", + "default": "121145349", + "example": "121145349" + }, + "account_number": { + "type": "string", + "default": "621327727210181", + "example": "621327727210181" + }, + "account_type": { + "type": "string", + "default": "Business checking", + "example": "Business checking" + }, + "swift_bic_code": { + "type": [ + "string", + "null" + ], + "default": "CHASUS33", + "example": "CHASUS33" + }, + "ach": { + "type": [ + "object", + "null" + ], + "properties": { + "routing_number": { + "type": "string", + "example": "123456789" + }, + "account_number": { + "type": "string", + "example": "123456789" + } + }, + "required": [ + "routing_number", + "account_number" + ] + }, + "wire": { + "type": [ + "object", + "null" + ], + "properties": { + "routing_number": { + "type": "string", + "example": "123456789" + }, + "account_number": { + "type": "string", + "example": "123456789" + } + }, + "required": [ + "routing_number", + "account_number" + ] + }, + "rtp": { + "type": [ + "object", + "null" + ], + "properties": { + "routing_number": { + "type": "string", + "example": "123456789" + }, + "account_number": { + "type": "string", + "example": "123456789" + } + }, + "required": [ + "routing_number", + "account_number" + ] + }, + "beneficiary": { + "type": "object", + "properties": { + "name": { + "type": "string", + "default": "BlindPay, Inc.", + "example": "BlindPay, Inc." + }, + "address_line_1": { + "type": "string", + "default": "8 The Green, #19364", + "example": "8 The Green, #19364" + }, + "address_line_2": { + "type": "string", + "default": "Dover, DE 19901", + "example": "Dover, DE 19901" + } + } + }, + "receiving_bank": { + "type": "object", + "properties": { + "name": { + "type": "string", + "default": "CFSB", + "example": "CFSB" + }, + "address_line_1": { + "type": "string", + "default": "1 Letterman Drive, Building A, Suite A4-700", + "example": "1 Letterman Drive, Building A, Suite A4-700" + }, + "address_line_2": { + "type": "string", + "default": "San Francisco, CA 94129", + "example": "San Francisco, CA 94129" + } + } + }, + "swift_account_number": { + "type": [ + "string", + "null" + ], + "example": "GB50TCCL04140449730892" + }, + "swift_receiving_bank": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": [ + "string", + "null" + ], + "example": "JPMorgan Chase" + }, + "address_line_1": { + "type": [ + "string", + "null" + ], + "example": "270 Park Ave" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "New York, NY, 10017-2070" + } + } + } + }, + "required": [ + "beneficiary", + "receiving_bank" + ] }, - "swift_bank_city": { + "customer_id": { "type": [ "string", "null" ], - "example": "City" + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" }, - "swift_bank_state_province_region": { + "receiver_amount": { "type": [ - "string", + "number", "null" ], - "example": "District" + "description": "10.10 USDC", + "example": 1010 }, - "swift_bank_postal_code": { + "payment_method": { "type": [ "string", "null" ], - "example": "11530" + "enum": [ + "ach", + "ach_pull", + "wire", + "pix", + "card", + "ted", + "spei", + "transfers", + "pse", + "bre_b", + "international_swift", + "rtp" + ], + "example": "pix" }, - "swift_ifsc_branch_code": { + "sender_amount": { "type": [ - "string", + "number", "null" ], - "pattern": "^[A-Z]{4}0[A-Z0-9]{6}$", - "example": "BARB0AHIMCI" + "description": "52.40 BRL needs to be sent in a pix transfer", + "example": 5240 + } + }, + "required": [ + "id", + "status", + "tracking_complete", + "tracking_payment", + "tracking_transaction", + "blindpay_bank_details" + ] + }, + "CreatePayinIn": { + "type": "object", + "properties": { + "payin_quote_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "pq_000000000000" + } + }, + "required": [ + "payin_quote_id" + ] + }, + "CreateCardPaymentOut": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "example": true }, - "swift_intermediary_bank_swift_code_bic": { - "anyOf": [ - { + "provider_transaction_id": { + "type": "string", + "description": "Gateway transaction id of the approved card sale", + "example": "8584364761" + }, + "status": { + "type": "string", + "enum": [ + "confirmed" + ], + "description": "The card payment is confirmed and the stablecoin delivery pipeline was released", + "example": "confirmed" + } + }, + "required": [ + "success", + "provider_transaction_id", + "status" + ] + }, + "CreateCardPaymentIn": { + "type": "object", + "properties": { + "payment_token": { + "type": "string", + "minLength": 1, + "description": "Single-use Collect.js payment token (expires 24h after creation, destroyed after use)", + "example": "8kR4TfnC-gU5ZpZ-2jWgJ9-536t4AMnVUzj" + }, + "cardholder_name": { + "type": "string", + "minLength": 1, + "description": "Name printed on the card", + "example": "Jane Doe" + }, + "billing_address": { + "type": "object", + "properties": { + "address1": { "type": "string", - "minLength": 8, - "maxLength": 8 + "minLength": 1, + "example": "100 Main St" }, - { + "city": { "type": "string", - "minLength": 11, - "maxLength": 11 + "minLength": 1, + "example": "Chicago" }, - { - "type": "null" + "state": { + "type": [ + "string", + "null" + ], + "example": "IL" + }, + "zip": { + "type": "string", + "minLength": 1, + "example": "60601" + }, + "country": { + "type": "string", + "minLength": 2, + "maxLength": 2, + "example": "US" } + }, + "required": [ + "address1", + "city", + "zip", + "country" ], - "example": "AEIBARB1" + "description": "Cardholder billing address, submitted to the gateway for AVS" }, - "swift_intermediary_bank_account_number_iban": { + "three_ds": { "type": [ - "string", + "object", "null" ], - "maxLength": 34, - "example": "123456789" + "properties": { + "cavv": { + "type": "string", + "minLength": 1, + "example": "AAABBWcSNIdjeUZThmNHAAAAAAA=" + }, + "eci": { + "type": "string", + "minLength": 1, + "example": "05" + }, + "xid": { + "type": [ + "string", + "null" + ], + "example": "MDAwMDAwMDAwMDAwMDAwMzIyNzY=" + }, + "cardholder_auth": { + "type": [ + "string", + "null" + ], + "example": "verified" + }, + "three_ds_version": { + "type": [ + "string", + "null" + ], + "example": "2.2.0" + }, + "directory_server_id": { + "type": [ + "string", + "null" + ], + "example": "f38e6948-5388-41a6-bca4-b49723c19437" + } + }, + "required": [ + "cavv", + "eci" + ], + "description": "3D Secure authentication result from Gateway.js. Required on production instances." + } + }, + "required": [ + "payment_token", + "cardholder_name", + "billing_address" + ] + }, + "CreatePayinQuoteOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "qu_000000000000" }, - "swift_intermediary_bank_name": { + "expires_at": { "type": [ - "string", + "number", "null" ], - "example": "Banco Regional SA" + "description": "Epoch timestamp in milliseconds after which the quote can no longer be used to create a payin: 5 minutes after creation, or 10 seconds for OTC quotes.", + "example": 1712958191000 }, - "swift_intermediary_bank_country": { + "commercial_quotation": { "type": [ - "string", + "number", "null" ], - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" + "description": "1 USD = 4.95 BRL", + "example": 495 + }, + "blindpay_quotation": { + "type": [ + "number", + "null" ], - "example": "US" + "description": "1 USD = 5.05 BRL (commercial quotation + (blindpay taxes))", + "example": 505 }, - "sepa_iban": { + "receiver_amount": { "type": [ - "string", + "number", "null" ], - "example": "DE89370400440532013000" + "description": "10.10 USDC", + "example": 1010 }, - "sepa_beneficiary_bic": { + "sender_amount": { + "type": [ + "number", + "null" + ], + "description": "52.40 BRL needs to be sent in a pix transfer", + "example": 5240 + }, + "partner_fee_amount": { + "type": [ + "number", + "null" + ], + "default": 0, + "description": "1.5 USDC", + "example": 150 + }, + "flat_fee": { + "type": [ + "number", + "null" + ], + "description": "0.5 USDC", + "example": 50 + }, + "billing_fee_amount": { + "type": [ + "number", + "null" + ], + "description": "BlindPay fee in cents accrued to your billing cycle (charged at the end of the month). Virtual account deposits below $100.00 always accrue here, so small deposits are delivered in full.", + "example": 50 + }, + "is_otc": { + "type": [ + "boolean", + "null" + ], + "description": "If true, the payin quote is for an OTC (Over the Counter) transaction", + "example": false + } + }, + "required": [ + "id", + "expires_at", + "commercial_quotation", + "blindpay_quotation", + "receiver_amount", + "sender_amount", + "flat_fee" + ] + }, + "CreatePayinQuoteIn": { + "type": "object", + "properties": { + "blockchain_wallet_id": { "type": [ "string", "null" ], - "description": "BIC/SWIFT code of the beneficiary bank", - "example": "TRWIBEB1XXX" + "minLength": 15, + "maxLength": 15, + "example": "bw_000000000000" }, - "sepa_beneficiary_legal_name": { + "wallet_id": { "type": [ "string", "null" ], - "maxLength": 128, - "example": "Hans Müller" + "minLength": 15, + "maxLength": 15, + "example": "bl_000000000000" }, - "sepa_beneficiary_address_line_1": { - "type": [ - "string", - "null" + "currency_type": { + "type": "string", + "enum": [ + "sender", + "receiver" ], - "example": "Friedrichstraße 12" + "description": "", + "example": "sender" }, - "sepa_beneficiary_address_line_2": { + "cover_fees": { "type": [ - "string", + "boolean", "null" ], - "example": "Apt 4B" + "description": "If true, the sender will cover the fees. If false, the customer will cover the fees.", + "example": true }, - "sepa_beneficiary_city": { - "type": [ - "string", - "null" - ], - "example": "Berlin" + "request_amount": { + "type": "integer", + "minimum": 500, + "description": "1000 represents 10.00, 2050 represents 20.50", + "example": 1000 }, - "sepa_beneficiary_state_province_region": { - "type": [ - "string", - "null" + "payment_method": { + "type": "string", + "enum": [ + "ach", + "ach_pull", + "wire", + "pix", + "card", + "ted", + "spei", + "transfers", + "pse", + "international_swift", + "rtp" ], - "example": "Berlin" + "example": "pix" }, - "sepa_beneficiary_postal_code": { - "type": [ - "string", - "null" + "token": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB" ], - "example": "10117" + "example": "USDC" }, - "sepa_beneficiary_country": { + "partner_fee_id": { "type": [ "string", "null" ], - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "DE" + "minLength": 15, + "maxLength": 15, + "example": "pf_000000000000" }, - "business_industry": { + "payer_rules": { "type": [ - "string", + "object", "null" ], - "enum": [ - "111998", - "112120", - "113310", - "115114", - "541211", - "541810", - "541430", - "541715", - "541930", - "561422", - "561311", - "561612", - "561740", - "561730", - "236115", - "236220", - "237310", - "238210", - "811111", - "812111", - "812112", - "532111", - "624410", - "541922", - "811210", - "812199", - "611110", - "611310", - "611410", - "611710", - "211120", - "212114", - "221310", - "562111", - "562920", - "213112", - "522110", - "522210", - "522320", - "523150", - "523940", - "523999", - "524113", - "813110", - "813211", - "813219", - "551112", - "721110", - "722511", - "722513", - "561510", - "713110", - "713210", - "712110", - "711110", - "711211", - "621111", - "621210", - "622110", - "623110", - "621511", - "623220", - "541940", - "621399", - "621910", - "541110", - "311421", - "337121", - "322220", - "339920", - "334210", - "339930", - "312130", - "334111", - "334118", - "325412", - "339112", - "336110", - "336390", - "315990", - "313110", - "339910", - "516120", - "513130", - "512250", - "519130", - "711410", - "711510", - "531110", - "531120", - "531130", - "531190", - "531210", - "531311", - "531312", - "531320", - "531390", - "454110", - "445110", - "455110", - "457110", - "449210", - "444110", - "459210", - "459120", - "445320", - "458110", - "458210", - "458310", - "455219", - "424210", - "456110", - "446120", - "541511", - "541512", - "541519", - "518210", - "511210", - "517111", - "517112", - "517410", - "481111", - "483111", - "485210", - "488510", - "484121", - "493110", - "423430", - "423690", - "423110", - "423830", - "423840", - "423510", - "424690", - "424990", - "424410", - "424480", - "423940", - "541611", - "541618", - "541330", - "541990", - "541214", - "561499" - ], - "example": "541511" + "properties": { + "pix_allowed_tax_ids": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string", + "example": "123.456.789-09" + } + }, + "transfers_allowed_tax_id": { + "type": [ + "string", + "null" + ], + "example": "20-12345678-6" + }, + "pse_allowed_tax_ids": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string", + "example": "1234567890" + } + }, + "pse_full_name": { + "type": [ + "string", + "null" + ], + "maxLength": 50 + }, + "pse_document_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "CC", + "NIT" + ] + }, + "pse_document_number": { + "type": [ + "string", + "null" + ] + }, + "pse_email": { + "type": [ + "string", + "null" + ], + "format": "email" + }, + "pse_phone": { + "type": [ + "string", + "null" + ], + "pattern": "^\\+573\\d{9}$" + }, + "pse_bank_code": { + "type": [ + "string", + "null" + ] + } + }, + "example": { + "pix_allowed_tax_ids": [ + "123.456.789-09" + ], + "transfers_allowed_tax_id": "20-12345678-6", + "pse_allowed_tax_ids": [ + "1234567890" + ] + } }, - "phone_number": { + "is_otc": { "type": [ - "string", + "boolean", "null" ], - "example": "+13055555555" + "description": "If true, the payin quote is for an OTC (Over the Counter) transaction", + "example": false }, - "tax_id": { + "funding_bank_account_id": { "type": [ "string", "null" ], - "maxLength": 32, - "example": "536804398" + "minLength": 15, + "maxLength": 15, + "description": "Plaid-connected bank account that funds the payin by ach pull. Required when payment_method is ach_pull, not accepted otherwise.", + "example": "ba_000000000000" + } + }, + "required": [ + "currency_type", + "request_amount", + "payment_method", + "token" + ] + }, + "PayableOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "pb_000000000000" }, - "date_of_birth": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, + "instance_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "customer_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "from": { + "$ref": "#/components/schemas/PayableParty" + }, + "to": { + "allOf": [ { - "type": "string" + "$ref": "#/components/schemas/PayableParty" }, { - "type": "null" + "description": "The beneficiary being paid." } + ] + }, + "currency": { + "type": "string", + "enum": [ + "BRL", + "USD", + "MXN", + "COP", + "ARS", + "EUR", + "GBP" ], - "example": "1998-01-01T00:00:00Z" + "description": "ISO 4217 currency code of the payable.", + "example": "BRL" }, - "pix_safe_bank_code": { + "line_items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PayableLineItem" + }, + "maxItems": 100, + "default": [], + "description": "Invoice line items. The payable total is the line item sum plus taxes minus discount." + }, + "note": { "type": [ "string", "null" ], - "pattern": "^\\d{4,8}$", - "example": "00416968" + "maxLength": 512, + "example": "August retainer" }, - "pix_safe_branch_code": { + "discount": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "default": 0, + "description": "Discount in cents of the payable currency.", + "example": 0 + }, + "taxes": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "default": 0, + "description": "Taxes in cents of the payable currency.", + "example": 0 + }, + "boleto_barcode": { "type": [ "string", "null" ], - "pattern": "^\\d{4}(-\\d)?$", - "example": "0001" + "minLength": 1, + "maxLength": 512, + "description": "Boleto or arrecadação code (linha digitável or barcode).", + "example": "34191.79001 01043.510047 91020.150008 1 84660000002000" }, - "pix_safe_cpf_cnpj": { + "pix_qrcode": { "type": [ "string", "null" ], - "example": "12345678901" + "minLength": 1, + "maxLength": 512, + "description": "PIX copia e cola (EMV) payload." }, - "ted_bank_code": { + "document_file": { "type": [ "string", "null" ], - "pattern": "^\\d{3,5}$", - "example": "033" + "format": "uri", + "description": "The boleto or invoice document, as a file URL returned by POST /upload with bucket `documents`. Not accepted for PIX payables. Read it through POST /presign.", + "example": "https://files.blindpay.com/1712345678901-boleto.pdf" }, - "ted_branch_code": { + "due_date": { "type": [ "string", "null" ], - "pattern": "^\\d{4}(-\\d)?$", - "example": "0001" + "example": "2026-08-10" }, - "ted_cpf_cnpj": { + "scheduled_at": { "type": [ "string", "null" ], - "example": "12345678901" + "description": "When to pay this payable automatically. Not executed yet: stored for the upcoming scheduling feature.", + "example": "2026-08-10T12:00:00.000Z" }, - "tron_wallet_hash": { + "status": { + "type": "string", + "enum": [ + "draft", + "processing", + "completed", + "canceled" + ], + "description": "draft until a payout executes this payable, processing while one is in flight, completed when paid, canceled when a draft is deleted. A failed or refunded attempt returns it to draft; follow the payout for the attempt detail.", + "example": "draft" + }, + "created_at": { "type": [ "string", "null" ], - "example": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" }, - "offramp_wallets": { + "updated_at": { "type": [ - "array", + "string", "null" ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "ow_000000000000" - }, - "external_id": { - "type": [ - "string", - "null" - ], - "example": "your_external_id" - }, - "circle_wallet_id": { - "type": [ - "string", - "null" - ], - "example": "01234567-abcd-efgh-ijkl-012345678901" - }, - "network": { - "type": "string", - "enum": [ - "tron", - "solana", - "solana_devnet", - "arbitrum", - "base", - "ethereum", - "polygon", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "polygon_amoy" - ], - "example": "tron" - }, - "address": { - "type": "string", - "example": "TALJN9zTTEL9TVBb4WuTt6wLvPqJZr3hvb" - } - }, - "required": [ - "id", - "network", - "address" - ] - }, - "example": [ - { - "address": "TALJN9zTTEL9TVBb4WuTt6wLvPqJZr3hvb", - "id": "ow_000000000000", - "network": "tron", - "external_id": "your_external_id" - } + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + }, + "amount": { + "type": [ + "integer", + "null" + ], + "description": "Derived total in cents: line item sum plus taxes minus discount. For boleto/PIX the rail amount is re-resolved from the code at quote time and can differ (fines, interest).", + "example": 300000 + }, + "payout_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "description": "The payout executing this payable, once one exists. Null while the payable is a draft.", + "example": "po_000000000000" + }, + "bank_account": { + "$ref": "#/components/schemas/PayableBankAccount" + }, + "last_attempt_status": { + "type": [ + "string", + "null" + ], + "enum": [ + "failed", + "refunded" + ], + "description": "Why the payable returned to draft: the attempt in payout_id failed before funding or was refunded after it. Set only on that payable.update event; follow the payout for the detail.", + "example": "failed" + }, + "first_name": { + "type": [ + "string", + "null" + ] + }, + "last_name": { + "type": [ + "string", + "null" + ] + }, + "legal_name": { + "type": [ + "string", + "null" ] + } + }, + "required": [ + "id", + "instance_id", + "customer_id", + "currency", + "status", + "amount" + ] + }, + "CreateBankAccountIn": { + "type": [ + "object", + "null" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "wire", + "ach", + "pix", + "pix_safe", + "ted", + "spei_bitso", + "transfers_bitso", + "ach_cop_bitso", + "international_swift", + "rtp", + "sepa", + "faster_payments" + ], + "example": "wire" + }, + "name": { + "type": "string", + "example": "Bank Account Name" }, "status": { "type": [ @@ -22583,6 +25620,9 @@ "in_swift_p0107", "in_swift_p0108", "in_swift_p0109", + "in_swift_p0304", + "in_swift_p1099", + "in_swift_p1108", "jp_swift_1001", "jp_swift_1002", "jp_swift_1003", @@ -23291,46 +26331,7080 @@ "za_swift_10301", "za_swift_27201" ], - "example": "bh_swift_afl" + "example": "bh_swift_afl" + }, + "pix_key": { + "type": [ + "string", + "null" + ], + "example": "14947677768" + }, + "force_cpf_cnpj": { + "type": [ + "boolean", + "null" + ], + "description": "Force CPF/CNPJ validation for PIX key", + "example": false + }, + "beneficiary_name": { + "type": [ + "string", + "null" + ], + "maxLength": 128, + "example": "Individual full name or business name" + }, + "routing_number": { + "type": [ + "string", + "null" + ], + "example": "012345678" + }, + "account_number": { + "type": [ + "string", + "null" + ], + "example": "1001001234" + }, + "account_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "checking", + "saving" + ], + "example": "checking" + }, + "account_class": { + "type": [ + "string", + "null" + ], + "enum": [ + "individual", + "business" + ], + "example": "individual" + }, + "address_line_1": { + "type": [ + "string", + "null" + ], + "example": "Address line 1" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "Address line 2" + }, + "city": { + "type": [ + "string", + "null" + ], + "example": "City" + }, + "state_province_region": { + "type": [ + "string", + "null" + ], + "example": "State/Province/Region" + }, + "country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "US" + }, + "postal_code": { + "type": [ + "string", + "null" + ], + "example": "Postal code" + }, + "checkbook_account_id": { + "type": [ + "string", + "null" + ], + "example": "dc809ff8f4d3417d83e5697e76f0b88a" + }, + "checkbook_user_key": { + "type": [ + "string", + "null" + ], + "example": "d84fd0dc-3882-4de9-97f8-656730214619" + }, + "onemoney_external_account_id": { + "type": [ + "string", + "null" + ], + "example": "ex_000000000000" + }, + "pix_safe_bank_code": { + "type": [ + "string", + "null" + ], + "pattern": "^\\d{4,8}$", + "example": "00416968" + }, + "pix_safe_branch_code": { + "type": [ + "string", + "null" + ], + "pattern": "^\\d{4}(-\\d)?$", + "example": "0001" + }, + "pix_safe_cpf_cnpj": { + "type": [ + "string", + "null" + ], + "example": "12345678901" + }, + "ted_bank_code": { + "type": [ + "string", + "null" + ], + "pattern": "^\\d{3,5}$", + "example": "033" + }, + "ted_branch_code": { + "type": [ + "string", + "null" + ], + "pattern": "^\\d{4}(-\\d)?$", + "example": "0001" + }, + "ted_cpf_cnpj": { + "type": [ + "string", + "null" + ], + "example": "12345678901" + }, + "spei_protocol": { + "type": [ + "string", + "null" + ], + "enum": [ + "clabe", + "debitcard", + "phonenum" + ], + "description": "For debitcard and phonenum the spei_institution_code is required", + "example": "clabe" + }, + "spei_institution_code": { + "type": [ + "string", + "null" + ], + "minLength": 5, + "maxLength": 5, + "example": "40002" + }, + "spei_clabe": { + "type": [ + "string", + "null" + ], + "example": "5482347403740546" + }, + "transfers_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "CVU", + "CBU", + "ALIAS" + ], + "example": "CVU" + }, + "transfers_account": { + "type": [ + "string", + "null" + ], + "example": "BM123123123123" + }, + "ach_cop_beneficiary_first_name": { + "type": [ + "string", + "null" + ], + "example": "Fernando" + }, + "ach_cop_beneficiary_last_name": { + "type": [ + "string", + "null" + ], + "example": "Guzman Alarcón" + }, + "ach_cop_document_id": { + "type": [ + "string", + "null" + ], + "example": "1661105408" + }, + "ach_cop_document_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "CC", + "CE", + "NIT", + "PASS", + "PEP" + ], + "description": "CC - Cédula de Ciudadanía; CE - Cédula de Extranjería; NIT - Número de Identificación Tributaria; PASS - Passport; PEP - Permiso Especial de Permanencia", + "example": "CC" + }, + "ach_cop_email": { + "type": [ + "string", + "null" + ], + "example": "fernando.guzman@gmail.com" + }, + "ach_cop_bank_code": { + "type": [ + "string", + "null" + ], + "example": "051" + }, + "ach_cop_bank_account": { + "type": [ + "string", + "null" + ], + "example": "12345678" + }, + "swift_code_bic": { + "type": [ + "string", + "null" + ], + "example": "123456789" + }, + "swift_account_holder_name": { + "type": [ + "string", + "null" + ], + "example": "John Doe" + }, + "swift_account_number_iban": { + "type": [ + "string", + "null" + ], + "example": "123456789" + }, + "swift_beneficiary_address_line_1": { + "type": [ + "string", + "null" + ], + "example": "123 MAIN STREET SUITE 100" + }, + "swift_beneficiary_address_line_2": { + "type": [ + "string", + "null" + ], + "example": "BUILDING A FLOOR 5" + }, + "swift_beneficiary_country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "MX" + }, + "swift_beneficiary_city": { + "type": [ + "string", + "null" + ], + "example": "MEXICO CITY" + }, + "swift_beneficiary_state_province_region": { + "type": [ + "string", + "null" + ], + "example": "MX" + }, + "swift_beneficiary_postal_code": { + "type": [ + "string", + "null" + ], + "example": "11530" + }, + "swift_bank_name": { + "type": [ + "string", + "null" + ], + "example": "Banco Regional SA" + }, + "swift_bank_address_line_1": { + "type": [ + "string", + "null" + ], + "example": "123 Main Street, Suite 100, Downtown District, City Center CP 12345" + }, + "swift_bank_address_line_2": { + "type": [ + "string", + "null" + ], + "example": "456 Oak Avenue, Building 7, Financial District, Business Center CP 54321" + }, + "swift_bank_country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "MX" + }, + "swift_bank_city": { + "type": [ + "string", + "null" + ], + "example": "City" + }, + "swift_bank_state_province_region": { + "type": [ + "string", + "null" + ], + "example": "District" + }, + "swift_bank_postal_code": { + "type": [ + "string", + "null" + ], + "example": "11530" + }, + "swift_ifsc_branch_code": { + "type": [ + "string", + "null" + ], + "pattern": "^[A-Z]{4}0[A-Z0-9]{6}$", + "example": "BARB0AHIMCI" + }, + "swift_intermediary_bank_swift_code_bic": { + "anyOf": [ + { + "type": "string", + "minLength": 8, + "maxLength": 8 + }, + { + "type": "string", + "minLength": 11, + "maxLength": 11 + }, + { + "type": "null" + } + ], + "example": "AEIBARB1" + }, + "swift_intermediary_bank_account_number_iban": { + "type": [ + "string", + "null" + ], + "maxLength": 34, + "example": "123456789" + }, + "swift_intermediary_bank_name": { + "type": [ + "string", + "null" + ], + "example": "Banco Regional SA" + }, + "swift_intermediary_bank_country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "US" + }, + "swift_intermediary_bank_routing_number": { + "anyOf": [ + { + "type": "string", + "enum": [ + "" + ] + }, + { + "type": "string", + "pattern": "^\\d{9}$" + }, + { + "type": "null" + } + ], + "description": "US ABA routing number of the correspondent bank, from the beneficiary bank USD wire instructions. Used by providers that require an explicit US correspondent for the SWIFT route.", + "example": "021000089" + }, + "sepa_iban": { + "type": [ + "string", + "null" + ], + "example": "DE89370400440532013000" + }, + "sepa_beneficiary_bic": { + "type": [ + "string", + "null" + ], + "description": "BIC/SWIFT code of the beneficiary bank", + "example": "TRWIBEB1XXX" + }, + "sepa_beneficiary_legal_name": { + "type": [ + "string", + "null" + ], + "maxLength": 128, + "example": "Hans Müller" + }, + "sepa_beneficiary_address_line_1": { + "type": [ + "string", + "null" + ], + "example": "Friedrichstraße 12" + }, + "sepa_beneficiary_address_line_2": { + "type": [ + "string", + "null" + ], + "example": "Apt 4B" + }, + "sepa_beneficiary_city": { + "type": [ + "string", + "null" + ], + "example": "Berlin" + }, + "sepa_beneficiary_state_province_region": { + "type": [ + "string", + "null" + ], + "example": "Berlin" + }, + "sepa_beneficiary_postal_code": { + "type": [ + "string", + "null" + ], + "example": "10117" + }, + "sepa_beneficiary_country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "DE" + }, + "faster_payments_sort_code": { + "type": [ + "string", + "null" + ], + "description": "UK bank sort code, 6 digits. Dashes and spaces are stripped.", + "example": "040004" + }, + "faster_payments_account_number": { + "type": [ + "string", + "null" + ], + "description": "UK bank account number, 8 digits.", + "example": "12345678" + }, + "faster_payments_beneficiary_legal_name": { + "type": [ + "string", + "null" + ], + "maxLength": 128, + "example": "Oliver Smith" + }, + "faster_payments_beneficiary_address_line_1": { + "type": [ + "string", + "null" + ], + "example": "221B Baker Street" + }, + "faster_payments_beneficiary_address_line_2": { + "type": [ + "string", + "null" + ], + "example": "Flat 2" + }, + "faster_payments_beneficiary_city": { + "type": [ + "string", + "null" + ], + "example": "London" + }, + "faster_payments_beneficiary_state_province_region": { + "type": [ + "string", + "null" + ], + "example": "Greater London" + }, + "faster_payments_beneficiary_postal_code": { + "type": [ + "string", + "null" + ], + "example": "NW1 6XE" + }, + "faster_payments_beneficiary_country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "GB" + }, + "business_industry": { + "type": [ + "string", + "null" + ], + "enum": [ + "111998", + "112120", + "113310", + "115114", + "111120", + "111219", + "111336", + "111421", + "112111", + "112210", + "112310", + "112410", + "112519", + "112990", + "113110", + "113210", + "114119", + "114210", + "115113", + "115210", + "115310", + "541211", + "541213", + "541219", + "541810", + "541430", + "541715", + "541930", + "561422", + "561311", + "561612", + "561740", + "561730", + "532490", + "533110", + "541490", + "541690", + "541720", + "561110", + "561210", + "561611", + "561990", + "722310", + "236115", + "236220", + "237310", + "238210", + "236118", + "236210", + "237130", + "237210", + "237990", + "238191", + "238391", + "238991", + "541310", + "811111", + "812111", + "812112", + "532111", + "624410", + "541922", + "811210", + "812199", + "532289", + "532310", + "561790", + "811198", + "811310", + "811411", + "812210", + "812320", + "812990", + "814110", + "611110", + "611310", + "611410", + "611710", + "611210", + "611420", + "611519", + "611699", + "211120", + "212114", + "221310", + "562111", + "562920", + "213112", + "211130", + "212290", + "212390", + "213113", + "221122", + "221210", + "221320", + "324110", + "562211", + "562998", + "522110", + "522210", + "522320", + "523150", + "523940", + "523999", + "524113", + "521110", + "522130", + "522298", + "522390", + "523210", + "524128", + "524298", + "525190", + "525910", + "813110", + "813211", + "813219", + "624190", + "624230", + "624310", + "813319", + "813410", + "813930", + "921140", + "922190", + "923130", + "924110", + "925120", + "926110", + "927110", + "928110", + "551112", + "551114", + "721110", + "722511", + "722513", + "561510", + "713110", + "713210", + "712110", + "711110", + "711211", + "487110", + "487210", + "487990", + "561599", + "711190", + "711219", + "711310", + "712120", + "713290", + "713990", + "721199", + "721211", + "721310", + "722410", + "621111", + "621210", + "622110", + "623110", + "621511", + "623220", + "541940", + "621399", + "621910", + "621498", + "621610", + "621999", + "622210", + "622310", + "623210", + "623311", + "623990", + "541110", + "541199", + "311421", + "337121", + "322220", + "339920", + "334210", + "339930", + "312130", + "334111", + "334118", + "325412", + "339112", + "336110", + "336390", + "315990", + "313110", + "339910", + "311119", + "311212", + "311314", + "311422", + "311511", + "311612", + "311710", + "311811", + "311999", + "312111", + "312230", + "313240", + "313310", + "314120", + "314999", + "315120", + "315250", + "316110", + "316210", + "316990", + "321113", + "321211", + "321918", + "322120", + "322299", + "323120", + "325180", + "325220", + "325320", + "325510", + "325611", + "325998", + "326111", + "326220", + "327120", + "327212", + "327310", + "327410", + "327999", + "331110", + "331210", + "331313", + "331410", + "331511", + "332111", + "332215", + "332311", + "332410", + "332510", + "332613", + "332710", + "332812", + "332999", + "333111", + "333248", + "333310", + "333413", + "333517", + "333611", + "333618", + "334310", + "334413", + "334511", + "334610", + "335131", + "335220", + "335311", + "335999", + "336211", + "336412", + "336510", + "336611", + "336999", + "337122", + "337214", + "337920", + "339999", + "516120", + "513130", + "512250", + "519130", + "519290", + "711410", + "711510", + "512199", + "512290", + "515210", + "531110", + "531120", + "531130", + "531190", + "531210", + "531311", + "531312", + "531320", + "531390", + "454110", + "445110", + "455110", + "457110", + "449210", + "444110", + "459210", + "459120", + "445320", + "458110", + "458210", + "458310", + "455219", + "424210", + "456110", + "446120", + "456120", + "441110", + "441227", + "441330", + "444180", + "444240", + "445132", + "445298", + "449110", + "449129", + "454390", + "458320", + "459310", + "459410", + "459510", + "459999", + "541511", + "541512", + "541519", + "518210", + "511210", + "513210", + "517111", + "517112", + "517410", + "517810", + "481111", + "483111", + "485210", + "488510", + "484121", + "493110", + "423430", + "423690", + "423110", + "423830", + "423840", + "423510", + "424690", + "424990", + "424410", + "424480", + "423940", + "423120", + "423220", + "423310", + "423490", + "423520", + "423620", + "423710", + "423990", + "424110", + "424310", + "424490", + "424590", + "424720", + "424820", + "425120", + "481211", + "482111", + "483112", + "483212", + "484110", + "484220", + "485119", + "485310", + "485410", + "485510", + "485999", + "486110", + "486210", + "486990", + "488190", + "488210", + "488390", + "488490", + "488999", + "492110", + "492210", + "493190", + "541611", + "541618", + "541330", + "541990", + "541214", + "561499" + ], + "example": "541511" + }, + "phone_number": { + "type": [ + "string", + "null" + ], + "example": "+13055555555" + }, + "tax_id": { + "type": [ + "string", + "null" + ], + "maxLength": 32, + "example": "536804398" + }, + "date_of_birth": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "example": "1998-01-01T00:00:00Z" + } + }, + "required": [ + "type", + "name" + ], + "description": "Destination bank details for an invoice payable, in the same shape as POST /customers/{customer_id}/bank-accounts. Accepted types: ach, wire. The account is created owned by the payable and is not reusable." + }, + "CreatePayableIn": { + "type": "object", + "properties": { + "customer_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "from": { + "$ref": "#/components/schemas/PayableParty" + }, + "to": { + "allOf": [ + { + "$ref": "#/components/schemas/PayableParty" + }, + { + "description": "The beneficiary being paid." + } + ] + }, + "currency": { + "type": "string", + "enum": [ + "BRL", + "USD", + "MXN", + "COP", + "ARS", + "EUR", + "GBP" + ], + "description": "ISO 4217 currency code of the payable.", + "example": "BRL" + }, + "line_items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PayableLineItem" + }, + "maxItems": 100, + "default": [], + "description": "Invoice line items. The payable total is the line item sum plus taxes minus discount." + }, + "note": { + "type": [ + "string", + "null" + ], + "maxLength": 512, + "example": "August retainer" + }, + "discount": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "default": 0, + "description": "Discount in cents of the payable currency.", + "example": 0 + }, + "taxes": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "default": 0, + "description": "Taxes in cents of the payable currency.", + "example": 0 + }, + "boleto_barcode": { + "type": [ + "string", + "null" + ], + "minLength": 1, + "maxLength": 512, + "description": "Boleto or arrecadação code (linha digitável or barcode).", + "example": "34191.79001 01043.510047 91020.150008 1 84660000002000" + }, + "pix_qrcode": { + "type": [ + "string", + "null" + ], + "minLength": 1, + "maxLength": 512, + "description": "PIX copia e cola (EMV) payload." + }, + "document_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "The boleto or invoice document, as a file URL returned by POST /upload with bucket `documents`. Not accepted for PIX payables. Read it through POST /presign.", + "example": "https://files.blindpay.com/1712345678901-boleto.pdf" + }, + "due_date": { + "type": [ + "string", + "null" + ], + "example": "2026-08-10" + }, + "scheduled_at": { + "type": [ + "string", + "null" + ], + "description": "When to pay this payable automatically. Not executed yet: stored for the upcoming scheduling feature.", + "example": "2026-08-10T12:00:00.000Z" + }, + "bank_account": { + "$ref": "#/components/schemas/CreateBankAccountIn" + } + }, + "required": [ + "customer_id", + "currency" + ] + }, + "TransferOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bl_000000000000" + }, + "status": { + "type": "string", + "enum": [ + "processing", + "failed", + "refunded", + "completed" + ], + "description": "Transfer general status", + "example": "processing" + }, + "transfer_quote_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "pq_000000000000" + }, + "instance_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "tracking_transaction_monitoring": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Transaction monitoring step", + "example": "processing" + }, + "blockchain_screening": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 100, + "description": "Blindpay screening step", + "example": 1 + }, + "risk_score": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 100, + "description": "Risk score", + "example": 1 + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Transfer transaction completed date", + "example": "2011-10-05T14:48:00.000Z" + } + }, + "required": [ + "step" + ] + }, + "tracking_paymaster": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "gas_fee": { + "type": [ + "string", + "null" + ], + "description": "Gas fee related to transaction", + "example": "100" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "error_message": { + "type": [ + "string", + "null" + ], + "example": "Gas fee is too low" + } + }, + "required": [ + "step" + ] + }, + "tracking_bridge_swap": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "gas_fee": { + "type": [ + "string", + "null" + ], + "description": "Gas fee related to transaction", + "example": "100" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "error_message": { + "type": [ + "string", + "null" + ], + "example": "Gas fee is too low" + } + }, + "required": [ + "step" + ] + }, + "tracking_complete": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "gas_fee": { + "type": [ + "string", + "null" + ], + "description": "Gas fee related to transaction", + "example": "100" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "error_message": { + "type": [ + "string", + "null" + ], + "example": "Gas fee is too low" + } + }, + "required": [ + "step" + ] + }, + "tracking_partner_fee": { + "type": [ + "object", + "null" + ], + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "gas_fee": { + "type": [ + "string", + "null" + ], + "description": "Gas fee related to transaction", + "example": "100" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "error_message": { + "type": [ + "string", + "null" + ], + "example": "Gas fee is too low" + } + }, + "required": [ + "step" + ] + }, + "created_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + }, + "updated_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + }, + "image_url": { + "type": [ + "string", + "null" + ], + "format": "uri", + "example": "https://example.com/image.png" + }, + "first_name": { + "type": [ + "string", + "null" + ], + "example": "John" + }, + "last_name": { + "type": [ + "string", + "null" + ], + "example": "Doe" + }, + "legal_name": { + "type": [ + "string", + "null" + ], + "example": "Company Name Inc." + }, + "wallet_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bl_000000000000" + }, + "sender_token": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB", + "EURC", + "EURB" + ], + "description": "Token debited from the sending wallet. When it differs from customer_token the transfer converts between USDC and EURC (USDB and EURB on development instances) on Base.", + "example": "USDC" + }, + "sender_amount": { + "type": "number", + "description": "52.40 BRL needs to be sent in a pix transfer", + "example": 5240 + }, + "receiver_amount": { + "type": "number", + "description": "10.10 USDC", + "example": 1010 + }, + "customer_network": { + "type": "string", + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "polygon" + }, + "customer_token": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB", + "EURC", + "EURB" + ], + "description": "Token delivered to the customer wallet.", + "example": "USDC" + }, + "customer_wallet_address": { + "type": "string", + "minLength": 32, + "maxLength": 64, + "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + }, + "partner_fee_amount": { + "type": [ + "number", + "null" + ], + "default": 0, + "description": "1.5 USDC", + "example": 150 + }, + "partner_percentage_fee": { + "type": "integer", + "minimum": 0, + "maximum": 9900, + "default": 0, + "description": "Partner percentage fee charged on this transfer, in hundredths of a percent. 150 represents 1.50%, 1000 represents 10.00%", + "example": 150 + }, + "partner_flat_fee": { + "type": "integer", + "minimum": 0, + "maximum": 100000, + "default": 0, + "description": "Partner flat fee charged on this transfer, in cents of the sender token. 50 represents 0.50, 1000 represents 10.00", + "example": 50 + }, + "external_id": { + "type": [ + "string", + "null" + ], + "maxLength": 255, + "example": "your-database-id" + }, + "customer_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "address": { + "type": [ + "string", + "null" + ], + "maxLength": 64, + "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + }, + "network": { + "type": "string", + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "polygon" + } + }, + "required": [ + "id", + "status", + "transfer_quote_id", + "instance_id", + "tracking_transaction_monitoring", + "tracking_paymaster", + "tracking_bridge_swap", + "tracking_complete", + "wallet_id", + "sender_token", + "sender_amount", + "receiver_amount", + "customer_network", + "customer_token", + "customer_wallet_address", + "customer_id", + "network" + ] + }, + "CreateTransferOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "tr_000000000000" + }, + "status": { + "type": "string", + "enum": [ + "processing", + "failed", + "refunded", + "completed" + ], + "description": "Transfer general status", + "example": "processing" + }, + "tracking_bridge_swap": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "gas_fee": { + "type": [ + "string", + "null" + ], + "description": "Gas fee related to transaction", + "example": "100" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "error_message": { + "type": [ + "string", + "null" + ], + "example": "Gas fee is too low" + } + }, + "required": [ + "step" + ] + }, + "tracking_complete": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "gas_fee": { + "type": [ + "string", + "null" + ], + "description": "Gas fee related to transaction", + "example": "100" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "error_message": { + "type": [ + "string", + "null" + ], + "example": "Gas fee is too low" + } + }, + "required": [ + "step" + ] + }, + "tracking_paymaster": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "gas_fee": { + "type": [ + "string", + "null" + ], + "description": "Gas fee related to transaction", + "example": "100" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "error_message": { + "type": [ + "string", + "null" + ], + "example": "Gas fee is too low" + } + }, + "required": [ + "step" + ] + }, + "tracking_transaction_monitoring": { + "type": "object", + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Transaction monitoring step", + "example": "processing" + }, + "blockchain_screening": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 100, + "description": "Blindpay screening step", + "example": 1 + }, + "risk_score": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 100, + "description": "Risk score", + "example": 1 + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Transfer transaction completed date", + "example": "2011-10-05T14:48:00.000Z" + } + }, + "required": [ + "step" + ] + }, + "tracking_partner_fee": { + "type": [ + "object", + "null" + ], + "properties": { + "step": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "pending_review", + "pending_refund_review", + "completed" + ], + "description": "Complete step", + "example": "on_hold" + }, + "transaction_hash": { + "type": [ + "string", + "null" + ], + "description": "Complete transaction hash", + "example": "0x123...890" + }, + "gas_fee": { + "type": [ + "string", + "null" + ], + "description": "Gas fee related to transaction", + "example": "100" + }, + "completed_at": { + "type": [ + "string", + "null" + ], + "description": "Complete completed date", + "example": "2011-10-05T14:48:00.000Z" + }, + "error_message": { + "type": [ + "string", + "null" + ], + "example": "Gas fee is too low" + } + }, + "required": [ + "step" + ] + } + }, + "required": [ + "id", + "status", + "tracking_bridge_swap", + "tracking_complete", + "tracking_paymaster", + "tracking_transaction_monitoring" + ] + }, + "CreateTransferIn": { + "type": "object", + "properties": { + "transfer_quote_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "pq_000000000000" + } + }, + "required": [ + "transfer_quote_id" + ] + }, + "CreateTransferQuoteOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "qu_000000000000" + }, + "expires_at": { + "type": [ + "number", + "null" + ], + "description": "Epoch timestamp in milliseconds after which the quote can no longer be executed, 5 minutes after creation.", + "example": 1712958191000 + }, + "commercial_quotation": { + "type": [ + "number", + "null" + ], + "description": "Units of customer_token per sender_token, times 100. 100 for same-token transfers, 86.5 means 1 USDC = 0.865 EURC", + "example": 100 + }, + "blindpay_quotation": { + "type": [ + "number", + "null" + ], + "description": "Rate applied to the transfer, in the same unit as commercial_quotation", + "example": 100 + }, + "receiver_amount": { + "type": "number", + "description": "10.10 USDC", + "example": 1010 + }, + "sender_amount": { + "type": "number", + "description": "52.40 BRL needs to be sent in a pix transfer", + "example": 5240 + }, + "partner_fee_amount": { + "type": [ + "number", + "null" + ], + "default": 0, + "description": "1.5 USDC", + "example": 150 + }, + "partner_percentage_fee": { + "type": "integer", + "minimum": 0, + "maximum": 9900, + "default": 0, + "description": "Partner percentage fee charged on this transfer, in hundredths of a percent. 150 represents 1.50%, 1000 represents 10.00%", + "example": 150 + }, + "partner_flat_fee": { + "type": "integer", + "minimum": 0, + "maximum": 100000, + "default": 0, + "description": "Partner flat fee charged on this transfer, in cents of the sender token. 50 represents 0.50, 1000 represents 10.00", + "example": 50 + }, + "flat_fee": { + "type": "number", + "description": "0.5 USDC", + "example": 50 + } + }, + "required": [ + "id", + "expires_at", + "commercial_quotation", + "blindpay_quotation", + "receiver_amount", + "sender_amount", + "flat_fee" + ] + }, + "CreateTransferQuoteIn": { + "type": "object", + "properties": { + "wallet_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bl_000000000000" + }, + "amount_reference": { + "type": "string", + "enum": [ + "sender", + "receiver" + ], + "description": "", + "example": "sender" + }, + "cover_fees": { + "type": [ + "boolean", + "null" + ], + "description": "If true, the sender will cover the fees. If false, the customer will cover the fees.", + "example": true + }, + "request_amount": { + "type": "integer", + "minimum": 1, + "description": "100 represents 1, 2050 represents 20.50", + "example": 1000 + }, + "sender_token": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB", + "EURC", + "EURB" + ], + "description": "Token debited from the sending wallet. When it differs from customer_token the transfer converts between USDC and EURC (USDB and EURB on development instances) on Base.", + "example": "USDC" + }, + "customer_wallet_address": { + "type": "string", + "minLength": 32, + "maxLength": 64, + "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + }, + "customer_token": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB", + "EURC", + "EURB" + ], + "description": "Token delivered to the customer wallet.", + "example": "USDC" + }, + "customer_network": { + "type": "string", + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "polygon" + }, + "partner_fee_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "example": "pf_000000000000" + }, + "partner_percentage_fee": { + "type": "integer", + "minimum": 0, + "maximum": 9900, + "default": 0, + "description": "Partner percentage fee charged on this transfer, in hundredths of a percent. 150 represents 1.50%, 1000 represents 10.00%", + "example": 150 + }, + "partner_flat_fee": { + "type": "integer", + "minimum": 0, + "maximum": 100000, + "default": 0, + "description": "Partner flat fee charged on this transfer, in cents of the sender token. 50 represents 0.50, 1000 represents 10.00", + "example": 50 + } + }, + "required": [ + "wallet_id", + "amount_reference", + "request_amount", + "sender_token", + "customer_wallet_address", + "customer_token", + "customer_network" + ] + }, + "CustomerLimitIncreaseOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "rl_000000000000" + } + }, + "required": [ + "id" + ] + }, + "CustomerLimitIncreaseIn": { + "type": "object", + "properties": { + "per_transaction": { + "type": [ + "integer", + "null" + ], + "maximum": 100000000000, + "example": 100000 + }, + "daily": { + "type": [ + "integer", + "null" + ], + "maximum": 100000000000, + "example": 200000 + }, + "monthly": { + "type": [ + "integer", + "null" + ], + "maximum": 100000000000, + "example": 1000000 + }, + "supporting_document_type": { + "type": "string", + "enum": [ + "individual_bank_statement", + "individual_tax_return", + "individual_proof_of_income", + "individual_pay_stub", + "individual_employment_letter", + "individual_investment_statement", + "individual_crypto_exchange_statement", + "individual_blockchain_wallet_statement", + "business_bank_statement", + "business_financial_statements", + "business_tax_return", + "business_contract", + "business_accounts_receivable", + "business_merchant_processor_statement", + "business_shareholder_loan" + ], + "description": "Single-document shorthand. Prefer supporting_documents.", + "example": "individual_bank_statement" + }, + "supporting_document_file": { + "type": "string", + "format": "uri", + "description": "Single-document shorthand. Prefer supporting_documents.", + "example": "https://example.com/document.pdf" + }, + "supporting_documents": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LimitIncreaseSupportingDocument" + }, + "minItems": 1, + "maxItems": 5, + "description": "Up to 5 supporting documents. Required unless supporting_document_type and supporting_document_file are sent." + } + }, + "required": [ + "per_transaction", + "daily", + "monthly" + ] + }, + "GetCustomerLimitIncreaseOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "rl_000000000000" + }, + "status": { + "type": "string", + "enum": [ + "in_review", + "approved", + "rejected" + ], + "example": "in_review" + }, + "per_transaction": { + "type": [ + "integer", + "null" + ], + "maximum": 100000000000, + "example": 100000 + }, + "daily": { + "type": [ + "integer", + "null" + ], + "maximum": 100000000000, + "example": 200000 + }, + "monthly": { + "type": [ + "integer", + "null" + ], + "maximum": 100000000000, + "example": 1000000 + }, + "approved_per_transaction": { + "type": [ + "integer", + "null" + ], + "maximum": 100000000000, + "example": 70000 + }, + "approved_daily": { + "type": [ + "integer", + "null" + ], + "maximum": 100000000000, + "example": 140000 + }, + "approved_monthly": { + "type": [ + "integer", + "null" + ], + "maximum": 100000000000, + "example": 700000 + }, + "supporting_document_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "individual_bank_statement", + "individual_tax_return", + "individual_proof_of_income", + "individual_pay_stub", + "individual_employment_letter", + "individual_investment_statement", + "individual_crypto_exchange_statement", + "individual_blockchain_wallet_statement", + "business_bank_statement", + "business_financial_statements", + "business_tax_return", + "business_contract", + "business_accounts_receivable", + "business_merchant_processor_statement", + "business_shareholder_loan" + ], + "example": "individual_bank_statement" + }, + "supporting_document_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "example": "https://example.com/document.pdf" + }, + "supporting_documents": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/components/schemas/LimitIncreaseSupportingDocument" + }, + "minItems": 1, + "maxItems": 5, + "description": "Every supporting document attached to the request, up to 5. The first one is mirrored in supporting_document_type and supporting_document_file." + }, + "customer_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "created_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + }, + "updated_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + } + }, + "required": [ + "id", + "status", + "customer_id" + ] + }, + "OfframpWallet": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "ow_000000000000" + }, + "external_id": { + "type": [ + "string", + "null" + ], + "example": "your_external_id" + }, + "instance_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "customer_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "bank_account_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "ba_000000000000" + }, + "circle_wallet_id": { + "type": [ + "string", + "null" + ], + "example": "01234567-abcd-efgh-ijkl-012345678901" + }, + "network": { + "type": "string", + "enum": [ + "tron", + "solana", + "solana_devnet", + "arbitrum", + "base", + "ethereum", + "polygon", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "polygon_amoy", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "tron" + }, + "address": { + "type": "string", + "example": "TALJN9zTTEL9TVBb4WuTt6wLvPqJZr3hvb" + }, + "created_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + }, + "updated_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + } + }, + "required": [ + "id", + "instance_id", + "customer_id", + "bank_account_id", + "network", + "address" + ] + }, + "WalletOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bl_000000000000" + }, + "name": { + "type": "string", + "maxLength": 255, + "example": "Blindpay Wallet" + }, + "external_id": { + "type": [ + "string", + "null" + ], + "maxLength": 255, + "example": "your-database-id" + }, + "address": { + "type": [ + "string", + "null" + ], + "maxLength": 64, + "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + }, + "network": { + "type": "string", + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "polygon" + }, + "yield_status": { + "$ref": "#/components/schemas/YieldStatus" + }, + "created_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + } + }, + "required": [ + "id", + "name", + "network" + ] + }, + "CreateWalletIn": { + "type": "object", + "properties": { + "network": { + "type": "string", + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "polygon" + }, + "external_id": { + "type": [ + "string", + "null" + ], + "maxLength": 255, + "example": "your-database-id" + }, + "name": { + "type": "string", + "maxLength": 255, + "example": "Blindpay Wallet" + } + }, + "required": [ + "network", + "name" + ] + }, + "WalletTokenOut": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "id": { + "type": "string" + }, + "symbol": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB", + "EURC", + "EURB" + ] + }, + "amount": { + "type": "number" + }, + "earning_amount": { + "type": "number", + "description": "Balance earning in the yield vault, net of accrued fees. 0 when yield is off.", + "example": 0 + }, + "total_amount": { + "type": "number", + "description": "amount + earning_amount", + "example": 0 + } + }, + "required": [ + "address", + "id", + "symbol", + "amount", + "earning_amount", + "total_amount" + ] + }, + "WalletBalanceOut": { + "type": "object", + "properties": { + "USDC": { + "$ref": "#/components/schemas/WalletTokenOut" + }, + "USDT": { + "$ref": "#/components/schemas/WalletTokenOut" + }, + "USDB": { + "$ref": "#/components/schemas/WalletTokenOut" + }, + "EURC": { + "allOf": [ + { + "$ref": "#/components/schemas/WalletTokenOut" + }, + { + "description": "Present on networks that hold EURC (Base)" + } + ] + }, + "EURB": { + "allOf": [ + { + "$ref": "#/components/schemas/WalletTokenOut" + }, + { + "description": "Present on networks that hold EURB, the development test token (Base Sepolia)" + } + ] + } + }, + "required": [ + "USDC", + "USDT", + "USDB" + ] + }, + "WalletDepositOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "wd_000000000000" + }, + "wallet_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bl_000000000000" + }, + "network": { + "type": "string", + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "polygon" + }, + "token": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB", + "EURC", + "EURB" + ], + "example": "USDC" + }, + "amount": { + "type": "integer", + "description": "In cents", + "example": 150000 + }, + "token_amount": { + "type": [ + "string", + "null" + ], + "description": "Exact amount in token units, as a decimal string", + "example": "1500.000123" + }, + "status": { + "type": "string", + "enum": [ + "processing", + "completed", + "on_hold", + "refunded" + ], + "description": "processing while the deposit is being checked, on_hold while the funds are held, refunded once returned to the sender", + "example": "completed" + }, + "transaction_hash": { + "type": "string", + "example": "0x8f3e1b..." + }, + "sender_address": { + "type": [ + "string", + "null" + ], + "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + }, + "created_at": { + "type": "string", + "format": "date-time", + "example": "2026-10-15T10:02:00Z" + } + }, + "required": [ + "id", + "wallet_id", + "network", + "token", + "amount", + "token_amount", + "status", + "transaction_hash", + "sender_address", + "created_at" + ] + }, + "WalletDepositsOut": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WalletDepositOut" + } + }, + "pagination": { + "$ref": "#/components/schemas/PaginationMetadata" + } + }, + "required": [ + "data", + "pagination" + ] + }, + "BlockchainWalletMessageOut": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + }, + "required": [ + "message" + ] + }, + "BlockchainWalletOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bw_000000000000" + }, + "name": { + "type": [ + "string", + "null" + ], + "example": "Wallet Display Name" + }, + "network": { + "type": [ + "string", + "null" + ], + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "polygon" + }, + "address": { + "type": [ + "string", + "null" + ], + "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + }, + "signature_tx_hash": { + "type": [ + "string", + "null" + ], + "example": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359" + }, + "is_account_abstraction": { + "type": [ + "boolean", + "null" + ], + "example": false + }, + "is_self_custody": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the customer holds the private keys of this wallet. Required for Brazilian customers (BCB Resolution 588). null means it was never answered; once set it cannot be changed.", + "example": true + }, + "customer_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + } + }, + "required": [ + "id", + "name", + "network", + "customer_id" + ] + }, + "CreateBlockchainWalletIn": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "Wallet Display Name" + }, + "network": { + "type": "string", + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "polygon" + }, + "signature_tx_hash": { + "type": [ + "string", + "null" + ], + "example": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359" + }, + "address": { + "type": [ + "string", + "null" + ], + "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + }, + "is_account_abstraction": { + "type": [ + "boolean", + "null" + ], + "example": false + }, + "is_self_custody": { + "type": "boolean", + "description": "Whether the customer holds the private keys of this wallet. Required when the customer country is BR.", + "example": true + } + }, + "required": [ + "name", + "network" + ] + }, + "UpdateBlockchainWalletIn": { + "type": "object", + "properties": { + "is_self_custody": { + "type": "boolean", + "description": "Whether the customer holds the private keys of this wallet. Can only be set while it is still null.", + "example": true + } + }, + "required": [ + "is_self_custody" + ] + }, + "PlaidLinkOut": { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "BlindPay hosted page that runs Plaid Link for this customer. Embed it in an iframe or open it in a new tab. The token in the URL is signed, single use, and expires in at most 4 hours. Sandbox instances get a Plaid sandbox session, production instances a Plaid production session.", + "example": "https://app.blindpay.com/e/plaid?token=eyJhbGciOiJIUzI1NiJ9..." + } + }, + "required": [ + "url" + ] + }, + "CreatePlaidLinkIn": { + "type": "object", + "properties": { + "redirect_url": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "Where to send the customer once the bank account is connected. BlindPay appends bank_account_ids (comma separated) as a query parameter. Leave empty to show a confirmation screen instead.", + "example": "https://example.com/bank-connected" + } + } + }, + "BankAccountOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "ba_000000000000" + }, + "type": { + "type": "string", + "enum": [ + "wire", + "ach", + "pix", + "pix_safe", + "ted", + "spei_bitso", + "transfers_bitso", + "ach_cop_bitso", + "international_swift", + "rtp", + "sepa", + "faster_payments" + ], + "example": "wire" + }, + "name": { + "type": "string", + "example": "Bank Account Name" + }, + "pix_key": { + "type": [ + "string", + "null" + ], + "example": "14947677768" + }, + "beneficiary_name": { + "type": [ + "string", + "null" + ], + "maxLength": 128, + "example": "Individual full name or business name" + }, + "routing_number": { + "type": [ + "string", + "null" + ], + "example": "012345678" + }, + "account_number": { + "type": [ + "string", + "null" + ], + "example": "1001001234" + }, + "account_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "checking", + "saving" + ], + "example": "checking" + }, + "account_class": { + "type": [ + "string", + "null" + ], + "enum": [ + "individual", + "business" + ], + "example": "individual" + }, + "address_line_1": { + "type": [ + "string", + "null" + ], + "example": "Address line 1" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "Address line 2" + }, + "city": { + "type": [ + "string", + "null" + ], + "example": "City" + }, + "state_province_region": { + "type": [ + "string", + "null" + ], + "example": "State/Province/Region" + }, + "country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "US" + }, + "postal_code": { + "type": [ + "string", + "null" + ], + "example": "Postal code" + }, + "spei_protocol": { + "type": [ + "string", + "null" + ], + "enum": [ + "clabe", + "debitcard", + "phonenum" + ], + "description": "For debitcard and phonenum the spei_institution_code is required", + "example": "clabe" + }, + "spei_institution_code": { + "type": [ + "string", + "null" + ], + "minLength": 5, + "maxLength": 5, + "example": "40002" + }, + "spei_clabe": { + "type": [ + "string", + "null" + ], + "example": "5482347403740546" + }, + "transfers_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "CVU", + "CBU", + "ALIAS" + ], + "example": "CVU" + }, + "transfers_account": { + "type": [ + "string", + "null" + ], + "example": "BM123123123123" + }, + "ach_cop_beneficiary_first_name": { + "type": [ + "string", + "null" + ], + "example": "Fernando" + }, + "ach_cop_beneficiary_last_name": { + "type": [ + "string", + "null" + ], + "example": "Guzman Alarcón" + }, + "ach_cop_document_id": { + "type": [ + "string", + "null" + ], + "example": "1661105408" + }, + "ach_cop_document_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "CC", + "CE", + "NIT", + "PASS", + "PEP" + ], + "description": "CC - Cédula de Ciudadanía; CE - Cédula de Extranjería; NIT - Número de Identificación Tributaria; PASS - Passport; PEP - Permiso Especial de Permanencia", + "example": "CC" + }, + "ach_cop_email": { + "type": [ + "string", + "null" + ], + "example": "fernando.guzman@gmail.com" + }, + "ach_cop_bank_code": { + "type": [ + "string", + "null" + ], + "example": "051" + }, + "ach_cop_bank_account": { + "type": [ + "string", + "null" + ], + "example": "12345678" + }, + "swift_code_bic": { + "type": [ + "string", + "null" + ], + "example": "123456789" + }, + "swift_account_holder_name": { + "type": [ + "string", + "null" + ], + "example": "John Doe" + }, + "swift_account_number_iban": { + "type": [ + "string", + "null" + ], + "example": "123456789" + }, + "swift_beneficiary_address_line_1": { + "type": [ + "string", + "null" + ], + "example": "123 MAIN STREET SUITE 100" + }, + "swift_beneficiary_address_line_2": { + "type": [ + "string", + "null" + ], + "example": "BUILDING A FLOOR 5" + }, + "swift_beneficiary_country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "MX" + }, + "swift_beneficiary_city": { + "type": [ + "string", + "null" + ], + "example": "MEXICO CITY" + }, + "swift_beneficiary_state_province_region": { + "type": [ + "string", + "null" + ], + "example": "MX" + }, + "swift_beneficiary_postal_code": { + "type": [ + "string", + "null" + ], + "example": "11530" + }, + "swift_bank_name": { + "type": [ + "string", + "null" + ], + "example": "Banco Regional SA" + }, + "swift_bank_address_line_1": { + "type": [ + "string", + "null" + ], + "example": "123 Main Street, Suite 100, Downtown District, City Center CP 12345" + }, + "swift_bank_address_line_2": { + "type": [ + "string", + "null" + ], + "example": "456 Oak Avenue, Building 7, Financial District, Business Center CP 54321" + }, + "swift_bank_country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "MX" + }, + "swift_bank_city": { + "type": [ + "string", + "null" + ], + "example": "City" + }, + "swift_bank_state_province_region": { + "type": [ + "string", + "null" + ], + "example": "District" + }, + "swift_bank_postal_code": { + "type": [ + "string", + "null" + ], + "example": "11530" + }, + "swift_ifsc_branch_code": { + "type": [ + "string", + "null" + ], + "pattern": "^[A-Z]{4}0[A-Z0-9]{6}$", + "example": "BARB0AHIMCI" + }, + "swift_intermediary_bank_swift_code_bic": { + "anyOf": [ + { + "type": "string", + "minLength": 8, + "maxLength": 8 + }, + { + "type": "string", + "minLength": 11, + "maxLength": 11 + }, + { + "type": "null" + } + ], + "example": "AEIBARB1" + }, + "swift_intermediary_bank_account_number_iban": { + "type": [ + "string", + "null" + ], + "maxLength": 34, + "example": "123456789" + }, + "swift_intermediary_bank_name": { + "type": [ + "string", + "null" + ], + "example": "Banco Regional SA" + }, + "swift_intermediary_bank_country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "US" + }, + "swift_intermediary_bank_routing_number": { + "anyOf": [ + { + "type": "string", + "enum": [ + "" + ] + }, + { + "type": "string", + "pattern": "^\\d{9}$" + }, + { + "type": "null" + } + ], + "description": "US ABA routing number of the correspondent bank, from the beneficiary bank USD wire instructions. Used by providers that require an explicit US correspondent for the SWIFT route.", + "example": "021000089" + }, + "sepa_iban": { + "type": [ + "string", + "null" + ], + "example": "DE89370400440532013000" + }, + "sepa_beneficiary_bic": { + "type": [ + "string", + "null" + ], + "description": "BIC/SWIFT code of the beneficiary bank", + "example": "TRWIBEB1XXX" + }, + "sepa_beneficiary_legal_name": { + "type": [ + "string", + "null" + ], + "maxLength": 128, + "example": "Hans Müller" + }, + "sepa_beneficiary_address_line_1": { + "type": [ + "string", + "null" + ], + "example": "Friedrichstraße 12" + }, + "sepa_beneficiary_address_line_2": { + "type": [ + "string", + "null" + ], + "example": "Apt 4B" + }, + "sepa_beneficiary_city": { + "type": [ + "string", + "null" + ], + "example": "Berlin" + }, + "sepa_beneficiary_state_province_region": { + "type": [ + "string", + "null" + ], + "example": "Berlin" + }, + "sepa_beneficiary_postal_code": { + "type": [ + "string", + "null" + ], + "example": "10117" + }, + "sepa_beneficiary_country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "DE" + }, + "faster_payments_sort_code": { + "type": [ + "string", + "null" + ], + "description": "UK bank sort code, 6 digits. Dashes and spaces are stripped.", + "example": "040004" + }, + "faster_payments_account_number": { + "type": [ + "string", + "null" + ], + "description": "UK bank account number, 8 digits.", + "example": "12345678" + }, + "faster_payments_beneficiary_legal_name": { + "type": [ + "string", + "null" + ], + "maxLength": 128, + "example": "Oliver Smith" + }, + "faster_payments_beneficiary_address_line_1": { + "type": [ + "string", + "null" + ], + "example": "221B Baker Street" + }, + "faster_payments_beneficiary_address_line_2": { + "type": [ + "string", + "null" + ], + "example": "Flat 2" + }, + "faster_payments_beneficiary_city": { + "type": [ + "string", + "null" + ], + "example": "London" + }, + "faster_payments_beneficiary_state_province_region": { + "type": [ + "string", + "null" + ], + "example": "Greater London" + }, + "faster_payments_beneficiary_postal_code": { + "type": [ + "string", + "null" + ], + "example": "NW1 6XE" + }, + "faster_payments_beneficiary_country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "GB" }, - "created_at": { + "business_industry": { "type": [ "string", "null" ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" - } - }, - "required": [ - "id", - "type", - "name" - ] - }, - "CreateBankAccountIn": { - "type": "object", - "properties": { - "type": { - "type": "string", "enum": [ - "wire", - "ach", - "pix", - "pix_safe", - "ted", - "spei_bitso", - "transfers_bitso", - "ach_cop_bitso", - "international_swift", - "rtp", - "sepa" + "111998", + "112120", + "113310", + "115114", + "111120", + "111219", + "111336", + "111421", + "112111", + "112210", + "112310", + "112410", + "112519", + "112990", + "113110", + "113210", + "114119", + "114210", + "115113", + "115210", + "115310", + "541211", + "541213", + "541219", + "541810", + "541430", + "541715", + "541930", + "561422", + "561311", + "561612", + "561740", + "561730", + "532490", + "533110", + "541490", + "541690", + "541720", + "561110", + "561210", + "561611", + "561990", + "722310", + "236115", + "236220", + "237310", + "238210", + "236118", + "236210", + "237130", + "237210", + "237990", + "238191", + "238391", + "238991", + "541310", + "811111", + "812111", + "812112", + "532111", + "624410", + "541922", + "811210", + "812199", + "532289", + "532310", + "561790", + "811198", + "811310", + "811411", + "812210", + "812320", + "812990", + "814110", + "611110", + "611310", + "611410", + "611710", + "611210", + "611420", + "611519", + "611699", + "211120", + "212114", + "221310", + "562111", + "562920", + "213112", + "211130", + "212290", + "212390", + "213113", + "221122", + "221210", + "221320", + "324110", + "562211", + "562998", + "522110", + "522210", + "522320", + "523150", + "523940", + "523999", + "524113", + "521110", + "522130", + "522298", + "522390", + "523210", + "524128", + "524298", + "525190", + "525910", + "813110", + "813211", + "813219", + "624190", + "624230", + "624310", + "813319", + "813410", + "813930", + "921140", + "922190", + "923130", + "924110", + "925120", + "926110", + "927110", + "928110", + "551112", + "551114", + "721110", + "722511", + "722513", + "561510", + "713110", + "713210", + "712110", + "711110", + "711211", + "487110", + "487210", + "487990", + "561599", + "711190", + "711219", + "711310", + "712120", + "713290", + "713990", + "721199", + "721211", + "721310", + "722410", + "621111", + "621210", + "622110", + "623110", + "621511", + "623220", + "541940", + "621399", + "621910", + "621498", + "621610", + "621999", + "622210", + "622310", + "623210", + "623311", + "623990", + "541110", + "541199", + "311421", + "337121", + "322220", + "339920", + "334210", + "339930", + "312130", + "334111", + "334118", + "325412", + "339112", + "336110", + "336390", + "315990", + "313110", + "339910", + "311119", + "311212", + "311314", + "311422", + "311511", + "311612", + "311710", + "311811", + "311999", + "312111", + "312230", + "313240", + "313310", + "314120", + "314999", + "315120", + "315250", + "316110", + "316210", + "316990", + "321113", + "321211", + "321918", + "322120", + "322299", + "323120", + "325180", + "325220", + "325320", + "325510", + "325611", + "325998", + "326111", + "326220", + "327120", + "327212", + "327310", + "327410", + "327999", + "331110", + "331210", + "331313", + "331410", + "331511", + "332111", + "332215", + "332311", + "332410", + "332510", + "332613", + "332710", + "332812", + "332999", + "333111", + "333248", + "333310", + "333413", + "333517", + "333611", + "333618", + "334310", + "334413", + "334511", + "334610", + "335131", + "335220", + "335311", + "335999", + "336211", + "336412", + "336510", + "336611", + "336999", + "337122", + "337214", + "337920", + "339999", + "516120", + "513130", + "512250", + "519130", + "519290", + "711410", + "711510", + "512199", + "512290", + "515210", + "531110", + "531120", + "531130", + "531190", + "531210", + "531311", + "531312", + "531320", + "531390", + "454110", + "445110", + "455110", + "457110", + "449210", + "444110", + "459210", + "459120", + "445320", + "458110", + "458210", + "458310", + "455219", + "424210", + "456110", + "446120", + "456120", + "441110", + "441227", + "441330", + "444180", + "444240", + "445132", + "445298", + "449110", + "449129", + "454390", + "458320", + "459310", + "459410", + "459510", + "459999", + "541511", + "541512", + "541519", + "518210", + "511210", + "513210", + "517111", + "517112", + "517410", + "517810", + "481111", + "483111", + "485210", + "488510", + "484121", + "493110", + "423430", + "423690", + "423110", + "423830", + "423840", + "423510", + "424690", + "424990", + "424410", + "424480", + "423940", + "423120", + "423220", + "423310", + "423490", + "423520", + "423620", + "423710", + "423990", + "424110", + "424310", + "424490", + "424590", + "424720", + "424820", + "425120", + "481211", + "482111", + "483112", + "483212", + "484110", + "484220", + "485119", + "485310", + "485410", + "485510", + "485999", + "486110", + "486210", + "486990", + "488190", + "488210", + "488390", + "488490", + "488999", + "492110", + "492210", + "493190", + "541611", + "541618", + "541330", + "541990", + "541214", + "561499" ], - "example": "wire" + "example": "541511" }, - "name": { - "type": "string", - "example": "Bank Account Name" + "phone_number": { + "type": [ + "string", + "null" + ], + "example": "+13055555555" + }, + "tax_id": { + "type": [ + "string", + "null" + ], + "maxLength": 32, + "example": "536804398" + }, + "date_of_birth": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "example": "1998-01-01T00:00:00Z" + }, + "pix_safe_bank_code": { + "type": [ + "string", + "null" + ], + "pattern": "^\\d{4,8}$", + "example": "00416968" + }, + "pix_safe_branch_code": { + "type": [ + "string", + "null" + ], + "pattern": "^\\d{4}(-\\d)?$", + "example": "0001" + }, + "pix_safe_cpf_cnpj": { + "type": [ + "string", + "null" + ], + "example": "12345678901" + }, + "ted_bank_code": { + "type": [ + "string", + "null" + ], + "pattern": "^\\d{3,5}$", + "example": "033" + }, + "ted_branch_code": { + "type": [ + "string", + "null" + ], + "pattern": "^\\d{4}(-\\d)?$", + "example": "0001" + }, + "ted_cpf_cnpj": { + "type": [ + "string", + "null" + ], + "example": "12345678901" + }, + "tron_wallet_hash": { + "type": [ + "string", + "null" + ], + "example": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t" + }, + "offramp_wallets": { + "type": [ + "array", + "null" + ], + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "ow_000000000000" + }, + "external_id": { + "type": [ + "string", + "null" + ], + "example": "your_external_id" + }, + "circle_wallet_id": { + "type": [ + "string", + "null" + ], + "example": "01234567-abcd-efgh-ijkl-012345678901" + }, + "network": { + "type": "string", + "enum": [ + "tron", + "solana", + "solana_devnet", + "arbitrum", + "base", + "ethereum", + "polygon", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "polygon_amoy", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "tron" + }, + "address": { + "type": "string", + "example": "TALJN9zTTEL9TVBb4WuTt6wLvPqJZr3hvb" + } + }, + "required": [ + "id", + "network", + "address" + ] + }, + "example": [ + { + "address": "TALJN9zTTEL9TVBb4WuTt6wLvPqJZr3hvb", + "id": "ow_000000000000", + "network": "tron", + "external_id": "your_external_id" + } + ] }, "status": { "type": [ @@ -23688,6 +33762,9 @@ "in_swift_p0107", "in_swift_p0108", "in_swift_p0109", + "in_swift_p0304", + "in_swift_p1099", + "in_swift_p1108", "jp_swift_1001", "jp_swift_1002", "jp_swift_1003", @@ -24396,873 +34473,4681 @@ "za_swift_10301", "za_swift_27201" ], - "example": "bh_swift_afl" + "example": "bh_swift_afl" + }, + "plaid_connected_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "When the bank account was verified through Plaid. Set means the account can fund an ach payin by pull.", + "example": "2021-01-01T00:00:00Z" + }, + "created_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + } + }, + "required": [ + "id", + "type", + "name" + ] + }, + "VirtualAccountOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "va_000000000000" + }, + "banking_partner": { + "type": [ + "string", + "null" + ], + "enum": [ + "jpmorgan", + "citi", + "hsbc", + "cfsb", + "portage", + "bre_b", + "spei", + "portage_g" + ], + "example": "jpmorgan" + }, + "kyc_status": { + "type": [ + "string", + "null" + ], + "enum": [ + "verifying", + "approved", + "rejected", + "deprecated", + "pending_review", + "awaiting_contract", + "compliance_request", + "approved_rfi" + ], + "example": "approved" + }, + "us": { + "type": [ + "object", + "null" + ], + "properties": { + "ach": { + "type": [ + "object", + "null" + ], + "properties": { + "routing_number": { + "type": "string", + "example": "123456789" + }, + "account_number": { + "type": "string", + "example": "123456789" + } + }, + "required": [ + "routing_number", + "account_number" + ] + }, + "wire": { + "type": "object", + "properties": { + "routing_number": { + "type": "string", + "example": "123456789" + }, + "account_number": { + "type": "string", + "example": "123456789" + } + }, + "required": [ + "routing_number", + "account_number" + ] + }, + "rtp": { + "type": [ + "object", + "null" + ], + "properties": { + "routing_number": { + "type": "string", + "example": "123456789" + }, + "account_number": { + "type": "string", + "example": "123456789" + } + }, + "required": [ + "routing_number", + "account_number" + ] + }, + "swift_bic_code": { + "type": [ + "string", + "null" + ], + "example": "TCCLGB3L" + }, + "swift_account_number": { + "type": [ + "string", + "null" + ], + "example": "GB50TCCL04140449730892" + }, + "account_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "Personal checking", + "Business checking" + ], + "default": "Business checking", + "example": "Business checking" + }, + "beneficiary": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": "string", + "example": "Customer Name" + }, + "address_line_1": { + "type": "string", + "example": "8 The Green, #19364" + }, + "address_line_2": { + "type": "string", + "example": "Dover, DE 19901" + } + }, + "required": [ + "name", + "address_line_1", + "address_line_2" + ] + }, + "receiving_bank": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": "string", + "example": "JPMorgan Chase" + }, + "address_line_1": { + "type": "string", + "example": "270 Park Ave" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "New York, NY, 10017-2070" + } + }, + "required": [ + "name", + "address_line_1" + ] + }, + "swift_receiving_bank": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": [ + "string", + "null" + ], + "example": "JPMorgan Chase" + }, + "address_line_1": { + "type": [ + "string", + "null" + ], + "example": "270 Park Ave" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "New York, NY, 10017-2070" + } + } + }, + "swift_intermediary_bank": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": [ + "string", + "null" + ], + "example": "JP Morgan Chase NA" + }, + "swift_code_bic": { + "type": [ + "string", + "null" + ], + "example": "CHASUS33" + }, + "routing_number": { + "type": [ + "string", + "null" + ], + "example": "021000021" + }, + "address_line_1": { + "type": [ + "string", + "null" + ], + "example": "270 Park Ave" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "New York, NY, 10017-2070" + } + } + } + }, + "required": [ + "wire" + ] + }, + "co": { + "type": [ + "object", + "null" + ], + "properties": { + "bre_b": { + "type": "object", + "properties": { + "key": { + "type": "string", + "example": "@BP000000000000" + } + }, + "required": [ + "key" + ] + }, + "beneficiary": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": "string", + "example": "Customer Name" + } + }, + "required": [ + "name" + ] + } + }, + "required": [ + "bre_b" + ] + }, + "mx": { + "type": [ + "object", + "null" + ], + "properties": { + "spei": { + "type": "object", + "properties": { + "clabe": { + "type": "string", + "minLength": 18, + "maxLength": 18, + "example": "710969000000000001" + } + }, + "required": [ + "clabe" + ] + }, + "beneficiary": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": "string", + "example": "BLINDPAY LLC" + } + }, + "required": [ + "name" + ] + } + }, + "required": [ + "spei" + ] + }, + "token": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB" + ], + "example": "USDC" + }, + "blockchain_wallet_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "example": "bw_000000000000" + }, + "blockchain_wallet": { + "type": [ + "object", + "null" + ], + "properties": { + "network": { + "type": "string", + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "polygon" + }, + "address": { + "type": [ + "string", + "null" + ], + "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" + } + }, + "required": [ + "network" + ] + }, + "partner_fee_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "example": "pf_000000000000" + }, + "customer_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + } + }, + "required": [ + "id", + "banking_partner", + "kyc_status", + "token" + ] + }, + "CreateVirtualAccountIn": { + "type": "object", + "properties": { + "banking_partner": { + "type": "string", + "enum": [ + "jpmorgan", + "citi", + "hsbc", + "cfsb", + "portage", + "bre_b", + "spei", + "portage_g" + ], + "example": "jpmorgan" + }, + "token": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB" + ], + "example": "USDC" + }, + "blockchain_wallet_id": { + "type": "string", + "minLength": 15, + "maxLength": 15 + }, + "sole_proprietor_doc_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "master_service_agreement", + "salary_slip", + "bank_statement" + ], + "example": "master_service_agreement" + }, + "sole_proprietor_doc_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "example": "https://example.com/document.pdf" + }, + "partner_fee_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "example": "pf_000000000000" + }, + "bre_b": { + "type": [ + "object", + "null" + ], + "properties": { + "gender": { + "type": "string", + "enum": [ + "male", + "female" + ], + "example": "female" + } + }, + "required": [ + "gender" + ] + } + }, + "required": [ + "banking_partner", + "token", + "blockchain_wallet_id" + ] + }, + "UpdateVirtualAccountIn": { + "type": "object", + "properties": { + "token": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB" + ], + "example": "USDC" + }, + "blockchain_wallet_id": { + "type": "string", + "minLength": 15, + "maxLength": 15 + }, + "partner_fee_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "example": "pf_000000000000" + } + }, + "required": [ + "token", + "blockchain_wallet_id" + ] + }, + "SimulateBrebDepositIn": { + "type": "object", + "properties": { + "amount": { + "type": "integer", + "exclusiveMinimum": 0, + "description": "Deposit amount in COP cents (50000000 = COP 500,000.00).", + "example": 50000000 + }, + "sender_name": { + "type": [ + "string", + "null" + ], + "minLength": 1, + "maxLength": 255, + "example": "Jane Smith" + }, + "sender_document_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "CC", + "CE", + "NIT", + "TI", + "PA" + ], + "example": "CC" + }, + "sender_document_id": { + "type": [ + "string", + "null" + ], + "minLength": 1, + "maxLength": 32, + "example": "123456789" + }, + "deposit_id": { + "type": [ + "string", + "null" + ], + "pattern": "^[a-zA-Z0-9_-]{1,32}$", + "description": "Reuse a value to replay the same deposit; omit for a new one.", + "example": "dep_000000000000" + } + }, + "required": [ + "amount" + ] + }, + "SimulateSpeiDepositIn": { + "type": "object", + "properties": { + "amount": { + "type": "integer", + "exclusiveMinimum": 0, + "description": "Deposit amount in MXN cents (1000000 = MXN 10,000.00).", + "example": 1000000 + }, + "sender_name": { + "type": [ + "string", + "null" + ], + "minLength": 1, + "maxLength": 255, + "example": "Juan Perez" + }, + "sender_clabe": { + "type": [ + "string", + "null" + ], + "minLength": 18, + "maxLength": 18, + "example": "012180001234567890" + }, + "sender_rfc_curp": { + "type": [ + "string", + "null" + ], + "minLength": 1, + "maxLength": 18, + "example": "PEPJ800101ABC" + }, + "deposit_id": { + "type": [ + "string", + "null" + ], + "pattern": "^[a-zA-Z0-9_-]{1,32}$", + "description": "Reuse a value to replay the same deposit; omit for a new one.", + "example": "dep_000000000000" + } + }, + "required": [ + "amount" + ] + }, + "CreateCustomerIn": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "individual", + "business" + ], + "example": "individual" + }, + "kyc_type": { + "type": "string", + "enum": [ + "light", + "standard", + "enhanced" + ], + "description": "Use standard for individuals and businesses, or enhanced for individuals. light is not available for new customers, and businesses only support standard.", + "example": "standard" + }, + "email": { + "type": "string", + "format": "email", + "example": "email@example.com" + }, + "tax_id": { + "type": [ + "string", + "null" + ], + "example": "536804398" + }, + "address_line_1": { + "type": [ + "string", + "null" + ], + "example": "738 Plain St" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "Building 22" + }, + "city": { + "type": [ + "string", + "null" + ], + "example": "Marshfield" + }, + "state_province_region": { + "type": [ + "string", + "null" + ], + "example": "MA" + }, + "country": { + "type": "string", + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "US" + }, + "postal_code": { + "type": [ + "string", + "null" + ], + "example": "02050" + }, + "ip_address": { + "type": [ + "string", + "null" + ], + "format": "ip", + "example": "127.0.0.1" + }, + "latitude": { + "type": [ + "number", + "null" + ], + "minimum": -90, + "maximum": 90, + "description": "Optional geolocation latitude collected from the customer. Forwarded to AiPrise and SEON for fraud analysis.", + "example": 37.7749 + }, + "longitude": { + "type": [ + "number", + "null" + ], + "minimum": -180, + "maximum": 180, + "description": "Optional geolocation longitude collected from the customer. Forwarded to AiPrise and SEON for fraud analysis.", + "example": -122.4194 + }, + "image_url": { + "type": [ + "string", + "null" + ], + "format": "uri", + "example": "https://example.com/image.png" + }, + "phone_number": { + "type": [ + "string", + "null" + ], + "example": "+13055555555" + }, + "proof_of_address_doc_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "UTILITY_BILL", + "BANK_STATEMENT", + "RENTAL_AGREEMENT", + "TAX_DOCUMENT", + "GOVERNMENT_CORRESPONDENCE" + ], + "example": "UTILITY_BILL" + }, + "proof_of_address_doc_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "Please upload one document that serve as proof of address, this needs to be the same physical address as the one provided above. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", + "example": "https://example.com/image.png" + }, + "first_name": { + "type": [ + "string", + "null" + ], + "example": "John" + }, + "last_name": { + "type": [ + "string", + "null" + ], + "example": "Doe" + }, + "date_of_birth": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "example": "1998-01-01T00:00:00Z" + }, + "id_doc_country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "BR" + }, + "id_doc_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "PASSPORT", + "ID_CARD", + "DRIVERS" + ], + "example": "PASSPORT" + }, + "id_doc_front_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "Only image files are accepted (.jpg, .jpeg, .png)", + "example": "https://example.com/image.png" + }, + "id_doc_back_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "Only image files are accepted (.jpg, .jpeg, .png)", + "example": "https://example.com/image.png" + }, + "legal_name": { + "type": [ + "string", + "null" + ], + "example": "Company Name Inc." + }, + "alternate_name": { + "type": [ + "string", + "null" + ], + "example": "Company Name Inc." + }, + "formation_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "example": "1998-01-01T00:00:00Z", + "format": "date-time" + }, + "website": { + "type": [ + "string", + "null" + ], + "format": "uri", + "example": "https://example.com" + }, + "owners": { + "type": [ + "array", + "null" + ], + "items": { + "type": "object", + "properties": { + "role": { + "type": "string", + "enum": [ + "beneficial_controlling", + "beneficial_owner", + "controlling_person" + ], + "description": "A beneficial owner is someone who directly or indirectly owns 25% or more of your business. A controlling person is someone with significant responsibility to control, manage or direct your business (typically a CEO, senior executive officer or equivalent).", + "example": "beneficial_owner" + }, + "first_name": { + "type": "string", + "minLength": 1, + "example": "John" + }, + "last_name": { + "type": "string", + "minLength": 1, + "example": "Doe" + }, + "date_of_birth": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + } + ], + "example": "1998-01-01T00:00:00Z" + }, + "tax_id": { + "type": "string", + "example": "536804398" + }, + "address_line_1": { + "type": "string", + "example": "738 Plain St" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "Building 22" + }, + "city": { + "type": "string", + "example": "Marshfield" + }, + "state_province_region": { + "type": "string", + "example": "MA" + }, + "country": { + "type": "string", + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "US" + }, + "postal_code": { + "type": "string", + "example": "02050" + }, + "id_doc_country": { + "type": "string", + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "BR" + }, + "id_doc_type": { + "type": "string", + "enum": [ + "PASSPORT", + "ID_CARD", + "DRIVERS" + ], + "example": "PASSPORT" + }, + "id_doc_front_file": { + "type": "string", + "format": "uri" + }, + "id_doc_back_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "Only image files are accepted (.jpg, .jpeg, .png)" + }, + "proof_of_address_doc_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "UTILITY_BILL", + "BANK_STATEMENT", + "RENTAL_AGREEMENT", + "TAX_DOCUMENT", + "GOVERNMENT_CORRESPONDENCE" + ], + "example": "UTILITY_BILL" + }, + "proof_of_address_doc_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "Please upload one document that serve as proof of address, this needs to be the same address as the one provided above. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB." + }, + "ownership_percentage": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "maximum": 100, + "description": "Ownership percentage of the beneficial owner (0-100)", + "example": 25 + }, + "title": { + "type": [ + "string", + "null" + ], + "maxLength": 128, + "description": "Job title of the owner", + "example": "CEO" + }, + "tax_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "SSN", + "ITIN" + ], + "description": "Tax identifier type. Mandatory when country is US; must be SSN or ITIN.", + "example": "SSN" + } + }, + "required": [ + "role", + "first_name", + "last_name", + "date_of_birth", + "tax_id", + "address_line_1", + "city", + "state_province_region", + "country", + "postal_code", + "id_doc_country", + "id_doc_type", + "id_doc_front_file" + ] + } + }, + "incorporation_doc_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "Please upload your articles of incorporation below. The articles of incorporation or a certificate of incorporation usually includes information like the company name, business purpose, number of shares offered, value of shares, etc. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", + "example": "https://example.com/image.png" + }, + "proof_of_ownership_doc_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "Please upload your proof of ownership below. This document usually includes information like the shareholders names and percentages. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", + "example": "https://example.com/image.png" + }, + "source_of_funds_doc_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "business_income", + "gambling_proceeds", + "gifts", + "government_benefits", + "inheritance", + "investment_loans", + "pension_retirement", + "salary", + "sale_of_assets_real_estate", + "savings", + "esops", + "investment_proceeds", + "someone_else_funds" + ], + "example": "business_income" + }, + "source_of_funds_doc_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "example": "https://example.com/image.png" + }, + "selfie_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "Only image files are accepted (.jpg, .jpeg, .png)", + "example": "https://example.com/image.png" + }, + "purpose_of_transactions": { + "type": [ + "string", + "null" + ], + "enum": [ + "business_transactions", + "charitable_donations", + "investment_purposes", + "payments_to_friends_or_family_abroad", + "personal_or_living_expenses", + "protect_wealth", + "purchase_good_and_services", + "receive_payment_for_freelancing", + "receive_salary", + "other" + ], + "example": "business_transactions" + }, + "purpose_of_transactions_explanation": { + "type": [ + "string", + "null" + ], + "example": "I am a business owner and I want to receive payments from my customers" + }, + "account_purpose": { + "type": [ + "string", + "null" + ], + "enum": [ + "charitable_donations", + "ecommerce_retail_payments", + "investment_purposes", + "business_expenses", + "payments_to_friends_or_family_abroad", + "personal_or_living_expenses", + "protect_wealth", + "purchase_goods_and_services", + "receive_payments_for_goods_and_services", + "tax_optimization", + "third_party_money_transmission", + "payroll", + "treasury_management", + "other" + ], + "example": "treasury_management" + }, + "account_purpose_other": { + "type": [ + "string", + "null" + ], + "maxLength": 512, + "description": "Required when account_purpose is \"other\". Max 512 characters.", + "example": "Custom account purpose description" + }, + "business_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "corporation", + "llc", + "partnership", + "sole_proprietorship", + "trust", + "non_profit" + ], + "example": "llc" + }, + "business_description": { + "type": [ + "string", + "null" + ], + "maxLength": 1000, + "example": "Software development company" + }, + "business_industry": { + "type": [ + "string", + "null" + ], + "enum": [ + "111998", + "112120", + "113310", + "115114", + "111120", + "111219", + "111336", + "111421", + "112111", + "112210", + "112310", + "112410", + "112519", + "112990", + "113110", + "113210", + "114119", + "114210", + "115113", + "115210", + "115310", + "541211", + "541213", + "541219", + "541810", + "541430", + "541715", + "541930", + "561422", + "561311", + "561612", + "561740", + "561730", + "532490", + "533110", + "541490", + "541690", + "541720", + "561110", + "561210", + "561611", + "561990", + "722310", + "236115", + "236220", + "237310", + "238210", + "236118", + "236210", + "237130", + "237210", + "237990", + "238191", + "238391", + "238991", + "541310", + "811111", + "812111", + "812112", + "532111", + "624410", + "541922", + "811210", + "812199", + "532289", + "532310", + "561790", + "811198", + "811310", + "811411", + "812210", + "812320", + "812990", + "814110", + "611110", + "611310", + "611410", + "611710", + "611210", + "611420", + "611519", + "611699", + "211120", + "212114", + "221310", + "562111", + "562920", + "213112", + "211130", + "212290", + "212390", + "213113", + "221122", + "221210", + "221320", + "324110", + "562211", + "562998", + "522110", + "522210", + "522320", + "523150", + "523940", + "523999", + "524113", + "521110", + "522130", + "522298", + "522390", + "523210", + "524128", + "524298", + "525190", + "525910", + "813110", + "813211", + "813219", + "624190", + "624230", + "624310", + "813319", + "813410", + "813930", + "921140", + "922190", + "923130", + "924110", + "925120", + "926110", + "927110", + "928110", + "551112", + "551114", + "721110", + "722511", + "722513", + "561510", + "713110", + "713210", + "712110", + "711110", + "711211", + "487110", + "487210", + "487990", + "561599", + "711190", + "711219", + "711310", + "712120", + "713290", + "713990", + "721199", + "721211", + "721310", + "722410", + "621111", + "621210", + "622110", + "623110", + "621511", + "623220", + "541940", + "621399", + "621910", + "621498", + "621610", + "621999", + "622210", + "622310", + "623210", + "623311", + "623990", + "541110", + "541199", + "311421", + "337121", + "322220", + "339920", + "334210", + "339930", + "312130", + "334111", + "334118", + "325412", + "339112", + "336110", + "336390", + "315990", + "313110", + "339910", + "311119", + "311212", + "311314", + "311422", + "311511", + "311612", + "311710", + "311811", + "311999", + "312111", + "312230", + "313240", + "313310", + "314120", + "314999", + "315120", + "315250", + "316110", + "316210", + "316990", + "321113", + "321211", + "321918", + "322120", + "322299", + "323120", + "325180", + "325220", + "325320", + "325510", + "325611", + "325998", + "326111", + "326220", + "327120", + "327212", + "327310", + "327410", + "327999", + "331110", + "331210", + "331313", + "331410", + "331511", + "332111", + "332215", + "332311", + "332410", + "332510", + "332613", + "332710", + "332812", + "332999", + "333111", + "333248", + "333310", + "333413", + "333517", + "333611", + "333618", + "334310", + "334413", + "334511", + "334610", + "335131", + "335220", + "335311", + "335999", + "336211", + "336412", + "336510", + "336611", + "336999", + "337122", + "337214", + "337920", + "339999", + "516120", + "513130", + "512250", + "519130", + "519290", + "711410", + "711510", + "512199", + "512290", + "515210", + "531110", + "531120", + "531130", + "531190", + "531210", + "531311", + "531312", + "531320", + "531390", + "454110", + "445110", + "455110", + "457110", + "449210", + "444110", + "459210", + "459120", + "445320", + "458110", + "458210", + "458310", + "455219", + "424210", + "456110", + "446120", + "456120", + "441110", + "441227", + "441330", + "444180", + "444240", + "445132", + "445298", + "449110", + "449129", + "454390", + "458320", + "459310", + "459410", + "459510", + "459999", + "541511", + "541512", + "541519", + "518210", + "511210", + "513210", + "517111", + "517112", + "517410", + "517810", + "481111", + "483111", + "485210", + "488510", + "484121", + "493110", + "423430", + "423690", + "423110", + "423830", + "423840", + "423510", + "424690", + "424990", + "424410", + "424480", + "423940", + "423120", + "423220", + "423310", + "423490", + "423520", + "423620", + "423710", + "423990", + "424110", + "424310", + "424490", + "424590", + "424720", + "424820", + "425120", + "481211", + "482111", + "483112", + "483212", + "484110", + "484220", + "485119", + "485310", + "485410", + "485510", + "485999", + "486110", + "486210", + "486990", + "488190", + "488210", + "488390", + "488490", + "488999", + "492110", + "492210", + "493190", + "541611", + "541618", + "541330", + "541990", + "541214", + "561499" + ], + "example": "541511" + }, + "estimated_annual_revenue": { + "type": [ + "string", + "null" + ], + "enum": [ + "0_99999", + "100000_999999", + "1000000_9999999", + "10000000_49999999", + "50000000_249999999", + "250000000_plus" + ], + "example": "1000000_9999999" + }, + "source_of_wealth": { + "type": [ + "string", + "null" + ], + "enum": [ + "business_dividends_or_profits", + "investments", + "asset_sales", + "client_investor_contributions", + "gambling", + "charitable_contributions", + "inheritance", + "affiliate_or_royalty_income", + "salary_or_wages", + "savings" + ], + "example": "affiliate_or_royalty_income" + }, + "publicly_traded": { + "type": [ + "boolean", + "null" + ], + "example": false + }, + "occupation": { + "type": [ + "string", + "null" + ], + "maxLength": 255, + "example": "Software Engineer" + }, + "external_id": { + "type": [ + "string", + "null" + ], + "example": "your_company_external_id" + }, + "tos_id": { + "type": [ + "string", + "null" + ], + "minLength": 15, + "maxLength": 15, + "example": "to_000000000000" + }, + "additional_info": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/components/schemas/AdditionalInfoItem" + }, + "description": "Optional extra documents or notes for this customer. `label` is a known category, `value` is either a URL to upload or a free-text description. Any URLs are downloaded and re-hosted on Blindpay storage before being stored.", + "example": [ + { + "label": "EIN_LETTER", + "value": "https://example.com/ein.pdf" + }, + { + "label": "FLOW_OF_FUNDS", + "value": "Funds originate from US payroll deposits, forwarded weekly to customer." + } + ] + } + }, + "required": [ + "type", + "kyc_type", + "email", + "country" + ] + }, + "CustomerOut": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "customer_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "type": { + "type": "string", + "enum": [ + "individual", + "business" + ], + "example": "individual" + }, + "kyc_type": { + "type": "string", + "enum": [ + "light", + "standard", + "enhanced" + ], + "description": "Use standard for individuals and businesses, or enhanced for individuals. light is not available for new customers, and businesses only support standard.", + "example": "standard" + }, + "kyc_status": { + "type": "string", + "enum": [ + "verifying", + "approved", + "rejected", + "deprecated", + "pending_review", + "awaiting_contract", + "compliance_request", + "approved_rfi" + ], + "example": "verifying" + }, + "kyc_warnings": { + "type": [ + "array", + "null" + ], + "items": { + "type": "object", + "properties": { + "code": { + "type": [ + "string", + "null" + ] + }, + "message": { + "type": [ + "string", + "null" + ] + }, + "resolution_status": { + "type": [ + "string", + "null" + ] + }, + "warning_id": { + "type": [ + "string", + "null" + ] + } + } + }, + "description": "You can find more information here: https://docs.aiprise.com/docs/warnings-and-error-codes", + "example": [ + { + "code": "BIRTH_DATE_MISMATCH", + "message": "Mismatch between supplied birth date and extracted/looked up birth date.", + "resolution_status": "UNRESOLVED", + "warning_id": "38170889-50aa-4271-9eb1-61113ebf408c" + } + ] + }, + "fraud_warnings": { + "type": [ + "array", + "null" + ], + "items": { + "type": "object", + "properties": { + "id": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "operation": { + "type": [ + "string", + "null" + ] + }, + "score": { + "type": [ + "number", + "null" + ] + } + } + }, + "example": [ + { + "id": "UC114", + "name": "User never used a Datacenter proxy and this device before", + "operation": "+", + "score": 10 + } + ] + }, + "email": { + "type": "string", + "format": "email", + "example": "email@example.com" + }, + "tax_id": { + "type": [ + "string", + "null" + ], + "example": "536804398" + }, + "address_line_1": { + "type": [ + "string", + "null" + ], + "example": "738 Plain St" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "Building 22" + }, + "city": { + "type": [ + "string", + "null" + ], + "example": "Marshfield" + }, + "state_province_region": { + "type": [ + "string", + "null" + ], + "example": "MA" + }, + "country": { + "type": "string", + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "US" }, - "pix_key": { + "postal_code": { "type": [ "string", "null" ], - "example": "14947677768" + "example": "02050" }, - "force_cpf_cnpj": { + "ip_address": { "type": [ - "boolean", + "string", "null" ], - "description": "Force CPF/CNPJ validation for PIX key", - "example": false + "format": "ip", + "example": "127.0.0.1" }, - "beneficiary_name": { + "latitude": { + "type": [ + "number", + "null" + ], + "minimum": -90, + "maximum": 90, + "description": "Optional geolocation latitude collected from the customer. Forwarded to AiPrise and SEON for fraud analysis.", + "example": 37.7749 + }, + "longitude": { + "type": [ + "number", + "null" + ], + "minimum": -180, + "maximum": 180, + "description": "Optional geolocation longitude collected from the customer. Forwarded to AiPrise and SEON for fraud analysis.", + "example": -122.4194 + }, + "image_url": { "type": [ "string", "null" ], - "maxLength": 128, - "example": "Individual full name or business name" + "example": "https://example.com/image.png" }, - "routing_number": { + "phone_number": { "type": [ "string", "null" ], - "example": "012345678" + "example": "+13055555555" + }, + "proof_of_address_doc_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "UTILITY_BILL", + "BANK_STATEMENT", + "RENTAL_AGREEMENT", + "TAX_DOCUMENT", + "GOVERNMENT_CORRESPONDENCE" + ], + "example": "UTILITY_BILL" + }, + "proof_of_address_doc_file": { + "type": [ + "string", + "null" + ], + "description": "Please upload one document that serve as proof of address, this needs to be the same physical address as the one provided above. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", + "example": "https://example.com/image.png" + }, + "first_name": { + "type": [ + "string", + "null" + ], + "example": "John" + }, + "last_name": { + "type": [ + "string", + "null" + ], + "example": "Doe" + }, + "date_of_birth": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "example": "1998-01-01T00:00:00Z" + }, + "id_doc_country": { + "type": [ + "string", + "null" + ], + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "BR" + }, + "id_doc_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "PASSPORT", + "ID_CARD", + "DRIVERS" + ], + "example": "PASSPORT" + }, + "id_doc_front_file": { + "type": [ + "string", + "null" + ], + "description": "Only image files are accepted (.jpg, .jpeg, .png)", + "example": "https://example.com/image.png" + }, + "id_doc_back_file": { + "type": [ + "string", + "null" + ], + "description": "Only image files are accepted (.jpg, .jpeg, .png)", + "example": "https://example.com/image.png" + }, + "legal_name": { + "type": [ + "string", + "null" + ], + "example": "Company Name Inc." + }, + "alternate_name": { + "type": [ + "string", + "null" + ], + "example": "Company Name Inc." + }, + "formation_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "example": "1998-01-01T00:00:00Z", + "format": "date-time" + }, + "website": { + "type": [ + "string", + "null" + ], + "format": "uri", + "example": "https://example.com" + }, + "owners": { + "type": [ + "array", + "null" + ], + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "ub_000000000000" + }, + "instance_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "customer_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "role": { + "type": "string", + "enum": [ + "beneficial_controlling", + "beneficial_owner", + "controlling_person" + ], + "description": "A beneficial owner is someone who directly or indirectly owns 25% or more of your business. A controlling person is someone with significant responsibility to control, manage or direct your business (typically a CEO, senior executive officer or equivalent).", + "example": "beneficial_owner" + }, + "first_name": { + "type": "string", + "minLength": 1, + "example": "John" + }, + "last_name": { + "type": "string", + "minLength": 1, + "example": "Doe" + }, + "date_of_birth": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + } + ], + "example": "1998-01-01T00:00:00Z" + }, + "tax_id": { + "type": [ + "string", + "null" + ], + "example": "536804398" + }, + "address_line_1": { + "type": "string", + "example": "738 Plain St" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "Building 22" + }, + "city": { + "type": "string", + "example": "Marshfield" + }, + "state_province_region": { + "type": "string", + "example": "MA" + }, + "country": { + "type": "string", + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "US" + }, + "postal_code": { + "type": "string", + "example": "02050" + }, + "id_doc_country": { + "type": "string", + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "BR" + }, + "id_doc_type": { + "type": "string", + "enum": [ + "PASSPORT", + "ID_CARD", + "DRIVERS" + ], + "example": "PASSPORT" + }, + "id_doc_front_file": { + "type": [ + "string", + "null" + ], + "description": "Only image files are accepted (.jpg, .jpeg, .png)" + }, + "id_doc_back_file": { + "type": [ + "string", + "null" + ], + "description": "Only image files are accepted (.jpg, .jpeg, .png)" + }, + "proof_of_address_doc_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "UTILITY_BILL", + "BANK_STATEMENT", + "RENTAL_AGREEMENT", + "TAX_DOCUMENT", + "GOVERNMENT_CORRESPONDENCE" + ], + "example": "UTILITY_BILL" + }, + "proof_of_address_doc_file": { + "type": [ + "string", + "null" + ], + "description": "Please upload one document that serve as proof of address, this needs to be the same address as the one provided above. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB." + }, + "ownership_percentage": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "maximum": 100, + "description": "Ownership percentage of the beneficial owner (0-100)", + "example": 25 + }, + "title": { + "type": [ + "string", + "null" + ], + "maxLength": 128, + "description": "Job title of the owner", + "example": "CEO" + }, + "tax_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "SSN", + "ITIN" + ], + "description": "Tax identifier type. Mandatory when country is US; must be SSN or ITIN.", + "example": "SSN" + } + } + }, + "description": "Customer owners", + "example": [ + { + "id": "ub_000000000000", + "first_name": "John", + "last_name": "Doe", + "address_line_1": "738 Plain St", + "address_line_2": "Building 22", + "city": "Marshfield", + "state_province_region": "MA", + "country": "US", + "postal_code": "02050", + "id_doc_country": "BR", + "id_doc_type": "PASSPORT", + "id_doc_front_file": "https://example.com/image.png", + "id_doc_back_file": "https://example.com/image.png" + } + ] }, - "account_number": { + "incorporation_doc_file": { "type": [ "string", "null" ], - "example": "1001001234" + "description": "Please upload your articles of incorporation below. The articles of incorporation or a certificate of incorporation usually includes information like the company name, business purpose, number of shares offered, value of shares, etc. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", + "example": "https://example.com/image.png" }, - "account_type": { + "proof_of_ownership_doc_file": { "type": [ "string", "null" ], - "enum": [ - "checking", - "saving" - ], - "example": "checking" + "description": "Please upload your proof of ownership below. This document usually includes information like the shareholders names and percentages. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", + "example": "https://example.com/image.png" }, - "account_class": { + "source_of_funds_doc_type": { "type": [ "string", "null" ], "enum": [ - "individual", - "business" - ], - "example": "individual" - }, - "address_line_1": { - "type": [ - "string", - "null" - ], - "example": "Address line 1" - }, - "address_line_2": { - "type": [ - "string", - "null" + "business_income", + "gambling_proceeds", + "gifts", + "government_benefits", + "inheritance", + "investment_loans", + "pension_retirement", + "salary", + "sale_of_assets_real_estate", + "savings", + "esops", + "investment_proceeds", + "someone_else_funds" ], - "example": "Address line 2" + "example": "business_income" }, - "city": { + "source_of_funds_doc_file": { "type": [ "string", "null" ], - "example": "City" + "example": "https://example.com/image.png" }, - "state_province_region": { + "selfie_file": { "type": [ "string", "null" ], - "example": "State/Province/Region" + "description": "Only image files are accepted (.jpg, .jpeg, .png)", + "example": "https://example.com/image.png" }, - "country": { + "purpose_of_transactions": { "type": [ "string", "null" ], "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "US" - }, - "postal_code": { - "type": [ - "string", - "null" - ], - "example": "Postal code" - }, - "checkbook_account_id": { - "type": [ - "string", - "null" - ], - "example": "dc809ff8f4d3417d83e5697e76f0b88a" - }, - "checkbook_user_key": { - "type": [ - "string", - "null" - ], - "example": "d84fd0dc-3882-4de9-97f8-656730214619" - }, - "onemoney_external_account_id": { - "type": [ - "string", - "null" - ], - "example": "ex_000000000000" - }, - "pix_safe_bank_code": { - "type": [ - "string", - "null" - ], - "pattern": "^\\d{4,8}$", - "example": "00416968" - }, - "pix_safe_branch_code": { - "type": [ - "string", - "null" - ], - "pattern": "^\\d{4}(-\\d)?$", - "example": "0001" - }, - "pix_safe_cpf_cnpj": { - "type": [ - "string", - "null" - ], - "example": "12345678901" - }, - "ted_bank_code": { - "type": [ - "string", - "null" - ], - "pattern": "^\\d{3,5}$", - "example": "033" - }, - "ted_branch_code": { - "type": [ - "string", - "null" - ], - "pattern": "^\\d{4}(-\\d)?$", - "example": "0001" - }, - "ted_cpf_cnpj": { - "type": [ - "string", - "null" + "business_transactions", + "charitable_donations", + "investment_purposes", + "payments_to_friends_or_family_abroad", + "personal_or_living_expenses", + "protect_wealth", + "purchase_good_and_services", + "receive_payment_for_freelancing", + "receive_salary", + "other" ], - "example": "12345678901" + "example": "business_transactions" }, - "spei_protocol": { + "purpose_of_transactions_explanation": { "type": [ "string", "null" ], - "enum": [ - "clabe", - "debitcard", - "phonenum" - ], - "description": "For debitcard and phonenum the spei_institution_code is required", - "example": "clabe" + "example": "I am a business owner and I want to receive payments from my customers" }, - "spei_institution_code": { + "is_fbo": { "type": [ - "string", + "boolean", "null" ], - "minLength": 5, - "maxLength": 5, - "example": "40002" + "example": false }, - "spei_clabe": { + "is_nested": { "type": [ - "string", + "boolean", "null" ], - "example": "5482347403740546" + "description": "Set by BlindPay compliance for nested customers (fintechs and PSPs). Only first-party transactions are allowed; third-party payins and payouts are held for manual review.", + "example": false }, - "transfers_type": { + "account_purpose": { "type": [ "string", "null" ], "enum": [ - "CVU", - "CBU", - "ALIAS" + "charitable_donations", + "ecommerce_retail_payments", + "investment_purposes", + "business_expenses", + "payments_to_friends_or_family_abroad", + "personal_or_living_expenses", + "protect_wealth", + "purchase_goods_and_services", + "receive_payments_for_goods_and_services", + "tax_optimization", + "third_party_money_transmission", + "payroll", + "treasury_management", + "other" ], - "example": "CVU" + "example": "treasury_management" }, - "transfers_account": { + "account_purpose_other": { "type": [ "string", "null" ], - "example": "BM123123123123" + "maxLength": 512, + "description": "Required when account_purpose is \"other\". Max 512 characters.", + "example": "Custom account purpose description" }, - "ach_cop_beneficiary_first_name": { + "business_type": { "type": [ "string", "null" ], - "example": "Fernando" + "enum": [ + "corporation", + "llc", + "partnership", + "sole_proprietorship", + "trust", + "non_profit" + ], + "example": "llc" }, - "ach_cop_beneficiary_last_name": { + "business_description": { "type": [ "string", "null" ], - "example": "Guzman Alarcón" + "maxLength": 1000, + "example": "Software development company" }, - "ach_cop_document_id": { + "business_industry": { "type": [ "string", "null" ], - "example": "1661105408" + "example": "541511" }, - "ach_cop_document_type": { + "estimated_annual_revenue": { "type": [ "string", "null" ], "enum": [ - "CC", - "CE", - "NIT", - "PASS", - "PEP" + "0_99999", + "100000_999999", + "1000000_9999999", + "10000000_49999999", + "50000000_249999999", + "250000000_plus" ], - "description": "CC - Cédula de Ciudadanía; CE - Cédula de Extranjería; NIT - Número de Identificación Tributaria; PASS - Passport; PEP - Permiso Especial de Permanencia", - "example": "CC" + "example": "1000000_9999999" }, - "ach_cop_email": { + "source_of_wealth": { "type": [ "string", "null" ], - "example": "fernando.guzman@gmail.com" + "enum": [ + "business_dividends_or_profits", + "investments", + "asset_sales", + "client_investor_contributions", + "gambling", + "charitable_contributions", + "inheritance", + "affiliate_or_royalty_income", + "salary_or_wages", + "savings" + ], + "example": "affiliate_or_royalty_income" }, - "ach_cop_bank_code": { + "publicly_traded": { "type": [ - "string", + "boolean", "null" ], - "example": "051" + "example": false }, - "ach_cop_bank_account": { + "occupation": { "type": [ "string", "null" ], - "example": "12345678" + "maxLength": 255, + "example": "Software Engineer" }, - "swift_code_bic": { + "external_id": { "type": [ "string", "null" ], - "example": "123456789" + "example": "your_company_external_id" }, - "swift_account_holder_name": { + "instance_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "tos_id": { "type": [ "string", "null" ], - "maxLength": 50, - "example": "John Doe" + "minLength": 15, + "maxLength": 15, + "example": "to_000000000000" }, - "swift_account_number_iban": { + "aml_status": { "type": [ "string", "null" ], - "example": "123456789" + "enum": [ + "clear", + "hit", + "error" + ], + "description": "AML screening status from SEON. null = not yet screened.", + "example": "clear" }, - "swift_beneficiary_address_line_1": { + "aml_hits": { "type": [ - "string", + "object", "null" ], - "example": "123 MAIN STREET SUITE 100" + "properties": { + "has_sanction_match": { + "type": "boolean", + "default": false + }, + "has_pep_match": { + "type": "boolean", + "default": false + }, + "has_watchlist_match": { + "type": "boolean", + "default": false + }, + "has_crimelist_match": { + "type": "boolean", + "default": false + }, + "has_adversemedia_match": { + "type": "boolean", + "default": false + } + }, + "description": "AML screening match details from SEON.", + "example": { + "has_sanction_match": false, + "has_pep_match": false, + "has_watchlist_match": false, + "has_crimelist_match": false, + "has_adversemedia_match": false + } }, - "swift_beneficiary_address_line_2": { + "created_at": { "type": [ "string", "null" ], - "example": "BUILDING A FLOOR 5" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" }, - "swift_beneficiary_country": { + "updated_at": { "type": [ "string", "null" ], - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "MX" + "format": "date-time", + "example": "2021-01-01T00:00:00Z" }, - "swift_beneficiary_city": { + "limit": { + "type": "object", + "properties": { + "per_transaction": { + "type": [ + "number", + "null" + ], + "example": 100000 + }, + "daily": { + "type": [ + "number", + "null" + ], + "example": 200000 + }, + "monthly": { + "type": [ + "number", + "null" + ], + "example": 1000000 + } + }, + "required": [ + "per_transaction", + "daily", + "monthly" + ] + }, + "is_tos_accepted": { "type": [ - "string", + "boolean", "null" - ], - "example": "MEXICO CITY" + ] }, - "swift_beneficiary_state_province_region": { + "additional_info": { "type": [ - "string", + "array", "null" ], - "example": "MX" + "items": { + "$ref": "#/components/schemas/AdditionalInfoItem" + }, + "description": "Optional extra documents or notes for this customer. `label` is a known category, `value` is either a URL to upload or a free-text description. Any URLs are downloaded and re-hosted on Blindpay storage before being stored.", + "example": [ + { + "label": "EIN_LETTER", + "value": "https://example.com/ein.pdf" + }, + { + "label": "FLOW_OF_FUNDS", + "value": "Funds originate from US payroll deposits, forwarded weekly to customer." + } + ] }, - "swift_beneficiary_postal_code": { + "cnae_condition": { + "$ref": "#/components/schemas/CustomerCnaeCondition" + }, + "virtual_account_preapproval": { + "$ref": "#/components/schemas/CustomerVirtualAccountPreapproval" + } + }, + "required": [ + "id", + "customer_id", + "type", + "kyc_type", + "kyc_status", + "email", + "country", + "instance_id", + "limit" + ] + }, + "UpdateCustomerIn": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email", + "example": "email@example.com" + }, + "tax_id": { "type": [ "string", "null" ], - "example": "11530" + "example": "536804398" }, - "swift_bank_name": { + "address_line_1": { "type": [ "string", "null" ], - "example": "Banco Regional SA" + "example": "738 Plain St" }, - "swift_bank_address_line_1": { + "address_line_2": { "type": [ "string", "null" ], - "example": "123 Main Street, Suite 100, Downtown District, City Center CP 12345" + "example": "Building 22" }, - "swift_bank_address_line_2": { + "city": { "type": [ "string", "null" ], - "example": "456 Oak Avenue, Building 7, Financial District, Business Center CP 54321" + "example": "Marshfield" }, - "swift_bank_country": { + "state_province_region": { "type": [ "string", "null" ], + "example": "MA" + }, + "country": { + "type": "string", "enum": [ "AF", "AL", @@ -25514,71 +39399,111 @@ "ZW", "AX" ], - "example": "MX" + "example": "US" }, - "swift_bank_city": { + "postal_code": { "type": [ "string", "null" ], - "example": "City" + "example": "02050" }, - "swift_bank_state_province_region": { + "ip_address": { "type": [ "string", "null" ], - "example": "District" + "format": "ip", + "example": "127.0.0.1" }, - "swift_bank_postal_code": { + "latitude": { + "type": [ + "number", + "null" + ], + "minimum": -90, + "maximum": 90, + "description": "Optional geolocation latitude collected from the customer. Forwarded to AiPrise and SEON for fraud analysis.", + "example": 37.7749 + }, + "longitude": { + "type": [ + "number", + "null" + ], + "minimum": -180, + "maximum": 180, + "description": "Optional geolocation longitude collected from the customer. Forwarded to AiPrise and SEON for fraud analysis.", + "example": -122.4194 + }, + "image_url": { "type": [ "string", "null" ], - "example": "11530" + "format": "uri", + "example": "https://example.com/image.png" }, - "swift_ifsc_branch_code": { + "phone_number": { "type": [ "string", "null" ], - "pattern": "^[A-Z]{4}0[A-Z0-9]{6}$", - "example": "BARB0AHIMCI" + "example": "+13055555555" }, - "swift_intermediary_bank_swift_code_bic": { - "anyOf": [ - { - "type": "string", - "minLength": 8, - "maxLength": 8 - }, - { - "type": "string", - "minLength": 11, - "maxLength": 11 - }, - { - "type": "null" - } + "proof_of_address_doc_type": { + "type": [ + "string", + "null" ], - "example": "AEIBARB1" + "enum": [ + "UTILITY_BILL", + "BANK_STATEMENT", + "RENTAL_AGREEMENT", + "TAX_DOCUMENT", + "GOVERNMENT_CORRESPONDENCE" + ], + "example": "UTILITY_BILL" }, - "swift_intermediary_bank_account_number_iban": { + "proof_of_address_doc_file": { "type": [ "string", "null" ], - "maxLength": 34, - "example": "123456789" + "format": "uri", + "description": "Please upload one document that serve as proof of address, this needs to be the same physical address as the one provided above. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", + "example": "https://example.com/image.png" }, - "swift_intermediary_bank_name": { + "first_name": { "type": [ "string", "null" ], - "example": "Banco Regional SA" + "example": "John" }, - "swift_intermediary_bank_country": { + "last_name": { + "type": [ + "string", + "null" + ], + "example": "Doe" + }, + "date_of_birth": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "example": "1998-01-01T00:00:00Z" + }, + "id_doc_country": { "type": [ "string", "null" @@ -25834,323 +39759,875 @@ "ZW", "AX" ], - "example": "US" + "example": "BR" + }, + "id_doc_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "PASSPORT", + "ID_CARD", + "DRIVERS" + ], + "example": "PASSPORT" + }, + "id_doc_front_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "Only image files are accepted (.jpg, .jpeg, .png)", + "example": "https://example.com/image.png" + }, + "id_doc_back_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "Only image files are accepted (.jpg, .jpeg, .png)", + "example": "https://example.com/image.png" + }, + "legal_name": { + "type": [ + "string", + "null" + ], + "example": "Company Name Inc." + }, + "alternate_name": { + "type": [ + "string", + "null" + ], + "example": "Company Name Inc." + }, + "formation_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "example": "1998-01-01T00:00:00Z", + "format": "date-time" + }, + "website": { + "type": [ + "string", + "null" + ], + "format": "uri", + "example": "https://example.com" + }, + "owners": { + "type": [ + "array", + "null" + ], + "items": { + "type": "object", + "properties": { + "role": { + "type": "string", + "enum": [ + "beneficial_controlling", + "beneficial_owner", + "controlling_person" + ], + "description": "A beneficial owner is someone who directly or indirectly owns 25% or more of your business. A controlling person is someone with significant responsibility to control, manage or direct your business (typically a CEO, senior executive officer or equivalent).", + "example": "beneficial_owner" + }, + "first_name": { + "type": "string", + "minLength": 1, + "example": "John" + }, + "last_name": { + "type": "string", + "minLength": 1, + "example": "Doe" + }, + "date_of_birth": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + } + ], + "example": "1998-01-01T00:00:00Z" + }, + "tax_id": { + "type": "string", + "example": "536804398" + }, + "address_line_1": { + "type": "string", + "example": "738 Plain St" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "Building 22" + }, + "city": { + "type": "string", + "example": "Marshfield" + }, + "state_province_region": { + "type": "string", + "example": "MA" + }, + "country": { + "type": "string", + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "US" + }, + "postal_code": { + "type": "string", + "example": "02050" + }, + "id_doc_country": { + "type": "string", + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "BR" + }, + "id_doc_type": { + "type": "string", + "enum": [ + "PASSPORT", + "ID_CARD", + "DRIVERS" + ], + "example": "PASSPORT" + }, + "id_doc_front_file": { + "type": "string", + "format": "uri" + }, + "id_doc_back_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "Only image files are accepted (.jpg, .jpeg, .png)" + }, + "proof_of_address_doc_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "UTILITY_BILL", + "BANK_STATEMENT", + "RENTAL_AGREEMENT", + "TAX_DOCUMENT", + "GOVERNMENT_CORRESPONDENCE" + ], + "example": "UTILITY_BILL" + }, + "proof_of_address_doc_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "Please upload one document that serve as proof of address, this needs to be the same address as the one provided above. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB." + }, + "ownership_percentage": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "maximum": 100, + "description": "Ownership percentage of the beneficial owner (0-100)", + "example": 25 + }, + "title": { + "type": [ + "string", + "null" + ], + "maxLength": 128, + "description": "Job title of the owner", + "example": "CEO" + }, + "tax_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "SSN", + "ITIN" + ], + "description": "Tax identifier type. Mandatory when country is US; must be SSN or ITIN.", + "example": "SSN" + }, + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15 + } + }, + "required": [ + "id" + ] + } + }, + "incorporation_doc_file": { + "type": [ + "string", + "null" + ], + "format": "uri", + "description": "Please upload your articles of incorporation below. The articles of incorporation or a certificate of incorporation usually includes information like the company name, business purpose, number of shares offered, value of shares, etc. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", + "example": "https://example.com/image.png" }, - "sepa_iban": { + "proof_of_ownership_doc_file": { "type": [ "string", "null" ], - "example": "DE89370400440532013000" + "format": "uri", + "description": "Please upload your proof of ownership below. This document usually includes information like the shareholders names and percentages. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", + "example": "https://example.com/image.png" }, - "sepa_beneficiary_bic": { + "source_of_funds_doc_type": { "type": [ "string", "null" ], - "description": "BIC/SWIFT code of the beneficiary bank", - "example": "TRWIBEB1XXX" + "enum": [ + "business_income", + "gambling_proceeds", + "gifts", + "government_benefits", + "inheritance", + "investment_loans", + "pension_retirement", + "salary", + "sale_of_assets_real_estate", + "savings", + "esops", + "investment_proceeds", + "someone_else_funds" + ], + "example": "business_income" }, - "sepa_beneficiary_legal_name": { + "source_of_funds_doc_file": { "type": [ "string", "null" ], - "maxLength": 128, - "example": "Hans Müller" + "format": "uri", + "example": "https://example.com/image.png" }, - "sepa_beneficiary_address_line_1": { + "selfie_file": { "type": [ "string", "null" ], - "example": "Friedrichstraße 12" + "format": "uri", + "description": "Only image files are accepted (.jpg, .jpeg, .png)", + "example": "https://example.com/image.png" }, - "sepa_beneficiary_address_line_2": { + "purpose_of_transactions": { "type": [ "string", "null" ], - "example": "Apt 4B" + "enum": [ + "business_transactions", + "charitable_donations", + "investment_purposes", + "payments_to_friends_or_family_abroad", + "personal_or_living_expenses", + "protect_wealth", + "purchase_good_and_services", + "receive_payment_for_freelancing", + "receive_salary", + "other" + ], + "example": "business_transactions" }, - "sepa_beneficiary_city": { + "purpose_of_transactions_explanation": { "type": [ "string", "null" ], - "example": "Berlin" + "example": "I am a business owner and I want to receive payments from my customers" }, - "sepa_beneficiary_state_province_region": { + "account_purpose": { "type": [ "string", "null" ], - "example": "Berlin" + "enum": [ + "charitable_donations", + "ecommerce_retail_payments", + "investment_purposes", + "business_expenses", + "payments_to_friends_or_family_abroad", + "personal_or_living_expenses", + "protect_wealth", + "purchase_goods_and_services", + "receive_payments_for_goods_and_services", + "tax_optimization", + "third_party_money_transmission", + "payroll", + "treasury_management", + "other" + ], + "example": "treasury_management" }, - "sepa_beneficiary_postal_code": { + "account_purpose_other": { "type": [ "string", "null" ], - "example": "10117" + "maxLength": 512, + "description": "Required when account_purpose is \"other\". Max 512 characters.", + "example": "Custom account purpose description" }, - "sepa_beneficiary_country": { + "business_type": { "type": [ "string", "null" ], "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" + "corporation", + "llc", + "partnership", + "sole_proprietorship", + "trust", + "non_profit" ], - "example": "DE" + "example": "llc" + }, + "business_description": { + "type": [ + "string", + "null" + ], + "maxLength": 1000, + "example": "Software development company" }, "business_industry": { "type": [ @@ -26162,7 +40639,26 @@ "112120", "113310", "115114", + "111120", + "111219", + "111336", + "111421", + "112111", + "112210", + "112310", + "112410", + "112519", + "112990", + "113110", + "113210", + "114119", + "114210", + "115113", + "115210", + "115310", "541211", + "541213", + "541219", "541810", "541430", "541715", @@ -26172,10 +40668,29 @@ "561612", "561740", "561730", + "532490", + "533110", + "541490", + "541690", + "541720", + "561110", + "561210", + "561611", + "561990", + "722310", "236115", "236220", "237310", "238210", + "236118", + "236210", + "237130", + "237210", + "237990", + "238191", + "238391", + "238991", + "541310", "811111", "812111", "812112", @@ -26184,16 +40699,40 @@ "541922", "811210", "812199", + "532289", + "532310", + "561790", + "811198", + "811310", + "811411", + "812210", + "812320", + "812990", + "814110", "611110", "611310", "611410", "611710", + "611210", + "611420", + "611519", + "611699", "211120", "212114", "221310", "562111", "562920", "213112", + "211130", + "212290", + "212390", + "213113", + "221122", + "221210", + "221320", + "324110", + "562211", + "562998", "522110", "522210", "522320", @@ -26201,10 +40740,34 @@ "523940", "523999", "524113", + "521110", + "522130", + "522298", + "522390", + "523210", + "524128", + "524298", + "525190", + "525910", "813110", "813211", "813219", + "624190", + "624230", + "624310", + "813319", + "813410", + "813930", + "921140", + "922190", + "923130", + "924110", + "925120", + "926110", + "927110", + "928110", "551112", + "551114", "721110", "722511", "722513", @@ -26214,6 +40777,20 @@ "712110", "711110", "711211", + "487110", + "487210", + "487990", + "561599", + "711190", + "711219", + "711310", + "712120", + "713290", + "713990", + "721199", + "721211", + "721310", + "722410", "621111", "621210", "622110", @@ -26223,7 +40800,16 @@ "541940", "621399", "621910", + "621498", + "621610", + "621999", + "622210", + "622310", + "623210", + "623311", + "623990", "541110", + "541199", "311421", "337121", "322220", @@ -26240,12 +40826,93 @@ "315990", "313110", "339910", + "311119", + "311212", + "311314", + "311422", + "311511", + "311612", + "311710", + "311811", + "311999", + "312111", + "312230", + "313240", + "313310", + "314120", + "314999", + "315120", + "315250", + "316110", + "316210", + "316990", + "321113", + "321211", + "321918", + "322120", + "322299", + "323120", + "325180", + "325220", + "325320", + "325510", + "325611", + "325998", + "326111", + "326220", + "327120", + "327212", + "327310", + "327410", + "327999", + "331110", + "331210", + "331313", + "331410", + "331511", + "332111", + "332215", + "332311", + "332410", + "332510", + "332613", + "332710", + "332812", + "332999", + "333111", + "333248", + "333310", + "333413", + "333517", + "333611", + "333618", + "334310", + "334413", + "334511", + "334610", + "335131", + "335220", + "335311", + "335999", + "336211", + "336412", + "336510", + "336611", + "336999", + "337122", + "337214", + "337920", + "339999", "516120", "513130", "512250", "519130", + "519290", "711410", "711510", + "512199", + "512290", + "515210", "531110", "531120", "531130", @@ -26271,14 +40938,32 @@ "424210", "456110", "446120", + "456120", + "441110", + "441227", + "441330", + "444180", + "444240", + "445132", + "445298", + "449110", + "449129", + "454390", + "458320", + "459310", + "459410", + "459510", + "459999", "541511", "541512", "541519", "518210", "511210", + "513210", "517111", "517112", "517410", + "517810", "481111", "483111", "485210", @@ -26296,6 +40981,43 @@ "424410", "424480", "423940", + "423120", + "423220", + "423310", + "423490", + "423520", + "423620", + "423710", + "423990", + "424110", + "424310", + "424490", + "424590", + "424720", + "424820", + "425120", + "481211", + "482111", + "483112", + "483212", + "484110", + "484220", + "485119", + "485310", + "485410", + "485510", + "485999", + "486110", + "486210", + "486990", + "488190", + "488210", + "488390", + "488490", + "488999", + "492110", + "492210", + "493190", "541611", "541618", "541330", @@ -26305,385 +41027,437 @@ ], "example": "541511" }, - "phone_number": { + "estimated_annual_revenue": { "type": [ "string", "null" ], - "example": "+13055555555" + "enum": [ + "0_99999", + "100000_999999", + "1000000_9999999", + "10000000_49999999", + "50000000_249999999", + "250000000_plus" + ], + "example": "1000000_9999999" }, - "tax_id": { + "source_of_wealth": { "type": [ "string", "null" ], - "maxLength": 32, - "example": "536804398" + "enum": [ + "business_dividends_or_profits", + "investments", + "asset_sales", + "client_investor_contributions", + "gambling", + "charitable_contributions", + "inheritance", + "affiliate_or_royalty_income", + "salary_or_wages", + "savings" + ], + "example": "affiliate_or_royalty_income" }, - "date_of_birth": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "string" - }, - { - "type": "null" - } + "publicly_traded": { + "type": [ + "boolean", + "null" ], - "example": "1998-01-01T00:00:00Z" - } - }, - "required": [ - "type", - "name" - ] - }, - "VirtualAccountOut": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "va_000000000000" + "example": false }, - "banking_partner": { + "occupation": { "type": [ "string", "null" ], - "enum": [ - "jpmorgan", - "citi", - "hsbc", - "cfsb", - "portage", - "ssb" - ], - "example": "jpmorgan" + "maxLength": 255, + "example": "Software Engineer" }, - "kyc_status": { + "external_id": { "type": [ "string", "null" ], - "enum": [ - "verifying", - "approved", - "rejected", - "deprecated", - "pending_review", - "awaiting_contract", - "compliance_request", - "approved_rfi" + "example": "your_company_external_id" + }, + "tos_id": { + "type": [ + "string", + "null" ], - "example": "approved" + "minLength": 15, + "maxLength": 15, + "example": "to_000000000000" }, - "us": { + "additional_info": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/components/schemas/AdditionalInfoItem" + }, + "description": "Optional extra documents or notes for this customer. `label` is a known category, `value` is either a URL to upload or a free-text description. Any URLs are downloaded and re-hosted on Blindpay storage before being stored.", + "example": [ + { + "label": "EIN_LETTER", + "value": "https://example.com/ein.pdf" + }, + { + "label": "FLOW_OF_FUNDS", + "value": "Funds originate from US payroll deposits, forwarded weekly to customer." + } + ] + } + }, + "required": [ + "email", + "country" + ] + }, + "GetCustomerLimitsOut": { + "type": "object", + "properties": { + "limits": { "type": "object", "properties": { - "ach": { - "type": [ - "object", - "null" - ], + "payin": { + "type": "object", "properties": { - "routing_number": { - "type": "string", - "example": "123456789" + "daily": { + "type": "number" }, - "account_number": { - "type": "string", - "example": "123456789" + "monthly": { + "type": "number" } }, "required": [ - "routing_number", - "account_number" + "daily", + "monthly" ] }, - "wire": { + "payout": { "type": "object", "properties": { - "routing_number": { - "type": "string", - "example": "123456789" + "daily": { + "type": "number" }, - "account_number": { - "type": "string", - "example": "123456789" + "monthly": { + "type": "number" } }, "required": [ - "routing_number", - "account_number" + "daily", + "monthly" ] - }, - "rtp": { - "type": [ - "object", - "null" - ], - "properties": { - "routing_number": { - "type": "string", - "example": "123456789" - }, - "account_number": { - "type": "string", - "example": "123456789" - } + } + }, + "required": [ + "payin", + "payout" + ] + } + }, + "required": [ + "limits" + ], + "example": { + "limits": { + "payin": { + "daily": 500000, + "monthly": 2000000 + }, + "payout": { + "daily": 300000, + "monthly": 1000000 + } + } + } + }, + "RfiField": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "label": { + "type": "string", + "maxLength": 256 + }, + "regex": { + "type": "string", + "maxLength": 512 + }, + "required": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" }, - "required": [ - "routing_number", - "account_number" - ] - }, - "swift_bic_code": { - "type": [ - "string", - "null" - ], - "example": "TCCLGB3L" - }, - "swift_account_number": { - "type": [ - "string", - "null" - ], - "example": "GB50TCCL04140449730892" - }, - "account_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "Personal checking", - "Business checking" - ], - "default": "Business checking", - "example": "Business checking" + "value": { + "type": "string" + } }, - "beneficiary": { - "type": [ - "object", - "null" - ], - "properties": { - "name": { - "type": "string", - "example": "Customer Name" - }, - "address_line_1": { - "type": "string", - "example": "8 The Green, #19364" - }, - "address_line_2": { - "type": "string", - "example": "Dover, DE 19901" - } + "required": [ + "label", + "value" + ] + } + }, + "multiple": { + "type": "boolean" + }, + "aiprise_document_type": { + "type": "string", + "enum": [ + "ADDRESS_PROOF_DOCUMENT", + "SOURCE_OF_FUNDS_DOCUMENT", + "BANK_STATEMENT_DOCUMENT", + "USER_SELFIE", + "TAX_CERTIFICATE", + "VISA_DOCUMENT", + "OTHER" + ] + } + }, + "required": [ + "key", + "label", + "required" + ] + }, + "RfiSection": { + "type": "object", + "properties": { + "title": { + "type": "string", + "minLength": 1, + "maxLength": 256 + }, + "description": { + "type": "string", + "maxLength": 4096 + }, + "supporting_document": { + "type": "string", + "format": "uri" + }, + "fields": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RfiField" + }, + "minItems": 1, + "maxItems": 20 + } + }, + "required": [ + "title", + "description", + "fields" + ] + }, + "Rfi": { + "type": [ + "object", + "null" + ], + "properties": { + "id": { + "type": "string" + }, + "customer_id": { + "type": "string" + }, + "instance_id": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "pending", + "submitted", + "expired", + "cancelled" + ] + }, + "request": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RfiSection" + }, + "minItems": 1, + "maxItems": 20 + }, + "response": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string", + "maxLength": 4096 }, - "required": [ - "name", - "address_line_1", - "address_line_2" - ] - }, - "receiving_bank": { - "type": [ - "object", - "null" - ], - "properties": { - "name": { - "type": "string", - "example": "JPMorgan Chase" - }, - "address_line_1": { + { + "type": "array", + "items": { "type": "string", - "example": "270 Park Ave" - }, - "address_line_2": { - "type": [ - "string", - "null" - ], - "example": "New York, NY, 10017-2070" - } - }, - "required": [ - "name", - "address_line_1" - ] - }, - "swift_receiving_bank": { - "type": [ - "object", - "null" - ], - "properties": { - "name": { - "type": [ - "string", - "null" - ], - "example": "JPMorgan Chase" - }, - "address_line_1": { - "type": [ - "string", - "null" - ], - "example": "270 Park Ave" - }, - "address_line_2": { - "type": [ - "string", - "null" - ], - "example": "New York, NY, 10017-2070" - } - } - }, - "swift_intermediary_bank": { - "type": [ - "object", - "null" - ], - "properties": { - "name": { - "type": [ - "string", - "null" - ], - "example": "JP Morgan Chase NA" - }, - "swift_code_bic": { - "type": [ - "string", - "null" - ], - "example": "CHASUS33" - }, - "routing_number": { - "type": [ - "string", - "null" - ], - "example": "021000021" - }, - "address_line_1": { - "type": [ - "string", - "null" - ], - "example": "270 Park Ave" + "format": "uri" }, - "address_line_2": { - "type": [ - "string", - "null" - ], - "example": "New York, NY, 10017-2070" - } + "maxItems": 20 } - } - }, - "required": [ - "wire" - ] + ] + } }, - "token": { + "expires_at": { "type": "string", - "enum": [ - "USDC", - "USDT", - "USDB" - ], - "example": "USDC" + "format": "date-time" }, - "blockchain_wallet_id": { + "submitted_at": { "type": [ "string", "null" ], - "minLength": 15, - "maxLength": 15, - "example": "bw_000000000000" + "format": "date-time" }, - "blockchain_wallet": { + "created_at": { + "type": "string", + "format": "date-time" + }, + "customer_type": { + "type": "string", + "enum": [ + "individual", + "business" + ] + }, + "customer_aiprise_session_id": { "type": [ - "object", + "string", "null" - ], - "properties": { - "network": { - "type": "string", - "enum": [ - "base", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "arbitrum", - "polygon", - "polygon_amoy", - "ethereum", - "stellar", - "stellar_testnet", - "tron", - "solana", - "solana_devnet" - ], - "example": "polygon" - }, - "address": { - "type": [ - "string", - "null" - ], - "example": "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C" - } - }, - "required": [ - "network" ] }, - "customer_id": { + "customer_aiprise_user_profile_id": { "type": [ "string", "null" + ] + }, + "customer_kyc_status": { + "type": "string" + } + }, + "required": [ + "id", + "customer_id", + "instance_id", + "status", + "request", + "response", + "expires_at", + "submitted_at", + "created_at" + ] + }, + "YieldHistoryRowOut": { + "type": "object", + "properties": { + "date": { + "type": "string", + "format": "date", + "example": "2026-09-01" + }, + "token": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB" + ] + }, + "earning_amount": { + "type": "number", + "description": "Vault value net of accrued fees at the daily snapshot, in token units", + "example": 998.72 + }, + "earned_day": { + "type": "number", + "description": "Net yield earned between the previous snapshot and this one, in token units", + "example": 0.09 + }, + "apy": { + "type": [ + "number", + "null" ], - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" + "description": "APY after the performance fee on that day, as a fraction", + "example": 0.0291 + } + }, + "required": [ + "date", + "token", + "earning_amount", + "earned_day", + "apy" + ] + }, + "YieldHistoryOut": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/YieldHistoryRowOut" + } + } + }, + "required": [ + "data" + ] + }, + "YieldTransactionReference": { + "type": [ + "object", + "null" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "payout", + "transfer" + ], + "example": "payout" + }, + "id": { + "type": "string", + "example": "po_000000000000" } }, "required": [ - "id", - "banking_partner", - "kyc_status", - "us", - "token" - ] + "type", + "id" + ], + "description": "The payout or transfer this redeem funded, null otherwise" }, - "CreateVirtualAccountIn": { + "YieldTransactionOut": { "type": "object", "properties": { - "banking_partner": { + "id": { "type": "string", - "enum": [ - "jpmorgan", - "citi", - "hsbc", - "cfsb", - "portage", - "ssb" - ], - "example": "jpmorgan" + "minLength": 15, + "maxLength": 15, + "example": "yt_000000000000" }, "token": { "type": "string", @@ -26691,42 +41465,112 @@ "USDC", "USDT", "USDB" - ], - "example": "USDC" + ] }, - "blockchain_wallet_id": { + "type": { "type": "string", - "minLength": 15, - "maxLength": 15 + "enum": [ + "deposit", + "redeem", + "fee" + ], + "description": "deposit moves idle balance into the vault, redeem moves it back to the wallet, fee is a performance fee collection", + "example": "deposit" }, - "sole_proprietor_doc_type": { - "type": [ - "string", - "null" + "trigger": { + "type": "string", + "enum": [ + "sweep", + "payout", + "transfer", + "disable", + "fee_collection" ], + "example": "sweep" + }, + "reference": { + "$ref": "#/components/schemas/YieldTransactionReference" + }, + "status": { + "type": "string", "enum": [ - "master_service_agreement", - "salary_slip", - "bank_statement" + "pending", + "confirmed", + "failed" ], - "example": "master_service_agreement" + "example": "confirmed" }, - "sole_proprietor_doc_file": { + "amount": { + "type": "number", + "description": "In token units", + "example": 5000 + }, + "transaction_hash": { "type": [ "string", "null" ], - "format": "uri", - "example": "https://example.com/document.pdf" + "example": "0xabc…" + }, + "created_at": { + "type": "string", + "format": "date-time", + "example": "2026-09-01T10:02:00Z" } }, "required": [ - "banking_partner", + "id", "token", - "blockchain_wallet_id" + "type", + "trigger", + "reference", + "status", + "amount", + "transaction_hash", + "created_at" ] }, - "UpdateVirtualAccountIn": { + "YieldTransactionsOut": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/YieldTransactionOut" + } + }, + "pagination": { + "$ref": "#/components/schemas/PaginationMetadata" + } + }, + "required": [ + "data", + "pagination" + ] + }, + "YieldVaultOut": { + "type": "object", + "properties": { + "address": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "example": "0xC768c589647798a6EE01A91FdE98EF2ed046DBD6" + }, + "apy": { + "type": [ + "number", + "null" + ], + "description": "Vault APY before fees, as a fraction. Null when the source is unavailable.", + "example": 0.0342 + } + }, + "required": [ + "address", + "apy" + ] + }, + "YieldPositionOut": { "type": "object", "properties": { "token": { @@ -26738,5960 +41582,9276 @@ ], "example": "USDC" }, - "blockchain_wallet_id": { - "type": "string", - "minLength": 15, - "maxLength": 15 + "vault": { + "$ref": "#/components/schemas/YieldVaultOut" + }, + "apy": { + "type": [ + "number", + "null" + ], + "description": "APY the wallet earns after the performance fee, as a fraction. Null when the vault rate is unavailable.", + "example": 0.0291 + }, + "gross_amount": { + "type": "number", + "description": "Current vault value before fees, in token units", + "example": 1000.42 + }, + "fee_accrued": { + "type": "number", + "description": "Performance fee accrued on gains and not yet collected, in token units", + "example": 1.7 + }, + "earning_amount": { + "type": "number", + "description": "Current vault value net of accrued fees, in token units. This is the balance earning yield, not the profit.", + "example": 998.72 + }, + "max_withdrawable": { + "type": "number", + "description": "Amount the vault can return right now, in token units", + "example": 998.72 + }, + "total_deposited": { + "type": "number", + "description": "Lifetime deposits into the vault from this wallet, in token units", + "example": 950 + }, + "total_withdrawn": { + "type": "number", + "description": "Lifetime withdrawals back to this wallet, excluding fee collections, in token units", + "example": 0 + }, + "lifetime_earned_amount": { + "type": "number", + "description": "Lifetime net profit after fees, in token units, across every time yield was enabled on this wallet", + "example": 48.72 } }, "required": [ "token", - "blockchain_wallet_id" + "vault", + "apy", + "gross_amount", + "fee_accrued", + "earning_amount", + "max_withdrawable", + "total_deposited", + "total_withdrawn", + "lifetime_earned_amount" ] }, - "CreateCustomerIn": { + "YieldOut": { "type": "object", "properties": { - "type": { - "type": "string", - "enum": [ - "individual", - "business" - ], - "example": "individual" + "status": { + "$ref": "#/components/schemas/YieldStatus" }, - "kyc_type": { + "as_of": { "type": "string", - "enum": [ - "light", - "standard", - "enhanced" - ], - "example": "standard" + "format": "date-time", + "example": "2026-09-01T12:00:00Z" }, - "email": { - "type": "string", - "format": "email", - "example": "email@example.com" + "fee_bps": { + "type": "integer", + "description": "Performance fee on gains, basis points. Charged only on new gains above the previous high-water mark.", + "example": 1500 }, - "tax_id": { - "type": [ - "string", - "null" - ], - "example": "536804398" + "positions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/YieldPositionOut" + } + } + }, + "required": [ + "status", + "as_of", + "fee_bps", + "positions" + ] + }, + "InstanceRfi": { + "type": [ + "object", + "null" + ], + "properties": { + "id": { + "type": "string" }, - "address_line_1": { - "type": [ - "string", - "null" - ], - "example": "738 Plain St" + "instance_id": { + "type": "string" }, - "address_line_2": { - "type": [ - "string", - "null" - ], - "example": "Building 22" + "status": { + "type": "string", + "enum": [ + "pending", + "submitted", + "expired", + "cancelled" + ] }, - "city": { - "type": [ - "string", - "null" - ], - "example": "Marshfield" + "request": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RfiSection" + }, + "minItems": 1, + "maxItems": 20 }, - "state_province_region": { + "response": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string", + "maxLength": 4096 + }, + { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "maxItems": 20 + } + ] + } + }, + "expires_at": { + "type": "string", + "format": "date-time" + }, + "submitted_at": { "type": [ "string", "null" ], - "example": "MA" + "format": "date-time" }, - "country": { + "created_at": { "type": "string", - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "US" + "format": "date-time" + } + }, + "required": [ + "id", + "instance_id", + "status", + "request", + "response", + "expires_at", + "submitted_at", + "created_at" + ] + } + }, + "parameters": {} + }, + "paths": { + "/v1/instances/{instance_id}/onboarding/business_details": { + "get": { + "x-sdk": true, + "tags": [ + "Instances" + ], + "summary": "Retrieve Business Details", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Get business details", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "legal_name": { + "type": "string", + "example": "My Company" + }, + "tax_id": { + "type": "string", + "example": "000.000.000-00" + }, + "formation_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + } + ], + "example": "2020-04-23T00:00:00Z" + }, + "trading_names": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "example": [ + "Comercial Name" + ] + }, + "address_line_1": { + "type": "string", + "example": "5th Avenue" + }, + "address_line_2": { + "type": [ + "string", + "null" + ], + "example": "Building 1" + }, + "city": { + "type": "string", + "example": "New York" + }, + "state_province_region": { + "type": "string", + "example": "NY" + }, + "postal_code": { + "type": "string", + "example": "64101" + }, + "country": { + "type": "string", + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "BR" + }, + "entity_type": { + "type": "string", + "enum": [ + "cooperative", + "corporation", + "company", + "partnership", + "sole_proprietor", + "trust", + "other" + ], + "example": "company" + }, + "state_of_incorporation": { + "type": "string", + "example": "NY" + } + } + } + } + } }, - "postal_code": { - "type": [ - "string", - "null" - ], - "example": "02050" + "400": { + "description": "Possible error codes: `INSTANCES_TAX_ID_ALREADY_ONBOARDED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INSTANCES_TAX_ID_ALREADY_ONBOARDED": { + "summary": "INSTANCES_TAX_ID_ALREADY_ONBOARDED", + "value": { + "success": false, + "code": "INSTANCES_TAX_ID_ALREADY_ONBOARDED", + "message": "instance_already_exists_for_tax_id", + "description": "Your account already has an instance of this type onboarded with this tax id. Contact support if you need another one.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "ip_address": { - "type": [ - "string", - "null" - ], - "format": "ip", - "example": "127.0.0.1" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "latitude": { - "type": [ - "number", - "null" - ], - "minimum": -90, - "maximum": 90, - "description": "Optional geolocation latitude collected from the customer. Forwarded to AiPrise and SEON for fraud analysis.", - "example": 37.7749 + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "longitude": { - "type": [ - "number", - "null" - ], - "minimum": -180, - "maximum": 180, - "description": "Optional geolocation longitude collected from the customer. Forwarded to AiPrise and SEON for fraud analysis.", - "example": -122.4194 + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "image_url": { - "type": [ - "string", - "null" - ], - "format": "uri", - "example": "https://example.com/image.png" + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{instance_id}/onboarding/business_profile": { + "get": { + "x-sdk": true, + "tags": [ + "Instances" + ], + "summary": "Retrieve Business Profile", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Get business profile", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "scenario": { + "type": "string", + "enum": [ + "custodial", + "custodial_mtl", + "non_custodial", + "other" + ], + "example": "custodial" + }, + "scenario_description": { + "type": [ + "string", + "null" + ], + "example": "Scenario description" + }, + "has_kyc_screening": { + "type": [ + "boolean", + "null" + ], + "example": true + }, + "is_regulated": { + "type": [ + "boolean", + "null" + ], + "example": true + }, + "business_industry": { + "type": "string", + "enum": [ + "wallet", + "exchange", + "dapp", + "neo_bank", + "gaming", + "marketplace", + "saas", + "social", + "infra", + "gambling", + "other" + ], + "example": "wallet" + }, + "website": { + "type": [ + "string", + "null" + ], + "format": "uri", + "example": "https://domain.com" + }, + "top_volume_by_country": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ] + }, + "minItems": 1, + "example": [ + "BR" + ] + }, + "estimated_volume_per_month": { + "type": "string", + "enum": [ + "up_to_100", + "up_to_500", + "up_to_1000", + "up_to_10000", + "more_than_10000" + ], + "example": "up_to_1000" + } + } + } + } + } }, - "phone_number": { - "type": [ - "string", - "null" - ], - "example": "+13055555555" + "400": { + "description": "Possible error codes: `INSTANCES_TAX_ID_ALREADY_ONBOARDED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INSTANCES_TAX_ID_ALREADY_ONBOARDED": { + "summary": "INSTANCES_TAX_ID_ALREADY_ONBOARDED", + "value": { + "success": false, + "code": "INSTANCES_TAX_ID_ALREADY_ONBOARDED", + "message": "instance_already_exists_for_tax_id", + "description": "Your account already has an instance of this type onboarded with this tax id. Contact support if you need another one.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "proof_of_address_doc_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "UTILITY_BILL", - "BANK_STATEMENT", - "RENTAL_AGREEMENT", - "TAX_DOCUMENT", - "GOVERNMENT_CORRESPONDENCE" - ], - "example": "UTILITY_BILL" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "proof_of_address_doc_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Please upload one document that serve as proof of address, this needs to be the same physical address as the one provided above. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", - "example": "https://example.com/image.png" + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "first_name": { - "type": [ - "string", - "null" - ], - "example": "John" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{instance_id}/onboarding/ownership_documents": { + "get": { + "x-sdk": true, + "tags": [ + "Instances" + ], + "summary": "Retrieve Business Documents", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Get ownership documents", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "incorporation_doc_file": { + "type": [ + "string", + "null" + ] + }, + "proof_of_ownership_doc_file": { + "type": [ + "string", + "null" + ] + }, + "proof_of_address_doc_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "UTILITY_BILL", + "BANK_STATEMENT", + "RENTAL_AGREEMENT", + "TAX_DOCUMENT", + "GOVERNMENT_CORRESPONDENCE" + ], + "example": "UTILITY_BILL" + }, + "proof_of_address_doc_file": { + "type": [ + "string", + "null" + ] + }, + "owners": { + "type": [ + "array", + "null" + ], + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "ow_000000000000" + }, + "instance_id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "role": { + "type": "string", + "enum": [ + "beneficial_controlling", + "beneficial_owner", + "controlling_person" + ], + "example": "beneficial_owner" + }, + "first_name": { + "type": "string", + "minLength": 1, + "example": "John" + }, + "last_name": { + "type": "string", + "minLength": 1, + "example": "Doe" + }, + "ownership_percentage": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "maximum": 100 + }, + "date_of_birth": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + } + ], + "example": "1998-01-01T00:00:00Z" + }, + "tax_id": { + "type": "string", + "example": "536804398" + }, + "address_line_1": { + "type": "string", + "example": "738 Plain St" + }, + "address_line_2": { + "type": [ + "string", + "null" + ] + }, + "city": { + "type": "string", + "example": "Marshfield" + }, + "state_province_region": { + "type": "string", + "example": "MA" + }, + "country": { + "type": "string", + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "US" + }, + "postal_code": { + "type": "string", + "example": "02050" + }, + "id_doc_country": { + "type": "string", + "enum": [ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "CV", + "KH", + "CM", + "CA", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CD", + "CG", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "SZ", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KP", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "MK", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "UM", + "US", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX" + ], + "example": "BR" + }, + "id_doc_type": { + "type": "string", + "enum": [ + "PASSPORT", + "ID_CARD", + "DRIVERS" + ], + "example": "PASSPORT" + }, + "id_doc_front_file": { + "type": [ + "string", + "null" + ], + "format": "uri" + }, + "id_doc_back_file": { + "type": [ + "string", + "null" + ], + "format": "uri" + }, + "proof_of_address_doc_type": { + "type": [ + "string", + "null" + ], + "enum": [ + "UTILITY_BILL", + "BANK_STATEMENT", + "RENTAL_AGREEMENT", + "TAX_DOCUMENT", + "GOVERNMENT_CORRESPONDENCE" + ] + }, + "proof_of_address_doc_file": { + "type": [ + "string", + "null" + ] + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Possible error codes: `CUSTOMERS_ONBOARDING_INCOMPLETE`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_ONBOARDING_INCOMPLETE": { + "summary": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "value": { + "success": false, + "code": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "message": "onboarding_incomplete", + "description": "Onboarding is not complete yet. Finish the remaining steps before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "last_name": { - "type": [ - "string", - "null" - ], - "example": "Doe" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "date_of_birth": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "string" - }, - { - "type": "null" + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } } - ], - "example": "1998-01-01T00:00:00Z" + } }, - "id_doc_country": { - "type": [ - "string", - "null" - ], - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "BR" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "id_doc_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "PASSPORT", - "ID_CARD", - "DRIVERS" - ], - "example": "PASSPORT" + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{id}": { + "get": { + "x-sdk": true, + "tags": [ + "Instances" + ], + "summary": "Retrieve Instance", + "description": "Returns the instance your API key or connection is bound to. Check `type` before moving money: `development` simulates settlement and moves no real funds, `production` moves real funds. `onboarding_step` is `completed` once the instance can transact.", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Retrieve instance", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RetrieveInstanceOut" + } + } + } }, - "id_doc_front_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Only image files are accepted (.jpg, .jpeg, .png)", - "example": "https://example.com/image.png" + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "id_doc_back_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Only image files are accepted (.jpg, .jpeg, .png)", - "example": "https://example.com/image.png" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "legal_name": { - "type": [ - "string", - "null" - ], - "example": "Company Name Inc." + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "alternate_name": { - "type": [ - "string", - "null" - ], - "example": "Company Name Inc." + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "formation_date": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "string" - }, - { - "type": "null" + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } } - ], - "example": "1998-01-01T00:00:00Z", - "format": "date-time" + } + } + } + }, + "put": { + "x-sdk": true, + "tags": [ + "Instances" + ], + "summary": "Update Instance", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "id", + "in": "path" }, - "website": { - "type": [ - "string", - "null" - ], - "format": "uri", - "example": "https://example.com" + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" + } + ], + "requestBody": { + "description": "Update instance", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateInstanceIn" + } + } + } + }, + "responses": { + "200": { + "description": "Instance updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } }, - "owners": { - "type": [ - "array", - "null" - ], - "items": { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "beneficial_controlling", - "beneficial_owner", - "controlling_person" - ], - "description": "A beneficial owner is someone who directly or indirectly owns 25% or more of your business. A controlling person is someone with significant responsibility to control, manage or direct your business (typically a CEO, senior executive officer or equivalent).", - "example": "beneficial_owner" - }, - "first_name": { - "type": "string", - "minLength": 1, - "example": "John" - }, - "last_name": { - "type": "string", - "minLength": 1, - "example": "Doe" + "400": { + "description": "Possible error codes: `FILES_URL_INVALID`, `TOS_PASSTHROUGH_SETUP_INCOMPLETE`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "date_of_birth": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "string" + "examples": { + "FILES_URL_INVALID": { + "summary": "FILES_URL_INVALID", + "value": { + "success": false, + "code": "FILES_URL_INVALID", + "message": "file_url_invalid", + "description": "The file_url is not a BlindPay file URL. Pass the file_url returned by POST /upload.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" } - ], - "example": "1998-01-01T00:00:00Z" - }, - "tax_id": { - "type": "string", - "example": "536804398" - }, - "address_line_1": { - "type": "string", - "example": "738 Plain St" - }, - "address_line_2": { - "type": [ - "string", - "null" - ], - "example": "Building 22" + }, + "TOS_PASSTHROUGH_SETUP_INCOMPLETE": { + "summary": "TOS_PASSTHROUGH_SETUP_INCOMPLETE", + "value": { + "success": false, + "code": "TOS_PASSTHROUGH_SETUP_INCOMPLETE", + "message": "passthrough_tos_setup_incomplete", + "description": "Finish the passthrough Terms of Service setup in the instance settings: add the terms link and screenshot, then accept the partner agreement.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "city": { - "type": "string", - "example": "Marshfield" + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`, `TOS_PASSTHROUGH_NOT_ENABLED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "state_province_region": { - "type": "string", - "example": "MA" + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "TOS_PASSTHROUGH_NOT_ENABLED": { + "summary": "TOS_PASSTHROUGH_NOT_ENABLED", + "value": { + "success": false, + "code": "TOS_PASSTHROUGH_NOT_ENABLED", + "message": "passthrough_tos_not_enabled", + "description": "Passthrough Terms of Service is not enabled for this instance. Contact support to enable it.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "country": { - "type": "string", - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "US" + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "postal_code": { - "type": "string", - "example": "02050" + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + }, + "delete": { + "x-sdk": true, + "x-mcp": false, + "tags": [ + "Instances" + ], + "summary": "Delete Instance", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "id", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" + } + ], + "responses": { + "200": { + "description": "Instance deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + }, + "400": { + "description": "Possible error codes: `AUTH_FORBIDDEN`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "id_doc_country": { - "type": "string", - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "BR" + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{id}/members": { + "get": { + "x-sdk": true, + "tags": [ + "Instances" + ], + "summary": "Retrieve Instance Members", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Retrieve instance members", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "us_000000000000" + }, + "email": { + "type": "string", + "format": "email", + "example": "email@example.com" + }, + "first_name": { + "type": "string", + "minLength": 1, + "maxLength": 100, + "example": "Harry" + }, + "middle_name": { + "type": [ + "string", + "null" + ], + "minLength": 1, + "maxLength": 100, + "example": "James" + }, + "last_name": { + "type": "string", + "minLength": 1, + "maxLength": 100, + "example": "Potter" + }, + "image_url": { + "type": "string", + "format": "uri", + "example": "https://example.com/image.png" + }, + "created_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "example": "2021-01-01T00:00:00Z" + }, + "has_passkey": { + "type": [ + "boolean", + "null" + ], + "example": true + }, + "role": { + "type": "string", + "enum": [ + "owner", + "admin", + "finance", + "checker", + "operations", + "developer", + "viewer" + ], + "example": "admin" + } + }, + "required": [ + "id", + "email", + "first_name", + "last_name", + "image_url", + "role" + ] + } + } + } + } + }, + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "id_doc_type": { - "type": "string", - "enum": [ - "PASSPORT", - "ID_CARD", - "DRIVERS" - ], - "example": "PASSPORT" + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "id_doc_front_file": { - "type": "string", - "format": "uri" + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "id_doc_back_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Only image files are accepted (.jpg, .jpeg, .png)" + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "proof_of_address_doc_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "UTILITY_BILL", - "BANK_STATEMENT", - "RENTAL_AGREEMENT", - "TAX_DOCUMENT", - "GOVERNMENT_CORRESPONDENCE" - ], - "example": "UTILITY_BILL" + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "proof_of_address_doc_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Please upload one document that serve as proof of address, this needs to be the same address as the one provided above. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB." + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{id}/members/{user_id}": { + "delete": { + "x-sdk": true, + "tags": [ + "Instances" + ], + "summary": "Delete Member from Instance", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "user_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" + } + ], + "responses": { + "200": { + "description": "Member deleted from instance successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + }, + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "ownership_percentage": { - "type": [ - "integer", - "null" - ], - "minimum": 0, - "maximum": 100, - "description": "Ownership percentage of the beneficial owner (0-100)", - "example": 25 + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "title": { - "type": [ - "string", - "null" - ], - "maxLength": 128, - "description": "Job title of the owner", - "example": "CEO" + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "tax_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "SSN", - "ITIN" - ], - "description": "Tax identifier type. Mandatory when country is US; must be SSN or ITIN.", - "example": "SSN" + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } } - }, - "required": [ - "role", - "first_name", - "last_name", - "date_of_birth", - "tax_id", - "address_line_1", - "city", - "state_province_region", - "country", - "postal_code", - "id_doc_country", - "id_doc_type", - "id_doc_front_file" - ] + } } }, - "incorporation_doc_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Please upload your articles of incorporation below. The articles of incorporation or a certificate of incorporation usually includes information like the company name, business purpose, number of shares offered, value of shares, etc. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", - "example": "https://example.com/image.png" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "proof_of_ownership_doc_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Please upload your proof of ownership below. This document usually includes information like the shareholders names and percentages. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", - "example": "https://example.com/image.png" + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + }, + "put": { + "x-sdk": true, + "tags": [ + "Instances" + ], + "summary": "Update Instance Member Role", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" }, - "source_of_funds_doc_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "business_income", - "gambling_proceeds", - "gifts", - "government_benefits", - "inheritance", - "investment_loans", - "pension_retirement", - "salary", - "sale_of_assets_real_estate", - "savings", - "esops", - "investment_proceeds", - "someone_else_funds" - ], - "example": "business_income" + { + "schema": { + "type": "string" + }, + "required": true, + "name": "user_id", + "in": "path" }, - "source_of_funds_doc_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "example": "https://example.com/image.png" + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" + } + ], + "requestBody": { + "description": "Update instance member role", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateInstanceMemberIn" + } + } + } + }, + "responses": { + "200": { + "description": "Member role updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + }, + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "selfie_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Only image files are accepted (.jpg, .jpeg, .png)", - "example": "https://example.com/image.png" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "purpose_of_transactions": { - "type": [ - "string", - "null" - ], - "enum": [ - "business_transactions", - "charitable_donations", - "investment_purposes", - "payments_to_friends_or_family_abroad", - "personal_or_living_expenses", - "protect_wealth", - "purchase_good_and_services", - "receive_payment_for_freelancing", - "receive_salary", - "other" - ], - "example": "business_transactions" + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "purpose_of_transactions_explanation": { - "type": [ - "string", - "null" - ], - "example": "I am a business owner and I want to receive payments from my customers" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "account_purpose": { - "type": [ - "string", - "null" - ], - "enum": [ - "charitable_donations", - "ecommerce_retail_payments", - "investment_purposes", - "business_expenses", - "payments_to_friends_or_family_abroad", - "personal_or_living_expenses", - "protect_wealth", - "purchase_goods_and_services", - "receive_payments_for_goods_and_services", - "tax_optimization", - "third_party_money_transmission", - "payroll", - "treasury_management", - "other" - ], - "example": "treasury_management" + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{id}/ownership": { + "post": { + "x-sdk": true, + "x-mcp": false, + "tags": [ + "Instances" + ], + "summary": "Migrate Instance Ownership", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "id", + "in": "path" }, - "account_purpose_other": { - "type": [ - "string", - "null" - ], - "maxLength": 512, - "description": "Required when account_purpose is \"other\". Max 512 characters.", - "example": "Custom account purpose description" + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" + } + ], + "requestBody": { + "description": "Transfer instance ownership to another current member", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MigrateInstanceOwnershipIn" + } + } + } + }, + "responses": { + "200": { + "description": "Ownership transferred", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } }, - "business_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "corporation", - "llc", - "partnership", - "sole_proprietorship", - "trust", - "non_profit" - ], - "example": "llc" + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "business_description": { - "type": [ - "string", - "null" - ], - "maxLength": 1000, - "example": "Software development company" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "business_industry": { - "type": [ - "string", - "null" - ], - "enum": [ - "111998", - "112120", - "113310", - "115114", - "541211", - "541810", - "541430", - "541715", - "541930", - "561422", - "561311", - "561612", - "561740", - "561730", - "236115", - "236220", - "237310", - "238210", - "811111", - "812111", - "812112", - "532111", - "624410", - "541922", - "811210", - "812199", - "611110", - "611310", - "611410", - "611710", - "211120", - "212114", - "221310", - "562111", - "562920", - "213112", - "522110", - "522210", - "522320", - "523150", - "523940", - "523999", - "524113", - "813110", - "813211", - "813219", - "551112", - "721110", - "722511", - "722513", - "561510", - "713110", - "713210", - "712110", - "711110", - "711211", - "621111", - "621210", - "622110", - "623110", - "621511", - "623220", - "541940", - "621399", - "621910", - "541110", - "311421", - "337121", - "322220", - "339920", - "334210", - "339930", - "312130", - "334111", - "334118", - "325412", - "339112", - "336110", - "336390", - "315990", - "313110", - "339910", - "516120", - "513130", - "512250", - "519130", - "711410", - "711510", - "531110", - "531120", - "531130", - "531190", - "531210", - "531311", - "531312", - "531320", - "531390", - "454110", - "445110", - "455110", - "457110", - "449210", - "444110", - "459210", - "459120", - "445320", - "458110", - "458210", - "458310", - "455219", - "424210", - "456110", - "446120", - "541511", - "541512", - "541519", - "518210", - "511210", - "517111", - "517112", - "517410", - "481111", - "483111", - "485210", - "488510", - "484121", - "493110", - "423430", - "423690", - "423110", - "423830", - "423840", - "423510", - "424690", - "424990", - "424410", - "424480", - "423940", - "541611", - "541618", - "541330", - "541990", - "541214", - "561499" - ], - "example": "541511" + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "estimated_annual_revenue": { - "type": [ - "string", - "null" - ], - "enum": [ - "0_99999", - "100000_999999", - "1000000_9999999", - "10000000_49999999", - "50000000_249999999", - "250000000_plus" - ], - "example": "1000000_9999999" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "source_of_wealth": { - "type": [ - "string", - "null" - ], - "enum": [ - "business_dividends_or_profits", - "investments", - "asset_sales", - "client_investor_contributions", - "gambling", - "charitable_contributions", - "inheritance", - "affiliate_or_royalty_income" - ], - "example": "affiliate_or_royalty_income" + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{instance_id}/rfi": { + "get": { + "x-sdk": true, + "tags": [ + "Instances" + ], + "summary": "Get Open RFI for Instance", + "description": "Returns the open (pending) RFI for this instance, or null if the instance has no pending RFI.", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Open instance RFI, or null if none", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstanceRfi" + } + } + } }, - "publicly_traded": { - "type": [ - "boolean", - "null" - ], - "example": false + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "occupation": { - "type": [ - "string", - "null" - ], - "maxLength": 255, - "example": "Software Engineer" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "external_id": { - "type": [ - "string", - "null" - ], - "example": "your_company_external_id" + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "tos_id": { - "type": [ - "string", - "null" - ], - "minLength": 15, - "maxLength": 15, - "example": "to_000000000000" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "additional_info": { - "type": [ - "array", - "null" - ], - "items": { - "$ref": "#/components/schemas/AdditionalInfoItem" + "500": { + "description": "Possible error codes: `COMPLIANCE_RFI_INVALID`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "COMPLIANCE_RFI_INVALID": { + "summary": "COMPLIANCE_RFI_INVALID", + "value": { + "success": false, + "code": "COMPLIANCE_RFI_INVALID", + "message": "rfi_request_corrupt", + "description": "The information request could not be processed. Check the submitted fields.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + }, + "post": { + "x-sdk": true, + "tags": [ + "Instances" + ], + "summary": "Submit Instance RFI Response", + "description": "Submit a flat response object for the open instance RFI. Standalone: submitting does not change any instance or onboarding status. Returns `{ success: false, reason }` when no pending RFI exists, callers should refetch the RFI state instead of retrying.", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" }, - "description": "Optional extra documents or notes for this customer. `label` is a known category, `value` is either a URL to upload or a free-text description. Any URLs are downloaded and re-hosted on Blindpay storage before being stored.", - "example": [ - { - "label": "EIN_LETTER", - "value": "https://example.com/ein.pdf" - }, - { - "label": "FLOW_OF_FUNDS", - "value": "Funds originate from US payroll deposits, forwarded weekly to customer." + "required": true, + "name": "instance_id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": {} } - ] + } } }, - "required": [ - "type", - "kyc_type", - "email", - "country" - ] - }, - "CustomerOut": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" - }, - "customer_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" - }, - "type": { - "type": "string", - "enum": [ - "individual", - "business" - ], - "example": "individual" + "responses": { + "200": { + "description": "RFI submitted (success: true) or rejected because no pending RFI exists (success: false)", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "required": [ + "success" + ] + }, + { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + false + ] + }, + "reason": { + "type": "string", + "enum": [ + "no_pending_rfi", + "already_resolved" + ] + } + }, + "required": [ + "success", + "reason" + ] + } + ] + } + } + } }, - "kyc_type": { - "type": "string", - "enum": [ - "light", - "standard", - "enhanced" - ], - "example": "standard" + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "kyc_status": { - "type": "string", - "enum": [ - "verifying", - "approved", - "rejected", - "deprecated", - "pending_review", - "awaiting_contract", - "compliance_request", - "approved_rfi" - ], - "example": "verifying" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "kyc_warnings": { - "type": [ - "array", - "null" - ], - "items": { - "type": "object", - "properties": { - "code": { - "type": [ - "string", - "null" - ] + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "message": { - "type": [ - "string", - "null" - ] + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "resolution_status": { - "type": [ - "string", - "null" - ] + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "500": { + "description": "Possible error codes: `COMPLIANCE_RFI_INVALID`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "warning_id": { - "type": [ - "string", - "null" - ] + "examples": { + "COMPLIANCE_RFI_INVALID": { + "summary": "COMPLIANCE_RFI_INVALID", + "value": { + "success": false, + "code": "COMPLIANCE_RFI_INVALID", + "message": "rfi_request_corrupt", + "description": "The information request could not be processed. Check the submitted fields.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } } } - }, - "description": "You can find more information here: https://docs.aiprise.com/docs/warnings-and-error-codes", - "example": [ - { - "code": "BIRTH_DATE_MISMATCH", - "message": "Mismatch between supplied birth date and extracted/looked up birth date.", - "resolution_status": "UNRESOLVED", - "warning_id": "38170889-50aa-4271-9eb1-61113ebf408c" + } + } + } + } + }, + "/v1/e/instances/{instance_id}/tos": { + "post": { + "x-sdk": true, + "tags": [ + "Terms Of Service" + ], + "summary": "Initiate Terms of Service", + "description": "Returns a URL where the end customer accepts BlindPay's terms of service. A person must open it in a browser and accept; it cannot be accepted through the API. After acceptance the browser is sent to redirect_url with tos_id as a query parameter, and a tos.accept webhook fires. Pass that tos_id (to_...) to Create Customer. idempotency_key is any unique string and cannot be reused.", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + } + ], + "requestBody": { + "description": "Initiate a new terms of service", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InitiateTosIn" + } + } + } + }, + "responses": { + "200": { + "description": "Initiate terms of service", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InitiateTosOut" + } } - ] + } }, - "fraud_warnings": { - "type": [ - "array", - "null" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "operation": { - "type": [ - "string", - "null" - ] + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "score": { - "type": [ - "number", - "null" - ] + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } } } - }, - "example": [ - { - "id": "UC114", - "name": "User never used a Datacenter proxy and this device before", - "operation": "+", - "score": 10 - } - ] - }, - "email": { - "type": "string", - "format": "email", - "example": "email@example.com" - }, - "tax_id": { - "type": [ - "string", - "null" - ], - "example": "536804398" - }, - "address_line_1": { - "type": [ - "string", - "null" - ], - "example": "738 Plain St" - }, - "address_line_2": { - "type": [ - "string", - "null" - ], - "example": "Building 22" - }, - "city": { - "type": [ - "string", - "null" - ], - "example": "Marshfield" - }, - "state_province_region": { - "type": [ - "string", - "null" - ], - "example": "MA" - }, - "country": { - "type": "string", - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "US" - }, - "postal_code": { - "type": [ - "string", - "null" - ], - "example": "02050" - }, - "ip_address": { - "type": [ - "string", - "null" - ], - "format": "ip", - "example": "127.0.0.1" + } }, - "latitude": { - "type": [ - "number", - "null" - ], - "minimum": -90, - "maximum": 90, - "description": "Optional geolocation latitude collected from the customer. Forwarded to AiPrise and SEON for fraud analysis.", - "example": 37.7749 + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "longitude": { - "type": [ - "number", - "null" - ], - "minimum": -180, - "maximum": 180, - "description": "Optional geolocation longitude collected from the customer. Forwarded to AiPrise and SEON for fraud analysis.", - "example": -122.4194 + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "image_url": { - "type": [ - "string", - "null" - ], - "example": "https://example.com/image.png" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "phone_number": { - "type": [ - "string", - "null" - ], - "example": "+13055555555" + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{instance_id}/tos/passthrough": { + "post": { + "x-sdk": false, + "x-mcp": false, + "tags": [ + "Terms Of Service" + ], + "summary": "Create Passthrough Terms of Service Acceptance", + "description": "For instances with passthrough Terms of Service enabled that collect the acceptance on their own page. Call it from your server right after the customer accepts, with the IP address and User-Agent collected from the customer browser, and use the returned tos_id when creating the customer. The acceptance time is recorded when BlindPay receives the request. Submissions are validated and monitored as set out in the Passthrough Terms of Service Partner Agreement (https://blindpay.com/passthrough-tos-partner-agreement).", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + } + ], + "requestBody": { + "description": "Terms of service acceptance collected on the partner page", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreatePassthroughTosIn" + } + } + } + }, + "responses": { + "200": { + "description": "Terms of service acceptance recorded", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcceptTosOut" + } + } + } }, - "proof_of_address_doc_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "UTILITY_BILL", - "BANK_STATEMENT", - "RENTAL_AGREEMENT", - "TAX_DOCUMENT", - "GOVERNMENT_CORRESPONDENCE" - ], - "example": "UTILITY_BILL" + "400": { + "description": "Possible error codes: `TOS_PASSTHROUGH_ATTESTATION_INVALID`, `TOS_PASSTHROUGH_SETUP_INCOMPLETE`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "TOS_PASSTHROUGH_ATTESTATION_INVALID": { + "summary": "TOS_PASSTHROUGH_ATTESTATION_INVALID", + "value": { + "success": false, + "code": "TOS_PASSTHROUGH_ATTESTATION_INVALID", + "message": "passthrough_tos_attestation_invalid", + "description": "The acceptance data does not look like it was collected from the customer device. Send the public IP address and the User-Agent of the customer browser, right after the acceptance.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "TOS_PASSTHROUGH_SETUP_INCOMPLETE": { + "summary": "TOS_PASSTHROUGH_SETUP_INCOMPLETE", + "value": { + "success": false, + "code": "TOS_PASSTHROUGH_SETUP_INCOMPLETE", + "message": "passthrough_tos_setup_incomplete", + "description": "Finish the passthrough Terms of Service setup in the instance settings: add the terms link and screenshot, then accept the partner agreement.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "proof_of_address_doc_file": { - "type": [ - "string", - "null" - ], - "description": "Please upload one document that serve as proof of address, this needs to be the same physical address as the one provided above. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", - "example": "https://example.com/image.png" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "first_name": { - "type": [ - "string", - "null" - ], - "example": "John" + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`, `TOS_PASSTHROUGH_NOT_ENABLED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "TOS_PASSTHROUGH_NOT_ENABLED": { + "summary": "TOS_PASSTHROUGH_NOT_ENABLED", + "value": { + "success": false, + "code": "TOS_PASSTHROUGH_NOT_ENABLED", + "message": "passthrough_tos_not_enabled", + "description": "Passthrough Terms of Service is not enabled for this instance. Contact support to enable it.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "last_name": { - "type": [ - "string", - "null" - ], - "example": "Doe" + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "date_of_birth": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "string" - }, - { - "type": "null" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } } - ], - "example": "1998-01-01T00:00:00Z" + } }, - "id_doc_country": { - "type": [ - "string", - "null" - ], - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "BR" + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{instance_id}/customers/{customer_id}/limit-increase": { + "post": { + "x-sdk": true, + "tags": [ + "Customers" + ], + "summary": "Request Limit Increase", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" }, - "id_doc_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "PASSPORT", - "ID_CARD", - "DRIVERS" - ], - "example": "PASSPORT" + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" }, - "id_doc_front_file": { - "type": [ - "string", - "null" - ], - "description": "Only image files are accepted (.jpg, .jpeg, .png)", - "example": "https://example.com/image.png" + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" + } + ], + "requestBody": { + "description": "Request new limit increase", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerLimitIncreaseIn" + } + } + } + }, + "responses": { + "200": { + "description": "Create customer limit increase", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerLimitIncreaseOut" + } + } + } }, - "id_doc_back_file": { - "type": [ - "string", - "null" - ], - "description": "Only image files are accepted (.jpg, .jpeg, .png)", - "example": "https://example.com/image.png" + "400": { + "description": "Possible error codes: `CUSTOMERS_KYC_NOT_APPROVED`, `FILES_TOO_LARGE`, `FILES_TYPE_NOT_ALLOWED`, `FILES_UNREADABLE`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_KYC_NOT_APPROVED": { + "summary": "CUSTOMERS_KYC_NOT_APPROVED", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_NOT_APPROVED", + "message": "kyc_not_approved", + "description": "This customer has not completed verification yet. Complete the verification before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TYPE_NOT_ALLOWED": { + "summary": "FILES_TYPE_NOT_ALLOWED", + "value": { + "success": false, + "code": "FILES_TYPE_NOT_ALLOWED", + "message": "file_type_not_allowed", + "description": "This file type is not allowed. Upload a supported file type.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "legal_name": { - "type": [ - "string", - "null" - ], - "example": "Company Name Inc." + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "alternate_name": { - "type": [ - "string", - "null" - ], - "example": "Company Name Inc." + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "formation_date": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "string" - }, - { - "type": "null" + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } } - ], - "example": "1998-01-01T00:00:00Z", - "format": "date-time" + } }, - "website": { - "type": [ - "string", - "null" - ], - "format": "uri", - "example": "https://example.com" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "owners": { - "type": [ - "array", - "null" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "ub_000000000000" + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "instance_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + }, + "get": { + "x-sdk": true, + "tags": [ + "Customers" + ], + "summary": "Retrieve Limit Increase Requests", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "List customer limit increase requests", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GetCustomerLimitIncreaseOut" + } + } + } + } + }, + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "customer_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "role": { - "type": "string", - "enum": [ - "beneficial_controlling", - "beneficial_owner", - "controlling_person" - ], - "description": "A beneficial owner is someone who directly or indirectly owns 25% or more of your business. A controlling person is someone with significant responsibility to control, manage or direct your business (typically a CEO, senior executive officer or equivalent).", - "example": "beneficial_owner" + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "first_name": { - "type": "string", - "minLength": 1, - "example": "John" + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "last_name": { - "type": "string", - "minLength": 1, - "example": "Doe" + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "date_of_birth": { - "anyOf": [ - { - "type": "string", - "format": "date-time" + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{instance_id}/customers": { + "post": { + "x-sdk": true, + "tags": [ + "Customers" + ], + "summary": "Create Customer", + "description": "Creates a customer and starts KYC (individuals) or KYB (businesses). Send the tos_id the customer received after accepting terms of service (see Initiate Terms of Service). Required fields depend on type and kyc_type. Individual, standard: first_name, last_name, date_of_birth, tax_id, address_line_1, city, state_province_region, postal_code, country, id_doc_country, id_doc_type, id_doc_front_file and selfie_file. Business, standard: legal_name, formation_date, tax_id, website, the same address fields, at least one entry in owners, incorporation_doc_file, proof_of_ownership_doc_file, proof_of_address_doc_type and proof_of_address_doc_file. kyc_type light is not available, and businesses only support standard. US state_province_region is a two-letter code. File fields are HTTPS URLs that BlindPay downloads, so they must be publicly fetchable; data: URIs are rejected. The customer starts with kyc_status verifying. Development instances approve it automatically.", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" + } + ], + "requestBody": { + "description": "Create a new customer", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateCustomerIn" + } + } + } + }, + "responses": { + "200": { + "description": "Create customer", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" }, - { + "customer_id": { "type": "string" } - ], - "example": "1998-01-01T00:00:00Z" - }, - "tax_id": { - "type": [ - "string", - "null" - ], - "example": "536804398" - }, - "address_line_1": { - "type": "string", - "example": "738 Plain St" - }, - "address_line_2": { - "type": [ - "string", - "null" - ], - "example": "Building 22" + }, + "required": [ + "id", + "customer_id" + ] + } + } + } + }, + "400": { + "description": "Possible error codes: `CUSTOMERS_ALREADY_APPROVED`, `CUSTOMERS_BUSINESS_ENHANCED_NOT_AVAILABLE`, `CUSTOMERS_ENHANCED_KYC_REQUIRED`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_KYC_TYPE_NOT_AVAILABLE`, `FILES_TOO_LARGE`, `FILES_TYPE_NOT_ALLOWED`, `FILES_UNREADABLE`, `TOS_ALREADY_ACCEPTED`, `TOS_NOT_ACCEPTED`, `TOS_NOT_FOUND`, `VALIDATION_FAILED`, `VALIDATION_MISSING_REQUIRED_FIELDS`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "city": { - "type": "string", - "example": "Marshfield" + "examples": { + "CUSTOMERS_ALREADY_APPROVED": { + "summary": "CUSTOMERS_ALREADY_APPROVED", + "value": { + "success": false, + "code": "CUSTOMERS_ALREADY_APPROVED", + "message": "customer_already_approved", + "description": "This customer is already approved.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_BUSINESS_ENHANCED_NOT_AVAILABLE": { + "summary": "CUSTOMERS_BUSINESS_ENHANCED_NOT_AVAILABLE", + "value": { + "success": false, + "code": "CUSTOMERS_BUSINESS_ENHANCED_NOT_AVAILABLE", + "message": "business_enhanced_not_available", + "description": "Enhanced verification is not available for business customers. Use standard verification (kyc_type: standard) for businesses.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ENHANCED_KYC_REQUIRED": { + "summary": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "value": { + "success": false, + "code": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "message": "only_enhanced_kyc_allowed_for_high_risk_countries", + "description": "Individuals from high-risk countries must use enhanced verification (kyc_type: enhanced); standard verification is not available for them. See https://www.blindpay.com/docs/kb/supported-countries for country tiers.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_PHONE": { + "summary": "CUSTOMERS_INVALID_PHONE", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_PHONE", + "message": "invalid_phone_number", + "description": "The phone number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_TAX_ID": { + "summary": "CUSTOMERS_INVALID_TAX_ID", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_TAX_ID", + "message": "invalid_cpf_or_rg_tax_id", + "description": "The tax ID provided is not valid. Check the value and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE": { + "summary": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "message": "kyc_type_not_supported", + "description": "The requested verification type is not available for this customer. Use a supported verification type and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TYPE_NOT_ALLOWED": { + "summary": "FILES_TYPE_NOT_ALLOWED", + "value": { + "success": false, + "code": "FILES_TYPE_NOT_ALLOWED", + "message": "file_type_not_allowed", + "description": "This file type is not allowed. Upload a supported file type.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "TOS_ALREADY_ACCEPTED": { + "summary": "TOS_ALREADY_ACCEPTED", + "value": { + "success": false, + "code": "TOS_ALREADY_ACCEPTED", + "message": "tos_id_already_accepted", + "description": "These terms of service were already accepted.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "TOS_NOT_ACCEPTED": { + "summary": "TOS_NOT_ACCEPTED", + "value": { + "success": false, + "code": "TOS_NOT_ACCEPTED", + "message": "please_accept_terms_of_service", + "description": "The terms of service must be accepted before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "TOS_NOT_FOUND": { + "summary": "TOS_NOT_FOUND", + "value": { + "success": false, + "code": "TOS_NOT_FOUND", + "message": "tos_not_found", + "description": "The requested terms of service record was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_MISSING_REQUIRED_FIELDS": { + "summary": "VALIDATION_MISSING_REQUIRED_FIELDS", + "value": { + "success": false, + "code": "VALIDATION_MISSING_REQUIRED_FIELDS", + "message": "missing_required_fields", + "description": "Required fields are missing. Provide the missing fields and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { + "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "message": "id_doc_front_file_required", + "description": "An identity document is required for this customer. Upload the front of a valid document and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "state_province_region": { - "type": "string", - "example": "MA" + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "country": { - "type": "string", - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "US" + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "postal_code": { - "type": "string", - "example": "02050" + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "500": { + "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "id_doc_country": { - "type": "string", - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "BR" + "examples": { + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + }, + "get": { + "x-sdk": true, + "tags": [ + "Customers" + ], + "summary": "Retrieve Customers", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "enum": [ + "10", + "50", + "100", + "200", + "500", + "1000" + ], + "description": "Number of items to return", + "example": "50" + }, + "required": false, + "name": "limit", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "0", + "10", + "50", + "100", + "200", + "500", + "1000" + ], + "description": "Number of items to skip", + "example": "0" + }, + "required": false, + "name": "offset", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "A cursor for use in pagination. starting_after is an object ID that defines your place in the list.", + "example": "pi_123" + }, + "required": false, + "name": "starting_after", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "A cursor for use in pagination. ending_before is an object ID that defines your place in the list.", + "example": "pi_123" + }, + "required": false, + "name": "ending_before", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "full_name", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "customer_name", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "verifying", + "approved", + "rejected", + "deprecated", + "pending_review", + "awaiting_contract", + "compliance_request", + "approved_rfi" + ] + }, + "required": false, + "name": "status", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "customer_id", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "bank_account_id", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "country", + "in": "query" + } + ], + "responses": { + "200": { + "description": "List customers with pagination", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CustomerOut" + } + }, + "pagination": { + "$ref": "#/components/schemas/PaginationMetadata" + } + }, + "required": [ + "data", + "pagination" + ] + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/CustomerOut" + } + } + ] + } + } + } + }, + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`, `VALIDATION_INVALID_REQUEST`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_INVALID_REQUEST": { + "summary": "VALIDATION_INVALID_REQUEST", + "value": { + "success": false, + "code": "VALIDATION_INVALID_REQUEST", + "message": "invalid_body", + "description": "The request is not valid for this operation. Check the parameters and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "id_doc_type": { - "type": "string", - "enum": [ - "PASSPORT", - "ID_CARD", - "DRIVERS" - ], - "example": "PASSPORT" + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "id_doc_front_file": { - "type": [ - "string", - "null" - ], - "description": "Only image files are accepted (.jpg, .jpeg, .png)" + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "id_doc_back_file": { - "type": [ - "string", - "null" - ], - "description": "Only image files are accepted (.jpg, .jpeg, .png)" + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "proof_of_address_doc_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "UTILITY_BILL", - "BANK_STATEMENT", - "RENTAL_AGREEMENT", - "TAX_DOCUMENT", - "GOVERNMENT_CORRESPONDENCE" - ], - "example": "UTILITY_BILL" + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{instance_id}/customers/{id}": { + "get": { + "x-sdk": true, + "tags": [ + "Customers" + ], + "summary": "Retrieve Customer", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Get customer", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerOut" + } + } + } + }, + "400": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "proof_of_address_doc_file": { - "type": [ - "string", - "null" - ], - "description": "Please upload one document that serve as proof of address, this needs to be the same address as the one provided above. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB." + "examples": { + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "ownership_percentage": { - "type": [ - "integer", - "null" - ], - "minimum": 0, - "maximum": 100, - "description": "Ownership percentage of the beneficial owner (0-100)", - "example": 25 + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "title": { - "type": [ - "string", - "null" - ], - "maxLength": 128, - "description": "Job title of the owner", - "example": "CEO" + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "422": { + "description": "Possible error codes: `DATA_INTEGRITY_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "tax_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "SSN", - "ITIN" - ], - "description": "Tax identifier type. Mandatory when country is US; must be SSN or ITIN.", - "example": "SSN" + "examples": { + "DATA_INTEGRITY_ERROR": { + "summary": "DATA_INTEGRITY_ERROR", + "value": { + "success": false, + "code": "DATA_INTEGRITY_ERROR", + "message": "data_integrity_error", + "description": "This record could not be loaded because it contains invalid stored data. Contact support with the ID below.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } } } - }, - "description": "Customer owners", - "example": [ - { - "id": "ub_000000000000", - "first_name": "John", - "last_name": "Doe", - "address_line_1": "738 Plain St", - "address_line_2": "Building 22", - "city": "Marshfield", - "state_province_region": "MA", - "country": "US", - "postal_code": "02050", - "id_doc_country": "BR", - "id_doc_type": "PASSPORT", - "id_doc_front_file": "https://example.com/image.png", - "id_doc_back_file": "https://example.com/image.png" + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } } - ] + } }, - "incorporation_doc_file": { - "type": [ - "string", - "null" - ], - "description": "Please upload your articles of incorporation below. The articles of incorporation or a certificate of incorporation usually includes information like the company name, business purpose, number of shares offered, value of shares, etc. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", - "example": "https://example.com/image.png" + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + }, + "put": { + "x-sdk": true, + "tags": [ + "Customers" + ], + "summary": "Update Customer", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" }, - "proof_of_ownership_doc_file": { - "type": [ - "string", - "null" - ], - "description": "Please upload your proof of ownership below. This document usually includes information like the shareholders names and percentages. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", - "example": "https://example.com/image.png" + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "required": true, + "name": "id", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" + } + ], + "requestBody": { + "description": "Update a customer", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateCustomerIn" + } + } + } + }, + "responses": { + "200": { + "description": "Customer updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + }, + "400": { + "description": "Possible error codes: `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_KYC_TYPE_NOT_AVAILABLE`, `FILES_TOO_LARGE`, `FILES_TYPE_NOT_ALLOWED`, `FILES_UNREADABLE`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_INVALID_PHONE": { + "summary": "CUSTOMERS_INVALID_PHONE", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_PHONE", + "message": "invalid_phone_number", + "description": "The phone number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_TAX_ID": { + "summary": "CUSTOMERS_INVALID_TAX_ID", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_TAX_ID", + "message": "invalid_cpf_or_rg_tax_id", + "description": "The tax ID provided is not valid. Check the value and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE": { + "summary": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "message": "kyc_type_not_supported", + "description": "The requested verification type is not available for this customer. Use a supported verification type and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TYPE_NOT_ALLOWED": { + "summary": "FILES_TYPE_NOT_ALLOWED", + "value": { + "success": false, + "code": "FILES_TYPE_NOT_ALLOWED", + "message": "file_type_not_allowed", + "description": "This file type is not allowed. Upload a supported file type.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "source_of_funds_doc_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "business_income", - "gambling_proceeds", - "gifts", - "government_benefits", - "inheritance", - "investment_loans", - "pension_retirement", - "salary", - "sale_of_assets_real_estate", - "savings", - "esops", - "investment_proceeds", - "someone_else_funds" - ], - "example": "business_income" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "source_of_funds_doc_file": { - "type": [ - "string", - "null" - ], - "example": "https://example.com/image.png" + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "selfie_file": { - "type": [ - "string", - "null" - ], - "description": "Only image files are accepted (.jpg, .jpeg, .png)", - "example": "https://example.com/image.png" + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "purpose_of_transactions": { - "type": [ - "string", - "null" - ], - "enum": [ - "business_transactions", - "charitable_donations", - "investment_purposes", - "payments_to_friends_or_family_abroad", - "personal_or_living_expenses", - "protect_wealth", - "purchase_good_and_services", - "receive_payment_for_freelancing", - "receive_salary", - "other" - ], - "example": "business_transactions" + "409": { + "description": "Possible error codes: `CUSTOMERS_REJECTED_DOCUMENTS_LOCKED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_REJECTED_DOCUMENTS_LOCKED": { + "summary": "CUSTOMERS_REJECTED_DOCUMENTS_LOCKED", + "value": { + "success": false, + "code": "CUSTOMERS_REJECTED_DOCUMENTS_LOCKED", + "message": "customer_rejected_documents_locked", + "description": "Documents of a rejected customer cannot be replaced, because updating a customer does not start a new verification. Create a new customer with the new documents instead.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "purpose_of_transactions_explanation": { - "type": [ - "string", - "null" - ], - "example": "I am a business owner and I want to receive payments from my customers" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "is_fbo": { - "type": [ - "boolean", - "null" - ], - "example": false + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + }, + "delete": { + "x-sdk": true, + "tags": [ + "Customers" + ], + "summary": "Delete Customer", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" }, - "account_purpose": { - "type": [ - "string", - "null" - ], - "enum": [ - "charitable_donations", - "ecommerce_retail_payments", - "investment_purposes", - "business_expenses", - "payments_to_friends_or_family_abroad", - "personal_or_living_expenses", - "protect_wealth", - "purchase_goods_and_services", - "receive_payments_for_goods_and_services", - "tax_optimization", - "third_party_money_transmission", - "payroll", - "treasury_management", - "other" - ], - "example": "treasury_management" + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "required": true, + "name": "id", + "in": "path" }, - "account_purpose_other": { - "type": [ - "string", - "null" - ], - "maxLength": 512, - "description": "Required when account_purpose is \"other\". Max 512 characters.", - "example": "Custom account purpose description" + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" + } + ], + "responses": { + "200": { + "description": "Customer deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } }, - "business_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "corporation", - "llc", - "partnership", - "sole_proprietorship", - "trust", - "non_profit" - ], - "example": "llc" + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "business_description": { - "type": [ - "string", - "null" - ], - "maxLength": 1000, - "example": "Software development company" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "business_industry": { - "type": [ - "string", - "null" - ], - "enum": [ - "111998", - "112120", - "113310", - "115114", - "541211", - "541810", - "541430", - "541715", - "541930", - "561422", - "561311", - "561612", - "561740", - "561730", - "236115", - "236220", - "237310", - "238210", - "811111", - "812111", - "812112", - "532111", - "624410", - "541922", - "811210", - "812199", - "611110", - "611310", - "611410", - "611710", - "211120", - "212114", - "221310", - "562111", - "562920", - "213112", - "522110", - "522210", - "522320", - "523150", - "523940", - "523999", - "524113", - "813110", - "813211", - "813219", - "551112", - "721110", - "722511", - "722513", - "561510", - "713110", - "713210", - "712110", - "711110", - "711211", - "621111", - "621210", - "622110", - "623110", - "621511", - "623220", - "541940", - "621399", - "621910", - "541110", - "311421", - "337121", - "322220", - "339920", - "334210", - "339930", - "312130", - "334111", - "334118", - "325412", - "339112", - "336110", - "336390", - "315990", - "313110", - "339910", - "516120", - "513130", - "512250", - "519130", - "711410", - "711510", - "531110", - "531120", - "531130", - "531190", - "531210", - "531311", - "531312", - "531320", - "531390", - "454110", - "445110", - "455110", - "457110", - "449210", - "444110", - "459210", - "459120", - "445320", - "458110", - "458210", - "458310", - "455219", - "424210", - "456110", - "446120", - "541511", - "541512", - "541519", - "518210", - "511210", - "517111", - "517112", - "517410", - "481111", - "483111", - "485210", - "488510", - "484121", - "493110", - "423430", - "423690", - "423110", - "423830", - "423840", - "423510", - "424690", - "424990", - "424410", - "424480", - "423940", - "541611", - "541618", - "541330", - "541990", - "541214", - "561499" - ], - "example": "541511" + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "estimated_annual_revenue": { - "type": [ - "string", - "null" - ], - "enum": [ - "0_99999", - "100000_999999", - "1000000_9999999", - "10000000_49999999", - "50000000_249999999", - "250000000_plus" - ], - "example": "1000000_9999999" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "source_of_wealth": { - "type": [ - "string", - "null" - ], - "enum": [ - "business_dividends_or_profits", - "investments", - "asset_sales", - "client_investor_contributions", - "gambling", - "charitable_contributions", - "inheritance", - "affiliate_or_royalty_income" - ], - "example": "affiliate_or_royalty_income" + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{instance_id}/limits/customers/{id}": { + "get": { + "x-sdk": true, + "tags": [ + "Customers" + ], + "summary": "Retrieve Customer Limits", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" }, - "publicly_traded": { - "type": [ - "boolean", - "null" - ], - "example": false + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Get customer limits", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetCustomerLimitsOut" + } + } + } }, - "occupation": { - "type": [ - "string", - "null" - ], - "maxLength": 255, - "example": "Software Engineer" + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "external_id": { - "type": [ - "string", - "null" - ], - "example": "your_company_external_id" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "instance_id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "tos_id": { - "type": [ - "string", - "null" - ], - "minLength": 15, - "maxLength": 15, - "example": "to_000000000000" + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "aml_status": { - "type": [ - "string", - "null" - ], - "enum": [ - "clear", - "hit", - "error" - ], - "description": "AML screening status from SEON. null = not yet screened.", - "example": "clear" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "aml_hits": { - "type": [ - "object", - "null" - ], - "properties": { - "has_sanction_match": { - "type": "boolean", - "default": false - }, - "has_pep_match": { - "type": "boolean", - "default": false - }, - "has_watchlist_match": { - "type": "boolean", - "default": false - }, - "has_crimelist_match": { - "type": "boolean", - "default": false - }, - "has_adversemedia_match": { - "type": "boolean", - "default": false + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } } + } + } + } + } + }, + "/v1/instances/{instance_id}/customers/{customer_id}/rfi": { + "get": { + "x-sdk": true, + "tags": [ + "Customers" + ], + "summary": "Get Open RFI for Customer", + "description": "Returns the open (pending) RFI for this customer, or null if the customer has no pending RFI.", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" }, - "description": "AML screening match details from SEON.", - "example": { - "has_sanction_match": false, - "has_pep_match": false, - "has_watchlist_match": false, - "has_crimelist_match": false, - "has_adversemedia_match": false + "required": true, + "name": "instance_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Open RFI, or null if none", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Rfi" + } + } } }, - "created_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "updated_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "limit": { - "type": "object", - "properties": { - "per_transaction": { - "type": [ - "number", - "null" - ], - "example": 100000 - }, - "daily": { - "type": [ - "number", - "null" - ], - "example": 200000 - }, - "monthly": { - "type": [ - "number", - "null" - ], - "example": 1000000 + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } } + } + } + } + }, + "post": { + "x-sdk": true, + "tags": [ + "Customers" + ], + "summary": "Submit RFI Response", + "description": "Submit a flat response object for the open RFI. On success flips kyc_status back to verifying. Returns `{ success: false, reason }` when no pending RFI exists, callers should refetch the RFI state instead of retrying.", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" }, - "required": [ - "per_transaction", - "daily", - "monthly" - ] + "required": true, + "name": "instance_id", + "in": "path" }, - "is_tos_accepted": { - "type": [ - "boolean", - "null" - ] + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" }, - "additional_info": { - "type": [ - "array", - "null" - ], - "items": { - "$ref": "#/components/schemas/AdditionalInfoItem" + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }, - "description": "Optional extra documents or notes for this customer. `label` is a known category, `value` is either a URL to upload or a free-text description. Any URLs are downloaded and re-hosted on Blindpay storage before being stored.", - "example": [ - { - "label": "EIN_LETTER", - "value": "https://example.com/ein.pdf" - }, - { - "label": "FLOW_OF_FUNDS", - "value": "Funds originate from US payroll deposits, forwarded weekly to customer." + "required": false, + "name": "Idempotency-Key", + "in": "header" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": {} } - ] + } } }, - "required": [ - "id", - "customer_id", - "type", - "kyc_type", - "kyc_status", - "email", - "country", - "instance_id", - "limit" - ] - }, - "UpdateCustomerIn": { - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "example": "email@example.com" - }, - "tax_id": { - "type": [ - "string", - "null" - ], - "example": "536804398" - }, - "address_line_1": { - "type": [ - "string", - "null" - ], - "example": "738 Plain St" - }, - "address_line_2": { - "type": [ - "string", - "null" - ], - "example": "Building 22" - }, - "city": { - "type": [ - "string", - "null" - ], - "example": "Marshfield" - }, - "state_province_region": { - "type": [ - "string", - "null" - ], - "example": "MA" - }, - "country": { - "type": "string", - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "US" - }, - "postal_code": { - "type": [ - "string", - "null" - ], - "example": "02050" - }, - "ip_address": { - "type": [ - "string", - "null" - ], - "format": "ip", - "example": "127.0.0.1" - }, - "latitude": { - "type": [ - "number", - "null" - ], - "minimum": -90, - "maximum": 90, - "description": "Optional geolocation latitude collected from the customer. Forwarded to AiPrise and SEON for fraud analysis.", - "example": 37.7749 + "responses": { + "200": { + "description": "RFI submitted (success: true) or rejected because no pending RFI exists (success: false)", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "required": [ + "success" + ] + }, + { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + false + ] + }, + "reason": { + "type": "string", + "enum": [ + "no_pending_rfi", + "already_resolved" + ] + } + }, + "required": [ + "success", + "reason" + ] + } + ] + } + } + } }, - "longitude": { - "type": [ - "number", - "null" - ], - "minimum": -180, - "maximum": 180, - "description": "Optional geolocation longitude collected from the customer. Forwarded to AiPrise and SEON for fraud analysis.", - "example": -122.4194 + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "image_url": { - "type": [ - "string", - "null" - ], - "format": "uri", - "example": "https://example.com/image.png" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "phone_number": { - "type": [ - "string", - "null" - ], - "example": "+13055555555" + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "proof_of_address_doc_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "UTILITY_BILL", - "BANK_STATEMENT", - "RENTAL_AGREEMENT", - "TAX_DOCUMENT", - "GOVERNMENT_CORRESPONDENCE" - ], - "example": "UTILITY_BILL" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "proof_of_address_doc_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Please upload one document that serve as proof of address, this needs to be the same physical address as the one provided above. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", - "example": "https://example.com/image.png" + "500": { + "description": "Possible error codes: `COMPLIANCE_RFI_INVALID`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "COMPLIANCE_RFI_INVALID": { + "summary": "COMPLIANCE_RFI_INVALID", + "value": { + "success": false, + "code": "COMPLIANCE_RFI_INVALID", + "message": "rfi_request_corrupt", + "description": "The information request could not be processed. Check the submitted fields.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{instance_id}/customers/{customer_id}/bank-accounts/plaid": { + "post": { + "x-sdk": true, + "tags": [ + "Bank Accounts" + ], + "summary": "Create Plaid Link", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" }, - "first_name": { - "type": [ - "string", - "null" - ], - "example": "John" + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + } + ], + "requestBody": { + "required": false, + "description": "Optional redirect once the bank account is connected", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreatePlaidLinkIn" + } + } + } + }, + "responses": { + "200": { + "description": "BlindPay hosted Plaid Link URL, carrying a signed short-lived token, to embed in an iframe or open in a new tab", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlaidLinkOut" + } + } + } }, - "last_name": { - "type": [ - "string", - "null" - ], - "example": "Doe" + "400": { + "description": "Possible error codes: `BANK_ACCOUNTS_PLAID_NOT_ENABLED`, `CUSTOMERS_KYC_TYPE_NOT_AVAILABLE`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "BANK_ACCOUNTS_PLAID_NOT_ENABLED": { + "summary": "BANK_ACCOUNTS_PLAID_NOT_ENABLED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PLAID_NOT_ENABLED", + "message": "plaid_not_supported", + "description": "Instantly connected bank accounts are not enabled for this account. Contact support to enable them.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE": { + "summary": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "message": "kyc_type_not_supported", + "description": "The requested verification type is not available for this customer. Use a supported verification type and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "date_of_birth": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "string" - }, - { - "type": "null" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } } - ], - "example": "1998-01-01T00:00:00Z" + } }, - "id_doc_country": { - "type": [ - "string", - "null" - ], - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "BR" + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "id_doc_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "PASSPORT", - "ID_CARD", - "DRIVERS" - ], - "example": "PASSPORT" + "404": { + "description": "Possible error codes: `BANK_ACCOUNTS_PLAID_LINK_SESSION_INVALID`, `CUSTOMERS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "BANK_ACCOUNTS_PLAID_LINK_SESSION_INVALID": { + "summary": "BANK_ACCOUNTS_PLAID_LINK_SESSION_INVALID", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PLAID_LINK_SESSION_INVALID", + "message": "plaid_link_session_expired", + "description": "This bank connection link is unknown or has expired. Request a new link.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "id_doc_front_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Only image files are accepted (.jpg, .jpeg, .png)", - "example": "https://example.com/image.png" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "id_doc_back_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Only image files are accepted (.jpg, .jpeg, .png)", - "example": "https://example.com/image.png" + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{instance_id}/customers/{customer_id}/bank-accounts": { + "post": { + "x-sdk": true, + "tags": [ + "Bank Accounts" + ], + "summary": "Add Bank Account", + "description": "Adds a payout destination for a customer. Required fields depend on type (the rail): call Bank Details (GET /v1/available/bank-details) with the rail first for the exact field list and validation. For ach and wire: business_industry (a NAICS code from GET /v1/available/naics) is required when account_class is business, phone_number is required when country is BR, CN, CO, HK, MY, MX, PH, UG or UY, and tax_id is required when country is AR, BY, BR, CL, CN, CO, CR, EC, GT, HN, JP, KZ, KR, MX, PK, PE, PH, RU, TH or UY. A US state_province_region is a two-letter code. ach, wire and rtp are not available for light KYC customers.", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" }, - "legal_name": { - "type": [ - "string", - "null" - ], - "example": "Company Name Inc." + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" }, - "alternate_name": { - "type": [ - "string", - "null" - ], - "example": "Company Name Inc." + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" + } + ], + "requestBody": { + "description": "Create a new bank account", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/CreateBankAccountIn" + }, + { + "type": "object" + } + ] + } + } + } + }, + "responses": { + "200": { + "description": "Add bank account", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BankAccountOut" + } + } + } }, - "formation_date": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "string" - }, - { - "type": "null" + "400": { + "description": "Possible error codes: `BANK_ACCOUNTS_INCOMPLETE`, `BANK_ACCOUNTS_INVALID_BANK_CODE`, `BANK_ACCOUNTS_INVALID_ROUTING`, `BANK_ACCOUNTS_NOT_APPROVED`, `BANK_ACCOUNTS_NOT_FOUND`, `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED`, `BANK_ACCOUNTS_RTP_NOT_SUPPORTED`, `BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `BLOCKCHAIN_TX_FAILED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_KYC_TYPE_NOT_AVAILABLE`, `CUSTOMERS_NAME_INVALID`, `CUSTOMERS_ONBOARDING_INCOMPLETE`, `FEES_PARTNER_FEE_EXCEEDED`, `FILES_TOO_LARGE`, `FILES_UNREADABLE`, `LIMITS_AMOUNT_OUT_OF_RANGE`, `PAYABLES_ALREADY_PAID_OR_EXPIRED`, `PAYABLES_ALREADY_PAID_OR_IN_FLIGHT`, `PAYABLES_AMOUNT_NEGATIVE`, `PAYABLES_BANK_ACCOUNT_INVALID`, `PAYABLES_CODE_UNRESOLVABLE`, `PAYABLES_CURRENCY_MUST_BE_BRL`, `PAYABLES_DESTINATION_NOT_SUPPORTED`, `PAYABLES_DOCUMENT_INVALID`, `PAYABLES_DUPLICATE`, `PAYABLES_NETWORK_NOT_SUPPORTED`, `PAYABLES_NOT_CANCELABLE`, `PAYABLES_PIX_AMOUNT_REQUIRED`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `PAYOUTS_DOCUMENTS_NOT_ACCEPTED`, `QUOTES_ALREADY_USED`, `QUOTES_EXPIRED`, `QUOTES_INVALID_STATE`, `QUOTES_RATE_UNAVAILABLE`, `VALIDATION_FAILED`, `VALIDATION_INVALID_REQUEST`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_NOT_FOUND`, `VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "BANK_ACCOUNTS_INCOMPLETE": { + "summary": "BANK_ACCOUNTS_INCOMPLETE", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INCOMPLETE", + "message": "infinitus_missing_intermediary", + "description": "The banking provider cannot route payments to this bank automatically. Provide the US correspondent bank routing number (ABA, 9 digits) from the beneficiary bank USD wire instructions in swift_intermediary_bank_routing_number.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_INVALID_BANK_CODE": { + "summary": "BANK_ACCOUNTS_INVALID_BANK_CODE", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INVALID_BANK_CODE", + "message": "bank_accounts_invalid_bank_code", + "description": "The bank code provided is not valid for this payment rail. The message lists where to fetch the valid codes.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_INVALID_ROUTING": { + "summary": "BANK_ACCOUNTS_INVALID_ROUTING", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INVALID_ROUTING", + "message": "The routing number must be a valid 9-digit ABA routing number.", + "description": "The routing number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_NOT_APPROVED": { + "summary": "BANK_ACCOUNTS_NOT_APPROVED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_APPROVED", + "message": "bank_account_not_approved", + "description": "This bank account is not approved yet.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_NOT_FOUND": { + "summary": "BANK_ACCOUNTS_NOT_FOUND", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_FOUND", + "message": "bank_account_not_found", + "description": "The requested bank account was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "message": "unsupported_banking_partner", + "description": "This banking option is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_RTP_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", + "message": "The provided routing number does not support RTP transactions.", + "description": "The provided routing number does not support instant payments.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR": { + "summary": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "message": "sepa_iban_not_eur", + "description": "SEPA payouts are only available to EUR accounts. This IBAN is from a country that holds another currency, so the payment would fail at settlement. Use an IBAN from a EUR account instead.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { + "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "message": "network_not_supported_on_dev_instance", + "description": "This network or token combination is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_TX_FAILED": { + "summary": "BLOCKCHAIN_TX_FAILED", + "value": { + "success": false, + "code": "BLOCKCHAIN_TX_FAILED", + "message": "transaction_failed", + "description": "The blockchain transaction failed. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { + "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "value": { + "success": false, + "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "message": "country_not_supported", + "description": "This country is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_PHONE": { + "summary": "CUSTOMERS_INVALID_PHONE", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_PHONE", + "message": "invalid_phone_number", + "description": "The phone number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_TAX_ID": { + "summary": "CUSTOMERS_INVALID_TAX_ID", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_TAX_ID", + "message": "invalid_cpf_or_rg_tax_id", + "description": "The tax ID provided is not valid. Check the value and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE": { + "summary": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "message": "kyc_type_not_supported", + "description": "The requested verification type is not available for this customer. Use a supported verification type and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_NAME_INVALID": { + "summary": "CUSTOMERS_NAME_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_NAME_INVALID", + "message": "legal_name_required", + "description": "The name registered for this customer is not accepted. Review it and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ONBOARDING_INCOMPLETE": { + "summary": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "value": { + "success": false, + "code": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "message": "onboarding_incomplete", + "description": "Onboarding is not complete yet. Finish the remaining steps before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_PARTNER_FEE_EXCEEDED": { + "summary": "FEES_PARTNER_FEE_EXCEEDED", + "value": { + "success": false, + "code": "FEES_PARTNER_FEE_EXCEEDED", + "message": "partner_fee_exceeded", + "description": "The partner fee exceeds the allowed maximum for this transaction.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "LIMITS_AMOUNT_OUT_OF_RANGE": { + "summary": "LIMITS_AMOUNT_OUT_OF_RANGE", + "value": { + "success": false, + "code": "LIMITS_AMOUNT_OUT_OF_RANGE", + "message": "limits_amount_out_of_range", + "description": "The amount is outside the allowed range. The message includes the allowed range.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_ALREADY_PAID_OR_EXPIRED": { + "summary": "PAYABLES_ALREADY_PAID_OR_EXPIRED", + "value": { + "success": false, + "code": "PAYABLES_ALREADY_PAID_OR_EXPIRED", + "message": "payable_already_paid_or_expired", + "description": "This payment code was already paid or has expired and can no longer be paid.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT": { + "summary": "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT", + "value": { + "success": false, + "code": "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT", + "message": "payable_already_paid_or_in_flight", + "description": "This payable is already being paid or was already paid. Only draft payables can be quoted; a failed or refunded attempt returns the payable to draft.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_AMOUNT_NEGATIVE": { + "summary": "PAYABLES_AMOUNT_NEGATIVE", + "value": { + "success": false, + "code": "PAYABLES_AMOUNT_NEGATIVE", + "message": "payable_amount_negative", + "description": "The payable total (line items plus taxes minus discount) cannot be negative.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_BANK_ACCOUNT_INVALID": { + "summary": "PAYABLES_BANK_ACCOUNT_INVALID", + "value": { + "success": false, + "code": "PAYABLES_BANK_ACCOUNT_INVALID", + "message": "payable_bank_account_invalid", + "description": "The bank_account details on this invoice payable were rejected. Check the errors list for the field that failed.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_CODE_UNRESOLVABLE": { + "summary": "PAYABLES_CODE_UNRESOLVABLE", + "value": { + "success": false, + "code": "PAYABLES_CODE_UNRESOLVABLE", + "message": "unresolvable_payable_code", + "description": "We could not read this payment code. Check the code and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_CURRENCY_MUST_BE_BRL": { + "summary": "PAYABLES_CURRENCY_MUST_BE_BRL", + "value": { + "success": false, + "code": "PAYABLES_CURRENCY_MUST_BE_BRL", + "message": "payable_currency_must_be_brl", + "description": "Boleto and PIX payables must use BRL.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DESTINATION_NOT_SUPPORTED": { + "summary": "PAYABLES_DESTINATION_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYABLES_DESTINATION_NOT_SUPPORTED", + "message": "payable_destination_not_supported", + "description": "Only boleto, arrecadação (utility/tax) and PIX QR code payables can be paid right now. Bank-destination invoice payables are not payable yet.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DOCUMENT_INVALID": { + "summary": "PAYABLES_DOCUMENT_INVALID", + "value": { + "success": false, + "code": "PAYABLES_DOCUMENT_INVALID", + "message": "payable_document_invalid", + "description": "document_file must be a URL returned by POST /upload with bucket `documents`, uploaded by this instance.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DUPLICATE": { + "summary": "PAYABLES_DUPLICATE", + "value": { + "success": false, + "code": "PAYABLES_DUPLICATE", + "message": "duplicate_payable", + "description": "This payment code already has a payable registered, in progress or completed for this instance.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_NETWORK_NOT_SUPPORTED": { + "summary": "PAYABLES_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYABLES_NETWORK_NOT_SUPPORTED", + "message": "payable_network_not_supported", + "description": "Only EVM wallets can fund payables right now.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_NOT_CANCELABLE": { + "summary": "PAYABLES_NOT_CANCELABLE", + "value": { + "success": false, + "code": "PAYABLES_NOT_CANCELABLE", + "message": "payable_not_cancelable", + "description": "Only draft payables can be deleted. Once a payout is executing this payable it can no longer be canceled.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_PIX_AMOUNT_REQUIRED": { + "summary": "PAYABLES_PIX_AMOUNT_REQUIRED", + "value": { + "success": false, + "code": "PAYABLES_PIX_AMOUNT_REQUIRED", + "message": "pix_code_amount_required", + "description": "This PIX code has no fixed amount and no amount was provided. Send the amount as line_items when registering a PIX code that lets the payer choose the value.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_AMOUNT_BELOW_MINIMUM": { + "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "value": { + "success": false, + "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "message": "swift_minimum_is_100_usd", + "description": "The amount is below the minimum for this payment rail.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_DOCUMENTS_NOT_ACCEPTED": { + "summary": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", + "value": { + "success": false, + "code": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", + "message": "document_upload_only_for_swift_payouts", + "description": "A document cannot be submitted for this payout in its current state.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_ALREADY_USED": { + "summary": "QUOTES_ALREADY_USED", + "value": { + "success": false, + "code": "QUOTES_ALREADY_USED", + "message": "quote_already_used", + "description": "This quote was already used. Request a new quote.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_EXPIRED": { + "summary": "QUOTES_EXPIRED", + "value": { + "success": false, + "code": "QUOTES_EXPIRED", + "message": "quote_expired", + "description": "This quote has expired. Request a new quote and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_INVALID_STATE": { + "summary": "QUOTES_INVALID_STATE", + "value": { + "success": false, + "code": "QUOTES_INVALID_STATE", + "message": "quote_invalid_state", + "description": "This quote cannot be authorized in its current state. Request a new quote and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_INVALID_REQUEST": { + "summary": "VALIDATION_INVALID_REQUEST", + "value": { + "success": false, + "code": "VALIDATION_INVALID_REQUEST", + "message": "invalid_body", + "description": "The request is not valid for this operation. Check the parameters and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { + "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "message": "id_doc_front_file_required", + "description": "An identity document is required for this customer. Upload the front of a valid document and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_NOT_FOUND": { + "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "message": "virtual_account_not_found", + "description": "The requested virtual account was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE": { + "summary": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "message": "banking_partner_not_eligible_for_customer", + "description": "This banking partner is not available for this customer. Choose a different banking partner.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } } - ], - "example": "1998-01-01T00:00:00Z", - "format": "date-time" - }, - "website": { - "type": [ - "string", - "null" - ], - "format": "uri", - "example": "https://example.com" + } }, - "owners": { - "type": [ - "array", - "null" - ], - "items": { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "beneficial_controlling", - "beneficial_owner", - "controlling_person" - ], - "description": "A beneficial owner is someone who directly or indirectly owns 25% or more of your business. A controlling person is someone with significant responsibility to control, manage or direct your business (typically a CEO, senior executive officer or equivalent).", - "example": "beneficial_owner" - }, - "first_name": { - "type": "string", - "minLength": 1, - "example": "John" - }, - "last_name": { - "type": "string", - "minLength": 1, - "example": "Doe" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "date_of_birth": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "string" + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" } - ], - "example": "1998-01-01T00:00:00Z" - }, - "tax_id": { - "type": "string", - "example": "536804398" - }, - "address_line_1": { - "type": "string", - "example": "738 Plain St" - }, - "address_line_2": { - "type": [ - "string", - "null" - ], - "example": "Building 22" - }, - "city": { - "type": "string", - "example": "Marshfield" + } + } + } + } + }, + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "state_province_region": { - "type": "string", - "example": "MA" + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `PAYABLES_NOT_FOUND`, `PAYOUTS_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "country": { - "type": "string", - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "US" + "examples": { + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_NOT_FOUND": { + "summary": "PAYABLES_NOT_FOUND", + "value": { + "success": false, + "code": "PAYABLES_NOT_FOUND", + "message": "payable_not_found", + "description": "This payable was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_NOT_FOUND": { + "summary": "PAYOUTS_NOT_FOUND", + "value": { + "success": false, + "code": "PAYOUTS_NOT_FOUND", + "message": "payout_not_found", + "description": "The requested payout was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", + "value": { + "success": false, + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "422": { + "description": "Possible error codes: `CUSTOMERS_INVALID_DATA`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "postal_code": { - "type": "string", - "example": "02050" + "examples": { + "CUSTOMERS_INVALID_DATA": { + "summary": "CUSTOMERS_INVALID_DATA", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_DATA", + "message": "invalid_customer_data", + "description": "The customer data was rejected by the banking provider. Check the highlighted fields and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "id_doc_country": { - "type": "string", - "enum": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BQ", - "BA", - "BW", - "BV", - "BR", - "IO", - "BN", - "BG", - "BF", - "BI", - "CV", - "KH", - "CM", - "CA", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CD", - "CG", - "CK", - "CR", - "HR", - "CU", - "CW", - "CY", - "CZ", - "CI", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "SZ", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "GF", - "PF", - "TF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GP", - "GU", - "GT", - "GG", - "GN", - "GW", - "GY", - "HT", - "HM", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KP", - "KR", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MQ", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "MM", - "NA", - "NR", - "NP", - "NL", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "NF", - "MP", - "NO", - "OM", - "PK", - "PW", - "PS", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "MK", - "RO", - "RU", - "RW", - "RE", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SX", - "SK", - "SI", - "SB", - "SO", - "ZA", - "GS", - "SS", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "UM", - "US", - "UY", - "UZ", - "VU", - "VE", - "VN", - "VG", - "VI", - "WF", - "EH", - "YE", - "ZM", - "ZW", - "AX" - ], - "example": "BR" + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "500": { + "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "502": { + "description": "Possible error codes: `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "503": { + "description": "Possible error codes: `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + }, + "get": { + "x-sdk": true, + "tags": [ + "Bank Accounts" + ], + "summary": "Retrieve Bank Accounts", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "enum": [ + "verifying", + "approved", + "rejected", + "deprecated" + ] + }, + "required": false, + "name": "status", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "wire", + "ach", + "pix", + "pix_safe", + "ted", + "spei_bitso", + "transfers_bitso", + "ach_cop_bitso", + "international_swift", + "rtp", + "sepa", + "faster_payments" + ] + }, + "required": false, + "name": "type", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "name", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "bank_account_id", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "country", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Get bank accounts", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BankAccountOut" + } + } + } + } + }, + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "id_doc_type": { - "type": "string", - "enum": [ - "PASSPORT", - "ID_CARD", - "DRIVERS" - ], - "example": "PASSPORT" + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "id_doc_front_file": { - "type": "string", - "format": "uri" + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "id_doc_back_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Only image files are accepted (.jpg, .jpeg, .png)" + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "proof_of_address_doc_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "UTILITY_BILL", - "BANK_STATEMENT", - "RENTAL_AGREEMENT", - "TAX_DOCUMENT", - "GOVERNMENT_CORRESPONDENCE" - ], - "example": "UTILITY_BILL" + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{instance_id}/customers/{customer_id}/bank-accounts/{id}": { + "get": { + "x-sdk": true, + "tags": [ + "Bank Accounts" + ], + "summary": "Retrieve Bank Account", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Get bank account", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BankAccountOut" + } + } + } + }, + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "proof_of_address_doc_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Please upload one document that serve as proof of address, this needs to be the same address as the one provided above. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB." + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "ownership_percentage": { - "type": [ - "integer", - "null" - ], - "minimum": 0, - "maximum": 100, - "description": "Ownership percentage of the beneficial owner (0-100)", - "example": 25 + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "title": { - "type": [ - "string", - "null" - ], - "maxLength": 128, - "description": "Job title of the owner", - "example": "CEO" + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "404": { + "description": "Possible error codes: `BANK_ACCOUNTS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "tax_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "SSN", - "ITIN" - ], - "description": "Tax identifier type. Mandatory when country is US; must be SSN or ITIN.", - "example": "SSN" + "examples": { + "BANK_ACCOUNTS_NOT_FOUND": { + "summary": "BANK_ACCOUNTS_NOT_FOUND", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_FOUND", + "message": "bank_account_not_found", + "description": "The requested bank account was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + }, + "delete": { + "x-sdk": true, + "tags": [ + "Bank Accounts" + ], + "summary": "Remove Bank Account", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" + }, + "required": true, + "name": "id", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" + } + ], + "responses": { + "200": { + "description": "Delete bank account", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } + }, + "400": { + "description": "Possible error codes: `BANK_ACCOUNTS_OWNED_BY_PAYABLE`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "BANK_ACCOUNTS_OWNED_BY_PAYABLE": { + "summary": "BANK_ACCOUNTS_OWNED_BY_PAYABLE", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_OWNED_BY_PAYABLE", + "message": "bank_account_owned_by_payable", + "description": "This bank account belongs to an invoice payable and can only be paid through that payable. Quote the payable instead.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15 + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } } - }, - "required": [ - "id" - ] + } } + } + } + } + }, + "/v1/instances/{instance_id}/customers/{customer_id}/virtual-accounts": { + "post": { + "x-sdk": true, + "tags": [ + "Virtual Accounts" + ], + "summary": "Create Virtual Account", + "description": "Creates a virtual account that automatically converts inbound USD deposits (ACH, wire, RTP) into stablecoins sent to the linked wallet. Fees on these automated payins depend on the deposit amount: deposits below $100.00 accrue the BlindPay fee to your billing cycle (charged at the end of the month via the payin's `billing_fee_amount`), while deposits of $100.00 or more are charged at the time of the transaction (deducted from the delivered amount via `transaction_fee_amount`). Every deposit is processed regardless of size and always delivers at least $0.01 on-chain; a partner fee (optional `partner_fee_id`) is collected only from what remains after that.", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" }, - "incorporation_doc_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Please upload your articles of incorporation below. The articles of incorporation or a certificate of incorporation usually includes information like the company name, business purpose, number of shares offered, value of shares, etc. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", - "example": "https://example.com/image.png" - }, - "proof_of_ownership_doc_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Please upload your proof of ownership below. This document usually includes information like the shareholders names and percentages. Only PDF and image files are accepted (.jpg, .jpeg, .png, .pdf) with a maximum size of 3MB.", - "example": "https://example.com/image.png" + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" }, - "source_of_funds_doc_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "business_income", - "gambling_proceeds", - "gifts", - "government_benefits", - "inheritance", - "investment_loans", - "pension_retirement", - "salary", - "sale_of_assets_real_estate", - "savings", - "esops", - "investment_proceeds", - "someone_else_funds" - ], - "example": "business_income" + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" + } + ], + "requestBody": { + "description": "Create a new virtual account", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateVirtualAccountIn" + } + } + } + }, + "responses": { + "200": { + "description": "Create virtual account", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VirtualAccountOut" + } + } + } }, - "source_of_funds_doc_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "example": "https://example.com/image.png" + "400": { + "description": "Possible error codes: `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_ENHANCED_KYC_REQUIRED`, `CUSTOMERS_ID_DOCUMENT_INVALID`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_KYC_NOT_APPROVED`, `CUSTOMERS_OWNERSHIP_INVALID`, `FEES_PARTNER_FEE_EXCEEDED`, `FILES_TOO_LARGE`, `FILES_UNREADABLE`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM`, `VALIDATION_FAILED`, `VALIDATION_MISSING_REQUIRED_FIELDS`, `VIRTUAL_ACCOUNTS_DISABLED`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE`, `VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED`, `WALLETS_NOT_OWNED_BY_CUSTOMER`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "message": "unsupported_banking_partner", + "description": "This banking option is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { + "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "message": "network_not_supported_on_dev_instance", + "description": "This network or token combination is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { + "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "value": { + "success": false, + "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "message": "country_not_supported", + "description": "This country is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ENHANCED_KYC_REQUIRED": { + "summary": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "value": { + "success": false, + "code": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "message": "only_enhanced_kyc_allowed_for_high_risk_countries", + "description": "Individuals from high-risk countries must use enhanced verification (kyc_type: enhanced); standard verification is not available for them. See https://www.blindpay.com/docs/kb/supported-countries for country tiers.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ID_DOCUMENT_INVALID": { + "summary": "CUSTOMERS_ID_DOCUMENT_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_ID_DOCUMENT_INVALID", + "message": "id_doc_is_not_valid_passport_or_national_id", + "description": "The identity document is not accepted for this customer. Use a national ID, a passport with a valid passport number as the tax ID, or a driver license with a valid SSN or ITIN as the tax ID.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_PHONE": { + "summary": "CUSTOMERS_INVALID_PHONE", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_PHONE", + "message": "invalid_phone_number", + "description": "The phone number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_TAX_ID": { + "summary": "CUSTOMERS_INVALID_TAX_ID", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_TAX_ID", + "message": "invalid_cpf_or_rg_tax_id", + "description": "The tax ID provided is not valid. Check the value and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_NOT_APPROVED": { + "summary": "CUSTOMERS_KYC_NOT_APPROVED", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_NOT_APPROVED", + "message": "kyc_not_approved", + "description": "This customer has not completed verification yet. Complete the verification before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_OWNERSHIP_INVALID": { + "summary": "CUSTOMERS_OWNERSHIP_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_OWNERSHIP_INVALID", + "message": "business_owner_required", + "description": "The ownership information for this business customer is incomplete or inconsistent. Review the registered owners and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_PARTNER_FEE_EXCEEDED": { + "summary": "FEES_PARTNER_FEE_EXCEEDED", + "value": { + "success": false, + "code": "FEES_PARTNER_FEE_EXCEEDED", + "message": "partner_fee_exceeded", + "description": "The partner fee exceeds the allowed maximum for this transaction.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_AMOUNT_BELOW_MINIMUM": { + "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "value": { + "success": false, + "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "message": "swift_minimum_is_100_usd", + "description": "The amount is below the minimum for this payment rail.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM": { + "summary": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "value": { + "success": false, + "code": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "message": "otc_provider_minimum_not_met", + "description": "The amount is below the minimum the liquidity provider accepts for this pair. Try a larger amount.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_MISSING_REQUIRED_FIELDS": { + "summary": "VALIDATION_MISSING_REQUIRED_FIELDS", + "value": { + "success": false, + "code": "VALIDATION_MISSING_REQUIRED_FIELDS", + "message": "missing_required_fields", + "description": "Required fields are missing. Provide the missing fields and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_DISABLED": { + "summary": "VIRTUAL_ACCOUNTS_DISABLED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_DISABLED", + "message": "virtual_accounts_not_enabled", + "description": "Virtual accounts are not enabled for this account. Contact support to enable them.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { + "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "message": "id_doc_front_file_required", + "description": "An identity document is required for this customer. Upload the front of a valid document and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE": { + "summary": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "message": "banking_partner_not_eligible_for_customer", + "description": "This banking partner is not available for this customer. Choose a different banking partner.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED": { + "summary": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", + "message": "us_state_not_supported", + "description": "Virtual accounts are not available for this country or region.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_NOT_OWNED_BY_CUSTOMER": { + "summary": "WALLETS_NOT_OWNED_BY_CUSTOMER", + "value": { + "success": false, + "code": "WALLETS_NOT_OWNED_BY_CUSTOMER", + "message": "blockchain_wallet_does_not_belong_to_customer", + "description": "The selected wallet belongs to a different customer. Choose one of this customer's wallets.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "selfie_file": { - "type": [ - "string", - "null" - ], - "format": "uri", - "description": "Only image files are accepted (.jpg, .jpeg, .png)", - "example": "https://example.com/image.png" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "purpose_of_transactions": { - "type": [ - "string", - "null" - ], - "enum": [ - "business_transactions", - "charitable_donations", - "investment_purposes", - "payments_to_friends_or_family_abroad", - "personal_or_living_expenses", - "protect_wealth", - "purchase_good_and_services", - "receive_payment_for_freelancing", - "receive_salary", - "other" - ], - "example": "business_transactions" + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "purpose_of_transactions_explanation": { - "type": [ - "string", - "null" - ], - "example": "I am a business owner and I want to receive payments from my customers" + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `FEES_NOT_FOUND`, `INSTANCES_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_NOT_FOUND": { + "summary": "FEES_NOT_FOUND", + "value": { + "success": false, + "code": "FEES_NOT_FOUND", + "message": "partner_fee_not_found", + "description": "The requested fee configuration was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "INSTANCES_NOT_FOUND": { + "summary": "INSTANCES_NOT_FOUND", + "value": { + "success": false, + "code": "INSTANCES_NOT_FOUND", + "message": "instance_not_found", + "description": "The requested instance was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", + "value": { + "success": false, + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "account_purpose": { - "type": [ - "string", - "null" - ], - "enum": [ - "charitable_donations", - "ecommerce_retail_payments", - "investment_purposes", - "business_expenses", - "payments_to_friends_or_family_abroad", - "personal_or_living_expenses", - "protect_wealth", - "purchase_goods_and_services", - "receive_payments_for_goods_and_services", - "tax_optimization", - "third_party_money_transmission", - "payroll", - "treasury_management", - "other" - ], - "example": "treasury_management" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "account_purpose_other": { - "type": [ - "string", - "null" - ], - "maxLength": 512, - "description": "Required when account_purpose is \"other\". Max 512 characters.", - "example": "Custom account purpose description" + "500": { + "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + }, + "get": { + "x-sdk": true, + "tags": [ + "Virtual Accounts" + ], + "summary": "Retrieve Virtual Accounts", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" }, - "business_type": { - "type": [ - "string", - "null" - ], - "enum": [ - "corporation", - "llc", - "partnership", - "sole_proprietorship", - "trust", - "non_profit" - ], - "example": "llc" + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Get virtual accounts", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VirtualAccountOut" + } + } + } + } }, - "business_description": { - "type": [ - "string", - "null" - ], - "maxLength": 1000, - "example": "Software development company" + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "business_industry": { - "type": [ - "string", - "null" - ], - "enum": [ - "111998", - "112120", - "113310", - "115114", - "541211", - "541810", - "541430", - "541715", - "541930", - "561422", - "561311", - "561612", - "561740", - "561730", - "236115", - "236220", - "237310", - "238210", - "811111", - "812111", - "812112", - "532111", - "624410", - "541922", - "811210", - "812199", - "611110", - "611310", - "611410", - "611710", - "211120", - "212114", - "221310", - "562111", - "562920", - "213112", - "522110", - "522210", - "522320", - "523150", - "523940", - "523999", - "524113", - "813110", - "813211", - "813219", - "551112", - "721110", - "722511", - "722513", - "561510", - "713110", - "713210", - "712110", - "711110", - "711211", - "621111", - "621210", - "622110", - "623110", - "621511", - "623220", - "541940", - "621399", - "621910", - "541110", - "311421", - "337121", - "322220", - "339920", - "334210", - "339930", - "312130", - "334111", - "334118", - "325412", - "339112", - "336110", - "336390", - "315990", - "313110", - "339910", - "516120", - "513130", - "512250", - "519130", - "711410", - "711510", - "531110", - "531120", - "531130", - "531190", - "531210", - "531311", - "531312", - "531320", - "531390", - "454110", - "445110", - "455110", - "457110", - "449210", - "444110", - "459210", - "459120", - "445320", - "458110", - "458210", - "458310", - "455219", - "424210", - "456110", - "446120", - "541511", - "541512", - "541519", - "518210", - "511210", - "517111", - "517112", - "517410", - "481111", - "483111", - "485210", - "488510", - "484121", - "493110", - "423430", - "423690", - "423110", - "423830", - "423840", - "423510", - "424690", - "424990", - "424410", - "424480", - "423940", - "541611", - "541618", - "541330", - "541990", - "541214", - "561499" - ], - "example": "541511" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "estimated_annual_revenue": { - "type": [ - "string", - "null" - ], - "enum": [ - "0_99999", - "100000_999999", - "1000000_9999999", - "10000000_49999999", - "50000000_249999999", - "250000000_plus" - ], - "example": "1000000_9999999" + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "source_of_wealth": { - "type": [ - "string", - "null" - ], - "enum": [ - "business_dividends_or_profits", - "investments", - "asset_sales", - "client_investor_contributions", - "gambling", - "charitable_contributions", - "inheritance", - "affiliate_or_royalty_income" - ], - "example": "affiliate_or_royalty_income" + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "publicly_traded": { - "type": [ - "boolean", - "null" - ], - "example": false + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/instances/{instance_id}/customers/{customer_id}/virtual-accounts/{id}": { + "get": { + "x-sdk": true, + "tags": [ + "Virtual Accounts" + ], + "summary": "Retrieve Virtual Account", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" }, - "occupation": { - "type": [ - "string", - "null" - ], - "maxLength": 255, - "example": "Software Engineer" + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" }, - "external_id": { - "type": [ - "string", - "null" - ], - "example": "your_company_external_id" + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Get virtual account", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/VirtualAccountOut" + }, + { + "type": [ + "object", + "null" + ] + } + ] + } + } + } + }, + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "tos_id": { - "type": [ - "string", - "null" - ], - "minLength": 15, - "maxLength": 15, - "example": "to_000000000000" + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "additional_info": { - "type": [ - "array", - "null" - ], - "items": { - "$ref": "#/components/schemas/AdditionalInfoItem" - }, - "description": "Optional extra documents or notes for this customer. `label` is a known category, `value` is either a URL to upload or a free-text description. Any URLs are downloaded and re-hosted on Blindpay storage before being stored.", - "example": [ - { - "label": "EIN_LETTER", - "value": "https://example.com/ein.pdf" - }, - { - "label": "FLOW_OF_FUNDS", - "value": "Funds originate from US payroll deposits, forwarded weekly to customer." + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } } - ] - } - }, - "required": [ - "email", - "country" - ] - }, - "GetCustomerLimitsOut": { - "type": "object", - "properties": { - "limits": { - "type": "object", - "properties": { - "payin": { - "type": "object", - "properties": { - "daily": { - "type": "number" - }, - "monthly": { - "type": "number" + } + }, + "422": { + "description": "Possible error codes: `DATA_INTEGRITY_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "DATA_INTEGRITY_ERROR": { + "summary": "DATA_INTEGRITY_ERROR", + "value": { + "success": false, + "code": "DATA_INTEGRITY_ERROR", + "message": "data_integrity_error", + "description": "This record could not be loaded because it contains invalid stored data. Contact support with the ID below.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "required": [ - "daily", - "monthly" - ] - }, - "payout": { - "type": "object", - "properties": { - "daily": { - "type": "number" - }, - "monthly": { - "type": "number" + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } + } + } + } + }, + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "required": [ - "daily", - "monthly" - ] + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } } - }, - "required": [ - "payin", - "payout" - ] - } - }, - "required": [ - "limits" - ], - "example": { - "limits": { - "payin": { - "daily": 500000, - "monthly": 2000000 - }, - "payout": { - "daily": 300000, - "monthly": 1000000 } } } }, - "RfiField": { - "type": "object", - "properties": { - "key": { - "type": "string", - "minLength": 1, - "maxLength": 128 + "put": { + "x-sdk": true, + "tags": [ + "Virtual Accounts" + ], + "summary": "Update Virtual Account", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" }, - "label": { - "type": "string", - "minLength": 1, - "maxLength": 256 + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" }, - "regex": { - "type": "string", - "maxLength": 512 + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" + }, + "required": true, + "name": "id", + "in": "path" }, - "required": { - "type": "boolean" + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" + } + ], + "requestBody": { + "description": "Update a virtual account", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateVirtualAccountIn" + } + } + } + }, + "responses": { + "200": { + "description": "Update virtual account", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + } }, - "items": { - "type": "array", - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" + "400": { + "description": "Possible error codes: `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_ENHANCED_KYC_REQUIRED`, `CUSTOMERS_ID_DOCUMENT_INVALID`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_KYC_NOT_APPROVED`, `CUSTOMERS_OWNERSHIP_INVALID`, `FEES_PARTNER_FEE_EXCEEDED`, `FILES_TOO_LARGE`, `FILES_UNREADABLE`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM`, `VALIDATION_FAILED`, `VALIDATION_MISSING_REQUIRED_FIELDS`, `VIRTUAL_ACCOUNTS_DISABLED`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE`, `VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED`, `WALLETS_NOT_OWNED_BY_CUSTOMER`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - "value": { - "type": "string" + "examples": { + "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "message": "unsupported_banking_partner", + "description": "This banking option is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { + "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "message": "network_not_supported_on_dev_instance", + "description": "This network or token combination is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { + "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "value": { + "success": false, + "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "message": "country_not_supported", + "description": "This country is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ENHANCED_KYC_REQUIRED": { + "summary": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "value": { + "success": false, + "code": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "message": "only_enhanced_kyc_allowed_for_high_risk_countries", + "description": "Individuals from high-risk countries must use enhanced verification (kyc_type: enhanced); standard verification is not available for them. See https://www.blindpay.com/docs/kb/supported-countries for country tiers.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ID_DOCUMENT_INVALID": { + "summary": "CUSTOMERS_ID_DOCUMENT_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_ID_DOCUMENT_INVALID", + "message": "id_doc_is_not_valid_passport_or_national_id", + "description": "The identity document is not accepted for this customer. Use a national ID, a passport with a valid passport number as the tax ID, or a driver license with a valid SSN or ITIN as the tax ID.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_PHONE": { + "summary": "CUSTOMERS_INVALID_PHONE", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_PHONE", + "message": "invalid_phone_number", + "description": "The phone number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_TAX_ID": { + "summary": "CUSTOMERS_INVALID_TAX_ID", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_TAX_ID", + "message": "invalid_cpf_or_rg_tax_id", + "description": "The tax ID provided is not valid. Check the value and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_NOT_APPROVED": { + "summary": "CUSTOMERS_KYC_NOT_APPROVED", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_NOT_APPROVED", + "message": "kyc_not_approved", + "description": "This customer has not completed verification yet. Complete the verification before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_OWNERSHIP_INVALID": { + "summary": "CUSTOMERS_OWNERSHIP_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_OWNERSHIP_INVALID", + "message": "business_owner_required", + "description": "The ownership information for this business customer is incomplete or inconsistent. Review the registered owners and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_PARTNER_FEE_EXCEEDED": { + "summary": "FEES_PARTNER_FEE_EXCEEDED", + "value": { + "success": false, + "code": "FEES_PARTNER_FEE_EXCEEDED", + "message": "partner_fee_exceeded", + "description": "The partner fee exceeds the allowed maximum for this transaction.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_AMOUNT_BELOW_MINIMUM": { + "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "value": { + "success": false, + "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "message": "swift_minimum_is_100_usd", + "description": "The amount is below the minimum for this payment rail.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM": { + "summary": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "value": { + "success": false, + "code": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "message": "otc_provider_minimum_not_met", + "description": "The amount is below the minimum the liquidity provider accepts for this pair. Try a larger amount.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_MISSING_REQUIRED_FIELDS": { + "summary": "VALIDATION_MISSING_REQUIRED_FIELDS", + "value": { + "success": false, + "code": "VALIDATION_MISSING_REQUIRED_FIELDS", + "message": "missing_required_fields", + "description": "Required fields are missing. Provide the missing fields and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_DISABLED": { + "summary": "VIRTUAL_ACCOUNTS_DISABLED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_DISABLED", + "message": "virtual_accounts_not_enabled", + "description": "Virtual accounts are not enabled for this account. Contact support to enable them.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { + "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "message": "id_doc_front_file_required", + "description": "An identity document is required for this customer. Upload the front of a valid document and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE": { + "summary": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "message": "banking_partner_not_eligible_for_customer", + "description": "This banking partner is not available for this customer. Choose a different banking partner.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED": { + "summary": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", + "message": "us_state_not_supported", + "description": "Virtual accounts are not available for this country or region.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_NOT_OWNED_BY_CUSTOMER": { + "summary": "WALLETS_NOT_OWNED_BY_CUSTOMER", + "value": { + "success": false, + "code": "WALLETS_NOT_OWNED_BY_CUSTOMER", + "message": "blockchain_wallet_does_not_belong_to_customer", + "description": "The selected wallet belongs to a different customer. Choose one of this customer's wallets.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } } - }, - "required": [ - "label", - "value" - ] + } } }, - "multiple": { - "type": "boolean" - }, - "aiprise_document_type": { - "type": "string", - "enum": [ - "ADDRESS_PROOF_DOCUMENT", - "SOURCE_OF_FUNDS_DOCUMENT", - "BANK_STATEMENT_DOCUMENT", - "USER_SELFIE", - "TAX_CERTIFICATE", - "VISA_DOCUMENT", - "OTHER" - ] - } - }, - "required": [ - "key", - "label", - "required" - ] - }, - "RfiSection": { - "type": "object", - "properties": { - "title": { - "type": "string", - "minLength": 1, - "maxLength": 256 - }, - "description": { - "type": "string", - "maxLength": 4096 - }, - "supporting_document": { - "type": "string", - "format": "uri" - }, - "fields": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RfiField" - }, - "minItems": 1, - "maxItems": 20 - } - }, - "required": [ - "title", - "description", - "fields" - ] - }, - "Rfi": { - "type": [ - "object", - "null" - ], - "properties": { - "id": { - "type": "string" - }, - "customer_id": { - "type": "string" - }, - "instance_id": { - "type": "string" - }, - "status": { - "type": "string", - "enum": [ - "pending", - "submitted", - "expired", - "cancelled" - ] + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "request": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RfiSection" - }, - "minItems": 1, - "maxItems": 20 + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "response": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { - "type": "string", - "maxLength": 4096 + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `FEES_NOT_FOUND`, `INSTANCES_NOT_FOUND`, `VIRTUAL_ACCOUNTS_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - { - "type": "array", - "items": { - "type": "string", - "format": "uri" + "examples": { + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } }, - "maxItems": 20 + "FEES_NOT_FOUND": { + "summary": "FEES_NOT_FOUND", + "value": { + "success": false, + "code": "FEES_NOT_FOUND", + "message": "partner_fee_not_found", + "description": "The requested fee configuration was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "INSTANCES_NOT_FOUND": { + "summary": "INSTANCES_NOT_FOUND", + "value": { + "success": false, + "code": "INSTANCES_NOT_FOUND", + "message": "instance_not_found", + "description": "The requested instance was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_NOT_FOUND": { + "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "message": "virtual_account_not_found", + "description": "The requested virtual account was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", + "value": { + "success": false, + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } } - ] + } } }, - "expires_at": { - "type": "string", - "format": "date-time" - }, - "submitted_at": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "customer_type": { - "type": "string", - "enum": [ - "individual", - "business" - ] - }, - "customer_aiprise_session_id": { - "type": [ - "string", - "null" - ] - }, - "customer_aiprise_user_profile_id": { - "type": [ - "string", - "null" - ] - }, - "customer_kyc_status": { - "type": "string" - } - }, - "required": [ - "id", - "customer_id", - "instance_id", - "status", - "request", - "response", - "expires_at", - "submitted_at", - "created_at" - ] - }, - "InstanceRfi": { - "type": [ - "object", - "null" - ], - "properties": { - "id": { - "type": "string" - }, - "instance_id": { - "type": "string" - }, - "status": { - "type": "string", - "enum": [ - "pending", - "submitted", - "expired", - "cancelled" - ] - }, - "request": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RfiSection" - }, - "minItems": 1, - "maxItems": 20 + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } }, - "response": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { - "type": "string", - "maxLength": 4096 + "500": { + "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" }, - { - "type": "array", - "items": { - "type": "string", - "format": "uri" + "examples": { + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } }, - "maxItems": 20 + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } } - ] + } } - }, - "expires_at": { - "type": "string", - "format": "date-time" - }, - "submitted_at": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "created_at": { - "type": "string", - "format": "date-time" } - }, - "required": [ - "id", - "instance_id", - "status", - "request", - "response", - "expires_at", - "submitted_at", - "created_at" - ] + } } }, - "parameters": {} - }, - "paths": { - "/v1/instances/{id}": { - "put": { - "x-sdk": true, + "/v1/instances/{instance_id}/customers/{customer_id}/virtual-accounts/{id}/simulate-breb-deposit": { + "post": { + "x-sdk": false, + "x-mcp": false, "tags": [ - "Instances" + "Virtual Accounts" ], - "summary": "Update Instance", + "summary": "Simulate Bre-B Deposit", + "description": "Development instances only. Simulates a COP deposit arriving on the virtual account's Bre-B key, creating a payin at the live rate exactly as a real deposit would.", "parameters": [ { "schema": { @@ -32701,34 +50861,46 @@ "example": "in_000000000000" }, "required": true, - "name": "id", + "name": "instance_id", "in": "path" }, { "schema": { "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" }, - "required": false, - "name": "Idempotency-Key", - "in": "header" + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" + }, + "required": true, + "name": "id", + "in": "path" } ], "requestBody": { - "description": "Update instance", + "description": "Simulated deposit", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateInstanceIn" + "$ref": "#/components/schemas/SimulateBrebDepositIn" } } } }, "responses": { "200": { - "description": "Instance updated", + "description": "Deposit simulation dispatched", "content": { "application/json": { "schema": { @@ -32738,13 +50910,167 @@ } }, "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_ENHANCED_KYC_REQUIRED`, `CUSTOMERS_ID_DOCUMENT_INVALID`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_KYC_NOT_APPROVED`, `CUSTOMERS_OWNERSHIP_INVALID`, `FEES_PARTNER_FEE_EXCEEDED`, `FILES_TOO_LARGE`, `FILES_UNREADABLE`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM`, `VALIDATION_FAILED`, `VALIDATION_MISSING_REQUIRED_FIELDS`, `VIRTUAL_ACCOUNTS_DISABLED`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE`, `VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED`, `WALLETS_NOT_OWNED_BY_CUSTOMER`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "message": "unsupported_banking_partner", + "description": "This banking option is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { + "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "message": "network_not_supported_on_dev_instance", + "description": "This network or token combination is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { + "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "value": { + "success": false, + "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "message": "country_not_supported", + "description": "This country is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ENHANCED_KYC_REQUIRED": { + "summary": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "value": { + "success": false, + "code": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "message": "only_enhanced_kyc_allowed_for_high_risk_countries", + "description": "Individuals from high-risk countries must use enhanced verification (kyc_type: enhanced); standard verification is not available for them. See https://www.blindpay.com/docs/kb/supported-countries for country tiers.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ID_DOCUMENT_INVALID": { + "summary": "CUSTOMERS_ID_DOCUMENT_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_ID_DOCUMENT_INVALID", + "message": "id_doc_is_not_valid_passport_or_national_id", + "description": "The identity document is not accepted for this customer. Use a national ID, a passport with a valid passport number as the tax ID, or a driver license with a valid SSN or ITIN as the tax ID.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_PHONE": { + "summary": "CUSTOMERS_INVALID_PHONE", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_PHONE", + "message": "invalid_phone_number", + "description": "The phone number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_TAX_ID": { + "summary": "CUSTOMERS_INVALID_TAX_ID", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_TAX_ID", + "message": "invalid_cpf_or_rg_tax_id", + "description": "The tax ID provided is not valid. Check the value and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_NOT_APPROVED": { + "summary": "CUSTOMERS_KYC_NOT_APPROVED", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_NOT_APPROVED", + "message": "kyc_not_approved", + "description": "This customer has not completed verification yet. Complete the verification before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_OWNERSHIP_INVALID": { + "summary": "CUSTOMERS_OWNERSHIP_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_OWNERSHIP_INVALID", + "message": "business_owner_required", + "description": "The ownership information for this business customer is incomplete or inconsistent. Review the registered owners and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_PARTNER_FEE_EXCEEDED": { + "summary": "FEES_PARTNER_FEE_EXCEEDED", + "value": { + "success": false, + "code": "FEES_PARTNER_FEE_EXCEEDED", + "message": "partner_fee_exceeded", + "description": "The partner fee exceeds the allowed maximum for this transaction.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_AMOUNT_BELOW_MINIMUM": { + "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "value": { + "success": false, + "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "message": "swift_minimum_is_100_usd", + "description": "The amount is below the minimum for this payment rail.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM": { + "summary": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "value": { + "success": false, + "code": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "message": "otc_provider_minimum_not_met", + "description": "The amount is below the minimum the liquidity provider accepts for this pair. Try a larger amount.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -32755,6 +51081,72 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "VALIDATION_MISSING_REQUIRED_FIELDS": { + "summary": "VALIDATION_MISSING_REQUIRED_FIELDS", + "value": { + "success": false, + "code": "VALIDATION_MISSING_REQUIRED_FIELDS", + "message": "missing_required_fields", + "description": "Required fields are missing. Provide the missing fields and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_DISABLED": { + "summary": "VIRTUAL_ACCOUNTS_DISABLED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_DISABLED", + "message": "virtual_accounts_not_enabled", + "description": "Virtual accounts are not enabled for this account. Contact support to enable them.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { + "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "message": "id_doc_front_file_required", + "description": "An identity document is required for this customer. Upload the front of a valid document and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE": { + "summary": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "message": "banking_partner_not_eligible_for_customer", + "description": "This banking partner is not available for this customer. Choose a different banking partner.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED": { + "summary": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", + "message": "us_state_not_supported", + "description": "Virtual accounts are not available for this country or region.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_NOT_OWNED_BY_CUSTOMER": { + "summary": "WALLETS_NOT_OWNED_BY_CUSTOMER", + "value": { + "success": false, + "code": "WALLETS_NOT_OWNED_BY_CUSTOMER", + "message": "blockchain_wallet_does_not_belong_to_customer", + "description": "The selected wallet belongs to a different customer. Choose one of this customer's wallets.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } @@ -32806,6 +51198,73 @@ } } }, + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `FEES_NOT_FOUND`, `INSTANCES_NOT_FOUND`, `VIRTUAL_ACCOUNTS_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_NOT_FOUND": { + "summary": "FEES_NOT_FOUND", + "value": { + "success": false, + "code": "FEES_NOT_FOUND", + "message": "partner_fee_not_found", + "description": "The requested fee configuration was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "INSTANCES_NOT_FOUND": { + "summary": "INSTANCES_NOT_FOUND", + "value": { + "success": false, + "code": "INSTANCES_NOT_FOUND", + "message": "instance_not_found", + "description": "The requested instance was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_NOT_FOUND": { + "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "message": "virtual_account_not_found", + "description": "The requested virtual account was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", + "value": { + "success": false, + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -32819,7 +51278,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -32830,13 +51289,24 @@ } }, "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -32847,19 +51317,34 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } } } } - }, - "delete": { - "x-sdk": true, + } + }, + "/v1/instances/{instance_id}/customers/{customer_id}/virtual-accounts/{id}/simulate-spei-deposit": { + "post": { + "x-sdk": false, + "x-mcp": false, "tags": [ - "Instances" + "Virtual Accounts" ], - "summary": "Delete Instance", + "summary": "Simulate SPEI Deposit", + "description": "Development instances only. Simulates an MXN deposit arriving on the virtual account's CLABE, creating a payin at the live rate exactly as a real deposit would.", "parameters": [ { "schema": { @@ -32869,24 +51354,46 @@ "example": "in_000000000000" }, "required": true, - "name": "id", + "name": "instance_id", "in": "path" }, { "schema": { "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" }, - "required": false, - "name": "Idempotency-Key", - "in": "header" + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" + }, + "required": true, + "name": "id", + "in": "path" } ], + "requestBody": { + "description": "Simulated deposit", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SimulateSpeiDepositIn" + } + } + } + }, "responses": { "200": { - "description": "Instance deleted", + "description": "Deposit simulation dispatched", "content": { "application/json": { "schema": { @@ -32896,20 +51403,163 @@ } }, "400": { - "description": "Possible error codes: `AUTH_FORBIDDEN`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_ENHANCED_KYC_REQUIRED`, `CUSTOMERS_ID_DOCUMENT_INVALID`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_KYC_NOT_APPROVED`, `CUSTOMERS_OWNERSHIP_INVALID`, `FEES_PARTNER_FEE_EXCEEDED`, `FILES_TOO_LARGE`, `FILES_UNREADABLE`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM`, `VALIDATION_FAILED`, `VALIDATION_MISSING_REQUIRED_FIELDS`, `VIRTUAL_ACCOUNTS_DISABLED`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE`, `VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED`, `WALLETS_NOT_OWNED_BY_CUSTOMER`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "AUTH_FORBIDDEN": { - "summary": "AUTH_FORBIDDEN", + "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", "value": { "success": false, - "code": "AUTH_FORBIDDEN", - "message": "user_not_allowed", - "description": "You do not have permission to perform this action.", + "code": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "message": "unsupported_banking_partner", + "description": "This banking option is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { + "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "message": "network_not_supported_on_dev_instance", + "description": "This network or token combination is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { + "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "value": { + "success": false, + "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "message": "country_not_supported", + "description": "This country is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ENHANCED_KYC_REQUIRED": { + "summary": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "value": { + "success": false, + "code": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "message": "only_enhanced_kyc_allowed_for_high_risk_countries", + "description": "Individuals from high-risk countries must use enhanced verification (kyc_type: enhanced); standard verification is not available for them. See https://www.blindpay.com/docs/kb/supported-countries for country tiers.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ID_DOCUMENT_INVALID": { + "summary": "CUSTOMERS_ID_DOCUMENT_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_ID_DOCUMENT_INVALID", + "message": "id_doc_is_not_valid_passport_or_national_id", + "description": "The identity document is not accepted for this customer. Use a national ID, a passport with a valid passport number as the tax ID, or a driver license with a valid SSN or ITIN as the tax ID.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_PHONE": { + "summary": "CUSTOMERS_INVALID_PHONE", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_PHONE", + "message": "invalid_phone_number", + "description": "The phone number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_TAX_ID": { + "summary": "CUSTOMERS_INVALID_TAX_ID", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_TAX_ID", + "message": "invalid_cpf_or_rg_tax_id", + "description": "The tax ID provided is not valid. Check the value and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_NOT_APPROVED": { + "summary": "CUSTOMERS_KYC_NOT_APPROVED", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_NOT_APPROVED", + "message": "kyc_not_approved", + "description": "This customer has not completed verification yet. Complete the verification before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_OWNERSHIP_INVALID": { + "summary": "CUSTOMERS_OWNERSHIP_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_OWNERSHIP_INVALID", + "message": "business_owner_required", + "description": "The ownership information for this business customer is incomplete or inconsistent. Review the registered owners and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_PARTNER_FEE_EXCEEDED": { + "summary": "FEES_PARTNER_FEE_EXCEEDED", + "value": { + "success": false, + "code": "FEES_PARTNER_FEE_EXCEEDED", + "message": "partner_fee_exceeded", + "description": "The partner fee exceeds the allowed maximum for this transaction.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_AMOUNT_BELOW_MINIMUM": { + "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "value": { + "success": false, + "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "message": "swift_minimum_is_100_usd", + "description": "The amount is below the minimum for this payment rail.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM": { + "summary": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "value": { + "success": false, + "code": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "message": "otc_provider_minimum_not_met", + "description": "The amount is below the minimum the liquidity provider accepts for this pair. Try a larger amount.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -32924,6 +51574,72 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "VALIDATION_MISSING_REQUIRED_FIELDS": { + "summary": "VALIDATION_MISSING_REQUIRED_FIELDS", + "value": { + "success": false, + "code": "VALIDATION_MISSING_REQUIRED_FIELDS", + "message": "missing_required_fields", + "description": "Required fields are missing. Provide the missing fields and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_DISABLED": { + "summary": "VIRTUAL_ACCOUNTS_DISABLED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_DISABLED", + "message": "virtual_accounts_not_enabled", + "description": "Virtual accounts are not enabled for this account. Contact support to enable them.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { + "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "message": "id_doc_front_file_required", + "description": "An identity document is required for this customer. Upload the front of a valid document and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE": { + "summary": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "message": "banking_partner_not_eligible_for_customer", + "description": "This banking partner is not available for this customer. Choose a different banking partner.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED": { + "summary": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", + "message": "us_state_not_supported", + "description": "Virtual accounts are not available for this country or region.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_NOT_OWNED_BY_CUSTOMER": { + "summary": "WALLETS_NOT_OWNED_BY_CUSTOMER", + "value": { + "success": false, + "code": "WALLETS_NOT_OWNED_BY_CUSTOMER", + "message": "blockchain_wallet_does_not_belong_to_customer", + "description": "The selected wallet belongs to a different customer. Choose one of this customer's wallets.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } @@ -32975,6 +51691,73 @@ } } }, + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `FEES_NOT_FOUND`, `INSTANCES_NOT_FOUND`, `VIRTUAL_ACCOUNTS_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_NOT_FOUND": { + "summary": "FEES_NOT_FOUND", + "value": { + "success": false, + "code": "FEES_NOT_FOUND", + "message": "partner_fee_not_found", + "description": "The requested fee configuration was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "INSTANCES_NOT_FOUND": { + "summary": "INSTANCES_NOT_FOUND", + "value": { + "success": false, + "code": "INSTANCES_NOT_FOUND", + "message": "instance_not_found", + "description": "The requested instance was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_NOT_FOUND": { + "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "message": "virtual_account_not_found", + "description": "The requested virtual account was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", + "value": { + "success": false, + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -32988,7 +51771,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -32999,13 +51782,24 @@ } }, "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -33016,6 +51810,17 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } @@ -33024,13 +51829,13 @@ } } }, - "/v1/instances/{id}/members": { + "/v1/instances/{instance_id}/customers/{customer_id}/blockchain-wallets/sign-message": { "get": { "x-sdk": true, "tags": [ - "Instances" + "Blockchain Wallets" ], - "summary": "Retrieve Instance Members", + "summary": "Retrieve Blockchain Wallet Message", "parameters": [ { "schema": { @@ -33040,95 +51845,29 @@ "example": "in_000000000000" }, "required": true, - "name": "id", + "name": "instance_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", "in": "path" } ], "responses": { "200": { - "description": "Retrieve instance members", + "description": "Get blockchain wallet sign message", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "us_000000000000" - }, - "email": { - "type": "string", - "format": "email", - "example": "email@example.com" - }, - "first_name": { - "type": "string", - "minLength": 1, - "maxLength": 100, - "example": "Harry" - }, - "middle_name": { - "type": [ - "string", - "null" - ], - "minLength": 1, - "maxLength": 100, - "example": "James" - }, - "last_name": { - "type": "string", - "minLength": 1, - "maxLength": 100, - "example": "Potter" - }, - "image_url": { - "type": "string", - "format": "uri", - "example": "https://example.com/image.png" - }, - "created_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2021-01-01T00:00:00Z" - }, - "has_passkey": { - "type": [ - "boolean", - "null" - ], - "example": true - }, - "role": { - "type": "string", - "enum": [ - "owner", - "admin", - "finance", - "checker", - "operations", - "developer", - "viewer" - ], - "example": "admin" - } - }, - "required": [ - "id", - "email", - "first_name", - "last_name", - "image_url", - "role" - ] - } + "$ref": "#/components/schemas/BlockchainWalletMessageOut" } } } @@ -33215,7 +51954,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -33251,28 +51990,35 @@ } } }, - "/v1/instances/{id}/members/{user_id}": { - "delete": { + "/v1/instances/{instance_id}/customers/{customer_id}/blockchain-wallets": { + "post": { "x-sdk": true, "tags": [ - "Instances" + "Blockchain Wallets" ], - "summary": "Delete Member from Instance", + "summary": "Add Blockchain Wallet", "parameters": [ { "schema": { - "type": "string" + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" }, "required": true, - "name": "id", + "name": "instance_id", "in": "path" }, { "schema": { - "type": "string" + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" }, "required": true, - "name": "user_id", + "name": "customer_id", "in": "path" }, { @@ -33287,25 +52033,46 @@ "in": "header" } ], + "requestBody": { + "description": "Create a new blockchain wallet", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateBlockchainWalletIn" + } + } + } + }, "responses": { "200": { - "description": "Member deleted from instance successfully", + "description": "Add blockchain wallet", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Success" + "$ref": "#/components/schemas/BlockchainWalletOut" } } } }, "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `VALIDATION_FAILED`, `WALLETS_SELF_CUSTODY_REQUIRED`, `WEBHOOKS_SIGNATURE_INVALID`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { + "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "message": "network_not_supported_on_dev_instance", + "description": "This network or token combination is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -33316,6 +52083,28 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "WALLETS_SELF_CUSTODY_REQUIRED": { + "summary": "WALLETS_SELF_CUSTODY_REQUIRED", + "value": { + "success": false, + "code": "WALLETS_SELF_CUSTODY_REQUIRED", + "message": "self_custody_required", + "description": "Brazilian customers must declare whether the wallet is self-custodied. Send is_self_custody as true or false.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WEBHOOKS_SIGNATURE_INVALID": { + "summary": "WEBHOOKS_SIGNATURE_INVALID", + "value": { + "success": false, + "code": "WEBHOOKS_SIGNATURE_INVALID", + "message": "invalid_signature", + "description": "The webhook signature is missing or invalid.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } @@ -33367,6 +52156,29 @@ } } }, + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -33380,7 +52192,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -33415,58 +52227,47 @@ } } }, - "put": { + "get": { "x-sdk": true, "tags": [ - "Instances" + "Blockchain Wallets" ], - "summary": "Update Instance Member Role", + "summary": "Retrieve Blockchain Wallets", "parameters": [ { "schema": { - "type": "string" + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" }, "required": true, - "name": "id", + "name": "instance_id", "in": "path" }, { "schema": { - "type": "string" + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" }, "required": true, - "name": "user_id", + "name": "customer_id", "in": "path" - }, - { - "schema": { - "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "required": false, - "name": "Idempotency-Key", - "in": "header" } ], - "requestBody": { - "description": "Update instance member role", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateInstanceMemberIn" - } - } - } - }, "responses": { "200": { - "description": "Member role updated successfully", + "description": "Get blockchain wallets", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Success" + "type": "array", + "items": { + "$ref": "#/components/schemas/BlockchainWalletOut" + } } } } @@ -33553,7 +52354,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -33589,54 +52390,56 @@ } } }, - "/v1/instances/{id}/ownership": { - "post": { + "/v1/instances/{instance_id}/customers/{customer_id}/blockchain-wallets/{id}": { + "get": { "x-sdk": true, "tags": [ - "Instances" + "Blockchain Wallets" ], - "summary": "Migrate Instance Ownership", + "summary": "Retrieve Blockchain Wallet", "parameters": [ { "schema": { "type": "string", "minLength": 15, "maxLength": 15, - "example": "in_000000000000" + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" }, "required": true, "name": "id", "in": "path" - }, - { - "schema": { - "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "required": false, - "name": "Idempotency-Key", - "in": "header" } ], - "requestBody": { - "description": "Transfer instance ownership to another current member", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MigrateInstanceOwnershipIn" - } - } - } - }, "responses": { "200": { - "description": "Ownership transferred", + "description": "Get blockchain wallet", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Success" + "$ref": "#/components/schemas/BlockchainWalletOut" } } } @@ -33710,6 +52513,29 @@ } } }, + "422": { + "description": "Possible error codes: `DATA_INTEGRITY_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "DATA_INTEGRITY_ERROR": { + "summary": "DATA_INTEGRITY_ERROR", + "value": { + "success": false, + "code": "DATA_INTEGRITY_ERROR", + "message": "data_integrity_error", + "description": "This record could not be loaded because it contains invalid stored data. Contact support with the ID below.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -33723,7 +52549,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -33757,16 +52583,13 @@ } } } - } - }, - "/v1/instances/{instance_id}/rfi": { - "get": { + }, + "delete": { "x-sdk": true, "tags": [ - "Instances" + "Blockchain Wallets" ], - "summary": "Get Open RFI for Instance", - "description": "Returns the open (pending) RFI for this instance, or null if the instance has no pending RFI.", + "summary": "Remove Blockchain Wallet", "parameters": [ { "schema": { @@ -33778,21 +52601,55 @@ "required": true, "name": "instance_id", "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" + }, + "required": true, + "name": "id", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" } ], "responses": { "200": { - "description": "Open instance RFI, or null if none", + "description": "Delete blockchain wallet", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InstanceRfi" + "$ref": "#/components/schemas/Success" } } } }, "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `VALIDATION_FAILED`, `WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { @@ -33809,6 +52666,17 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT": { + "summary": "WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT", + "value": { + "success": false, + "code": "WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT", + "message": "wallet_attached_to_virtual_account", + "description": "This wallet is attached to a virtual account and cannot be deleted. Delete the virtual account first.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } @@ -33860,6 +52728,29 @@ } } }, + "404": { + "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", + "value": { + "success": false, + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -33873,7 +52764,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -33884,24 +52775,13 @@ } }, "500": { - "description": "Possible error codes: `COMPLIANCE_RFI_INVALID`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "COMPLIANCE_RFI_INVALID": { - "summary": "COMPLIANCE_RFI_INVALID", - "value": { - "success": false, - "code": "COMPLIANCE_RFI_INVALID", - "message": "rfi_request_corrupt", - "description": "The information request could not be processed. Check the submitted fields.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -33919,13 +52799,13 @@ } } }, - "post": { + "patch": { "x-sdk": true, "tags": [ - "Instances" + "Blockchain Wallets" ], - "summary": "Submit Instance RFI Response", - "description": "Submit a flat response object for the open instance RFI. Standalone: submitting does not change any instance or onboarding status. Returns `{ success: false, reason }` when no pending RFI exists, callers should refetch the RFI state instead of retrying.", + "summary": "Set Blockchain Wallet Self-Custody", + "description": "Declares whether the customer holds the private keys of this wallet. Only works while is_self_custody is null; once saved it cannot be changed.", "parameters": [ { "schema": { @@ -33937,62 +52817,59 @@ "required": true, "name": "instance_id", "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" + }, + "required": true, + "name": "id", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" } ], "requestBody": { + "description": "Self-custody answer", "content": { "application/json": { "schema": { - "type": "object", - "additionalProperties": {} + "$ref": "#/components/schemas/UpdateBlockchainWalletIn" } } } }, "responses": { "200": { - "description": "RFI submitted (success: true) or rejected because no pending RFI exists (success: false)", + "description": "Updated blockchain wallet", "content": { "application/json": { "schema": { - "anyOf": [ - { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "enum": [ - true - ] - } - }, - "required": [ - "success" - ] - }, - { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "enum": [ - false - ] - }, - "reason": { - "type": "string", - "enum": [ - "no_pending_rfi", - "already_resolved" - ] - } - }, - "required": [ - "success", - "reason" - ] - } - ] + "$ref": "#/components/schemas/BlockchainWalletOut" } } } @@ -34066,6 +52943,52 @@ } } }, + "404": { + "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", + "value": { + "success": false, + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "409": { + "description": "Possible error codes: `WALLETS_SELF_CUSTODY_ALREADY_SET`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "WALLETS_SELF_CUSTODY_ALREADY_SET": { + "summary": "WALLETS_SELF_CUSTODY_ALREADY_SET", + "value": { + "success": false, + "code": "WALLETS_SELF_CUSTODY_ALREADY_SET", + "message": "self_custody_already_set", + "description": "The self-custody answer for this wallet was already saved and cannot be changed. Contact support if it is wrong.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -34079,7 +53002,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -34090,24 +53013,13 @@ } }, "500": { - "description": "Possible error codes: `COMPLIANCE_RFI_INVALID`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "COMPLIANCE_RFI_INVALID": { - "summary": "COMPLIANCE_RFI_INVALID", - "value": { - "success": false, - "code": "COMPLIANCE_RFI_INVALID", - "message": "rfi_request_corrupt", - "description": "The information request could not be processed. Check the submitted fields.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -34126,13 +53038,13 @@ } } }, - "/v1/e/instances/{instance_id}/tos": { + "/v1/instances/{instance_id}/customers/{customer_id}/bank-accounts/{bank_account_id}/offramp-wallets": { "post": { "x-sdk": true, "tags": [ - "Terms Of Service" + "Offramp Wallets" ], - "summary": "Initiate Terms of Service", + "summary": "Create Offramp Wallet", "parameters": [ { "schema": { @@ -34144,37 +53056,200 @@ "required": true, "name": "instance_id", "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "ba_000000000000" + }, + "required": true, + "name": "bank_account_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" } ], "requestBody": { - "description": "Initiate a new terms of service", + "description": "Create a new offramp wallet", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InitiateTosIn" + "type": "object", + "properties": { + "external_id": { + "type": [ + "string", + "null" + ], + "example": "your_external_id" + }, + "network": { + "type": "string", + "enum": [ + "tron", + "solana", + "solana_devnet", + "arbitrum", + "base", + "ethereum", + "polygon", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "polygon_amoy", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "tron" + } + }, + "required": [ + "network" + ] } } } }, "responses": { "200": { - "description": "Initiate terms of service", + "description": "Create offramp wallet", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InitiateTosOut" + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "ow_000000000000" + }, + "external_id": { + "type": [ + "string", + "null" + ], + "example": "your_external_id" + }, + "circle_wallet_id": { + "type": [ + "string", + "null" + ], + "example": "01234567-abcd-efgh-ijkl-012345678901" + }, + "network": { + "type": "string", + "enum": [ + "tron", + "solana", + "solana_devnet", + "arbitrum", + "base", + "ethereum", + "polygon", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "polygon_amoy", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "example": "tron" + }, + "address": { + "type": "string", + "example": "TALJN9zTTEL9TVBb4WuTt6wLvPqJZr3hvb" + } + }, + "required": [ + "id", + "network", + "address" + ] } } } }, "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BANK_ACCOUNTS_NOT_APPROVED`, `BANK_ACCOUNTS_OWNED_BY_PAYABLE`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_KYC_NOT_APPROVED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "BANK_ACCOUNTS_NOT_APPROVED": { + "summary": "BANK_ACCOUNTS_NOT_APPROVED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_APPROVED", + "message": "bank_account_not_approved", + "description": "This bank account is not approved yet.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_OWNED_BY_PAYABLE": { + "summary": "BANK_ACCOUNTS_OWNED_BY_PAYABLE", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_OWNED_BY_PAYABLE", + "message": "bank_account_owned_by_payable", + "description": "This bank account belongs to an invoice payable and can only be paid through that payable. Quote the payable instead.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { + "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "message": "network_not_supported_on_dev_instance", + "description": "This network or token combination is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_NOT_APPROVED": { + "summary": "CUSTOMERS_KYC_NOT_APPROVED", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_NOT_APPROVED", + "message": "kyc_not_approved", + "description": "This customer has not completed verification yet. Complete the verification before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -34236,6 +53311,40 @@ } } }, + "404": { + "description": "Possible error codes: `BANK_ACCOUNTS_NOT_FOUND`, `CUSTOMERS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "BANK_ACCOUNTS_NOT_FOUND": { + "summary": "BANK_ACCOUNTS_NOT_FOUND", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_FOUND", + "message": "bank_account_not_found", + "description": "The requested bank account was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -34249,7 +53358,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -34283,15 +53392,13 @@ } } } - } - }, - "/v1/instances/{instance_id}/customers/{customer_id}/limit-increase": { - "post": { + }, + "get": { "x-sdk": true, "tags": [ - "Customers" + "Offramp Wallets" ], - "summary": "Request Limit Increase", + "summary": "Get Offramp Wallets", "parameters": [ { "schema": { @@ -34319,88 +53426,37 @@ { "schema": { "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + "minLength": 15, + "maxLength": 15, + "example": "ba_000000000000" }, - "required": false, - "name": "Idempotency-Key", - "in": "header" - } - ], - "requestBody": { - "description": "Request new limit increase", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CustomerLimitIncreaseIn" - } - } + "required": true, + "name": "bank_account_id", + "in": "path" } - }, + ], "responses": { "200": { - "description": "Create customer limit increase", + "description": "Get offramp wallets", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CustomerLimitIncreaseOut" + "type": "array", + "items": { + "$ref": "#/components/schemas/OfframpWallet" + } } } } }, "400": { - "description": "Possible error codes: `CUSTOMERS_KYC_NOT_APPROVED`, `FILES_TOO_LARGE`, `FILES_TYPE_NOT_ALLOWED`, `FILES_UNREADABLE`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "CUSTOMERS_KYC_NOT_APPROVED": { - "summary": "CUSTOMERS_KYC_NOT_APPROVED", - "value": { - "success": false, - "code": "CUSTOMERS_KYC_NOT_APPROVED", - "message": "kyc_not_approved", - "description": "This customer has not completed verification yet. Complete the verification before continuing.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "FILES_TOO_LARGE": { - "summary": "FILES_TOO_LARGE", - "value": { - "success": false, - "code": "FILES_TOO_LARGE", - "message": "file_size_exceeded", - "description": "The file is too large. Upload a smaller file.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "FILES_TYPE_NOT_ALLOWED": { - "summary": "FILES_TYPE_NOT_ALLOWED", - "value": { - "success": false, - "code": "FILES_TYPE_NOT_ALLOWED", - "message": "file_type_not_allowed", - "description": "This file type is not allowed. Upload a supported file type.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", - "value": { - "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -34463,20 +53519,20 @@ } }, "404": { - "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "CUSTOMERS_NOT_FOUND": { - "summary": "CUSTOMERS_NOT_FOUND", + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", "value": { "success": false, - "code": "CUSTOMERS_NOT_FOUND", - "message": "customer_not_found", - "description": "The requested customer was not found.", + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -34498,7 +53554,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -34509,24 +53565,13 @@ } }, "500": { - "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", - "value": { - "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -34543,13 +53588,15 @@ } } } - }, + } + }, + "/v1/instances/{instance_id}/customers/{customer_id}/bank-accounts/{bank_account_id}/offramp-wallets/{id}": { "get": { "x-sdk": true, "tags": [ - "Customers" + "Offramp Wallets" ], - "summary": "Retrieve Limit Increase Requests", + "summary": "Get Offramp Wallet", "parameters": [ { "schema": { @@ -34573,18 +53620,37 @@ "required": true, "name": "customer_id", "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "ba_000000000000" + }, + "required": true, + "name": "bank_account_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "ow_000000000000" + }, + "required": true, + "name": "id", + "in": "path" } ], "responses": { "200": { - "description": "List customer limit increase requests", + "description": "Get offramp wallet", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GetCustomerLimitIncreaseOut" - } + "$ref": "#/components/schemas/OfframpWallet" } } } @@ -34671,7 +53737,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -34707,13 +53773,14 @@ } } }, - "/v1/instances/{instance_id}/customers": { + "/v1/instances/{instance_id}/quotes": { "post": { "x-sdk": true, "tags": [ - "Customers" + "Payouts Quotes" ], - "summary": "Create Customer", + "summary": "Create Quote", + "description": "Prices a payout. Send exactly one of bank_account_id or payable_id. request_amount is in cents (1000 means 10.00) and currency_type says whether it is what the sender pays or what the receiver gets. The quote expires 5 minutes after creation (expires_at is epoch milliseconds) and is single-use: execute it with Create Payout on EVM Chains for BlindPay-managed wallets on any network, Solana included, or with the Solana or Stellar payout endpoints for self-custodied wallets.", "parameters": [ { "schema": { @@ -34739,75 +53806,162 @@ } ], "requestBody": { - "description": "Create a new customer", + "description": "Create a new quote", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateCustomerIn" + "$ref": "#/components/schemas/QuoteIn" } } } }, "responses": { "200": { - "description": "Create customer", + "description": "Quote creation details", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "customer_id": { - "type": "string" - } - }, - "required": [ - "id", - "customer_id" - ] + "$ref": "#/components/schemas/QuoteOut" } } } }, "400": { - "description": "Possible error codes: `CUSTOMERS_ALREADY_APPROVED`, `CUSTOMERS_BUSINESS_ENHANCED_NOT_AVAILABLE`, `CUSTOMERS_ENHANCED_KYC_REQUIRED`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `FILES_TOO_LARGE`, `FILES_TYPE_NOT_ALLOWED`, `FILES_UNREADABLE`, `TOS_ALREADY_ACCEPTED`, `TOS_NOT_ACCEPTED`, `TOS_NOT_FOUND`, `VALIDATION_FAILED`, `VALIDATION_MISSING_REQUIRED_FIELDS`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BANK_ACCOUNTS_INCOMPLETE`, `BANK_ACCOUNTS_INVALID_BANK_CODE`, `BANK_ACCOUNTS_INVALID_ROUTING`, `BANK_ACCOUNTS_NOT_APPROVED`, `BANK_ACCOUNTS_NOT_FOUND`, `BANK_ACCOUNTS_OWNED_BY_PAYABLE`, `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED`, `BANK_ACCOUNTS_RTP_NOT_SUPPORTED`, `BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `BLOCKCHAIN_TX_FAILED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_KYC_NOT_APPROVED`, `CUSTOMERS_KYC_TYPE_NOT_AVAILABLE`, `CUSTOMERS_NAME_INVALID`, `CUSTOMERS_ONBOARDING_INCOMPLETE`, `FEES_PARTNER_FEE_EXCEEDED`, `FILES_TOO_LARGE`, `FILES_UNREADABLE`, `LIMITS_AMOUNT_OUT_OF_RANGE`, `LIMITS_VOLUME_EXCEEDED`, `PAYABLES_ALREADY_PAID_OR_EXPIRED`, `PAYABLES_ALREADY_PAID_OR_IN_FLIGHT`, `PAYABLES_AMOUNT_NEGATIVE`, `PAYABLES_BANK_ACCOUNT_INVALID`, `PAYABLES_BOLETO_WOULD_BE_OVERDUE`, `PAYABLES_CODE_UNRESOLVABLE`, `PAYABLES_CURRENCY_MUST_BE_BRL`, `PAYABLES_DESTINATION_NOT_SUPPORTED`, `PAYABLES_DOCUMENT_INVALID`, `PAYABLES_DUPLICATE`, `PAYABLES_NETWORK_NOT_SUPPORTED`, `PAYABLES_NOT_CANCELABLE`, `PAYABLES_PIX_AMOUNT_REQUIRED`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `PAYOUTS_DOCUMENTS_NOT_ACCEPTED`, `QUOTES_ALREADY_USED`, `QUOTES_AMOUNT_OUTSIDE_PROVIDER_LIMITS`, `QUOTES_EXPIRED`, `QUOTES_INVALID_STATE`, `QUOTES_RATE_UNAVAILABLE`, `TOS_NOT_ACCEPTED`, `VALIDATION_FAILED`, `VALIDATION_INVALID_REQUEST`, `VIRTUAL_ACCOUNTS_NOT_APPROVED`, `VIRTUAL_ACCOUNTS_NOT_FOUND`, `VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "CUSTOMERS_ALREADY_APPROVED": { - "summary": "CUSTOMERS_ALREADY_APPROVED", + "BANK_ACCOUNTS_INCOMPLETE": { + "summary": "BANK_ACCOUNTS_INCOMPLETE", "value": { "success": false, - "code": "CUSTOMERS_ALREADY_APPROVED", - "message": "customer_already_approved", - "description": "This customer is already approved.", + "code": "BANK_ACCOUNTS_INCOMPLETE", + "message": "infinitus_missing_intermediary", + "description": "The banking provider cannot route payments to this bank automatically. Provide the US correspondent bank routing number (ABA, 9 digits) from the beneficiary bank USD wire instructions in swift_intermediary_bank_routing_number.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "CUSTOMERS_BUSINESS_ENHANCED_NOT_AVAILABLE": { - "summary": "CUSTOMERS_BUSINESS_ENHANCED_NOT_AVAILABLE", + "BANK_ACCOUNTS_INVALID_BANK_CODE": { + "summary": "BANK_ACCOUNTS_INVALID_BANK_CODE", "value": { "success": false, - "code": "CUSTOMERS_BUSINESS_ENHANCED_NOT_AVAILABLE", - "message": "business_enhanced_not_available", - "description": "Enhanced verification is not available for business customers. Use standard verification (kyc_type: standard) for businesses.", + "code": "BANK_ACCOUNTS_INVALID_BANK_CODE", + "message": "bank_accounts_invalid_bank_code", + "description": "The bank code provided is not valid for this payment rail. The message lists where to fetch the valid codes.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "CUSTOMERS_ENHANCED_KYC_REQUIRED": { - "summary": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "BANK_ACCOUNTS_INVALID_ROUTING": { + "summary": "BANK_ACCOUNTS_INVALID_ROUTING", "value": { "success": false, - "code": "CUSTOMERS_ENHANCED_KYC_REQUIRED", - "message": "only_enhanced_kyc_allowed_for_high_risk_countries", - "description": "Individuals from high-risk countries must use enhanced verification (kyc_type: enhanced); standard verification is not available for them. See https://www.blindpay.com/docs/kb/supported-countries for country tiers.", + "code": "BANK_ACCOUNTS_INVALID_ROUTING", + "message": "The routing number must be a valid 9-digit ABA routing number.", + "description": "The routing number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_NOT_APPROVED": { + "summary": "BANK_ACCOUNTS_NOT_APPROVED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_APPROVED", + "message": "bank_account_not_approved", + "description": "This bank account is not approved yet.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_NOT_FOUND": { + "summary": "BANK_ACCOUNTS_NOT_FOUND", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_FOUND", + "message": "bank_account_not_found", + "description": "The requested bank account was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_OWNED_BY_PAYABLE": { + "summary": "BANK_ACCOUNTS_OWNED_BY_PAYABLE", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_OWNED_BY_PAYABLE", + "message": "bank_account_owned_by_payable", + "description": "This bank account belongs to an invoice payable and can only be paid through that payable. Quote the payable instead.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "message": "unsupported_banking_partner", + "description": "This banking option is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_RTP_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", + "message": "The provided routing number does not support RTP transactions.", + "description": "The provided routing number does not support instant payments.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR": { + "summary": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "message": "sepa_iban_not_eur", + "description": "SEPA payouts are only available to EUR accounts. This IBAN is from a country that holds another currency, so the payment would fail at settlement. Use an IBAN from a EUR account instead.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { + "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "message": "network_not_supported_on_dev_instance", + "description": "This network or token combination is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_TX_FAILED": { + "summary": "BLOCKCHAIN_TX_FAILED", + "value": { + "success": false, + "code": "BLOCKCHAIN_TX_FAILED", + "message": "transaction_failed", + "description": "The blockchain transaction failed. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { + "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "value": { + "success": false, + "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "message": "country_not_supported", + "description": "This country is not supported for this operation.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -34834,24 +53988,68 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "FILES_TOO_LARGE": { - "summary": "FILES_TOO_LARGE", + "CUSTOMERS_KYC_NOT_APPROVED": { + "summary": "CUSTOMERS_KYC_NOT_APPROVED", "value": { "success": false, - "code": "FILES_TOO_LARGE", - "message": "file_size_exceeded", - "description": "The file is too large. Upload a smaller file.", + "code": "CUSTOMERS_KYC_NOT_APPROVED", + "message": "kyc_not_approved", + "description": "This customer has not completed verification yet. Complete the verification before continuing.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "FILES_TYPE_NOT_ALLOWED": { - "summary": "FILES_TYPE_NOT_ALLOWED", + "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE": { + "summary": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", "value": { "success": false, - "code": "FILES_TYPE_NOT_ALLOWED", - "message": "file_type_not_allowed", - "description": "This file type is not allowed. Upload a supported file type.", + "code": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "message": "kyc_type_not_supported", + "description": "The requested verification type is not available for this customer. Use a supported verification type and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_NAME_INVALID": { + "summary": "CUSTOMERS_NAME_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_NAME_INVALID", + "message": "legal_name_required", + "description": "The name registered for this customer is not accepted. Review it and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ONBOARDING_INCOMPLETE": { + "summary": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "value": { + "success": false, + "code": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "message": "onboarding_incomplete", + "description": "Onboarding is not complete yet. Finish the remaining steps before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_PARTNER_FEE_EXCEEDED": { + "summary": "FEES_PARTNER_FEE_EXCEEDED", + "value": { + "success": false, + "code": "FEES_PARTNER_FEE_EXCEEDED", + "message": "partner_fee_exceeded", + "description": "The partner fee exceeds the allowed maximum for this transaction.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -34867,366 +54065,310 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "TOS_ALREADY_ACCEPTED": { - "summary": "TOS_ALREADY_ACCEPTED", + "LIMITS_AMOUNT_OUT_OF_RANGE": { + "summary": "LIMITS_AMOUNT_OUT_OF_RANGE", "value": { "success": false, - "code": "TOS_ALREADY_ACCEPTED", - "message": "tos_id_already_accepted", - "description": "These terms of service were already accepted.", + "code": "LIMITS_AMOUNT_OUT_OF_RANGE", + "message": "limits_amount_out_of_range", + "description": "The amount is outside the allowed range. The message includes the allowed range.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "TOS_NOT_ACCEPTED": { - "summary": "TOS_NOT_ACCEPTED", + "LIMITS_VOLUME_EXCEEDED": { + "summary": "LIMITS_VOLUME_EXCEEDED", "value": { "success": false, - "code": "TOS_NOT_ACCEPTED", - "message": "please_accept_terms_of_service", - "description": "The terms of service must be accepted before continuing.", + "code": "LIMITS_VOLUME_EXCEEDED", + "message": "limits_volume_exceeded", + "description": "You exceeded your transaction volume limit. The message includes the remaining amount available.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "TOS_NOT_FOUND": { - "summary": "TOS_NOT_FOUND", + "PAYABLES_ALREADY_PAID_OR_EXPIRED": { + "summary": "PAYABLES_ALREADY_PAID_OR_EXPIRED", "value": { "success": false, - "code": "TOS_NOT_FOUND", - "message": "tos_not_found", - "description": "The requested terms of service record was not found.", + "code": "PAYABLES_ALREADY_PAID_OR_EXPIRED", + "message": "payable_already_paid_or_expired", + "description": "This payment code was already paid or has expired and can no longer be paid.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT": { + "summary": "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT", + "message": "payable_already_paid_or_in_flight", + "description": "This payable is already being paid or was already paid. Only draft payables can be quoted; a failed or refunded attempt returns the payable to draft.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_MISSING_REQUIRED_FIELDS": { - "summary": "VALIDATION_MISSING_REQUIRED_FIELDS", + "PAYABLES_AMOUNT_NEGATIVE": { + "summary": "PAYABLES_AMOUNT_NEGATIVE", "value": { "success": false, - "code": "VALIDATION_MISSING_REQUIRED_FIELDS", - "message": "missing_required_fields", - "description": "Required fields are missing. Provide the missing fields and try again.", + "code": "PAYABLES_AMOUNT_NEGATIVE", + "message": "payable_amount_negative", + "description": "The payable total (line items plus taxes minus discount) cannot be negative.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { - "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "PAYABLES_BANK_ACCOUNT_INVALID": { + "summary": "PAYABLES_BANK_ACCOUNT_INVALID", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", - "message": "id_doc_front_file_required", - "description": "Additional documents are required to create this virtual account. Upload the requested documents.", + "code": "PAYABLES_BANK_ACCOUNT_INVALID", + "message": "payable_bank_account_invalid", + "description": "The bank_account details on this invoice payable were rejected. Check the errors list for the field that failed.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "401": { - "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_UNAUTHORIZED": { - "summary": "AUTH_UNAUTHORIZED", + }, + "PAYABLES_BOLETO_WOULD_BE_OVERDUE": { + "summary": "PAYABLES_BOLETO_WOULD_BE_OVERDUE", "value": { "success": false, - "code": "AUTH_UNAUTHORIZED", - "message": "unauthorized", - "description": "Authentication failed. Check your API key or session and try again.", + "code": "PAYABLES_BOLETO_WOULD_BE_OVERDUE", + "message": "payable_boleto_would_be_overdue", + "description": "This boleto is due before the next banking day, so it can no longer be paid on time. Boletos do not clear on weekends or outside banking hours.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "403": { - "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_FORBIDDEN": { - "summary": "AUTH_FORBIDDEN", + }, + "PAYABLES_CODE_UNRESOLVABLE": { + "summary": "PAYABLES_CODE_UNRESOLVABLE", + "value": { + "success": false, + "code": "PAYABLES_CODE_UNRESOLVABLE", + "message": "unresolvable_payable_code", + "description": "We could not read this payment code. Check the code and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_CURRENCY_MUST_BE_BRL": { + "summary": "PAYABLES_CURRENCY_MUST_BE_BRL", + "value": { + "success": false, + "code": "PAYABLES_CURRENCY_MUST_BE_BRL", + "message": "payable_currency_must_be_brl", + "description": "Boleto and PIX payables must use BRL.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DESTINATION_NOT_SUPPORTED": { + "summary": "PAYABLES_DESTINATION_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYABLES_DESTINATION_NOT_SUPPORTED", + "message": "payable_destination_not_supported", + "description": "Only boleto, arrecadação (utility/tax) and PIX QR code payables can be paid right now. Bank-destination invoice payables are not payable yet.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DOCUMENT_INVALID": { + "summary": "PAYABLES_DOCUMENT_INVALID", + "value": { + "success": false, + "code": "PAYABLES_DOCUMENT_INVALID", + "message": "payable_document_invalid", + "description": "document_file must be a URL returned by POST /upload with bucket `documents`, uploaded by this instance.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DUPLICATE": { + "summary": "PAYABLES_DUPLICATE", + "value": { + "success": false, + "code": "PAYABLES_DUPLICATE", + "message": "duplicate_payable", + "description": "This payment code already has a payable registered, in progress or completed for this instance.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_NETWORK_NOT_SUPPORTED": { + "summary": "PAYABLES_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYABLES_NETWORK_NOT_SUPPORTED", + "message": "payable_network_not_supported", + "description": "Only EVM wallets can fund payables right now.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_NOT_CANCELABLE": { + "summary": "PAYABLES_NOT_CANCELABLE", + "value": { + "success": false, + "code": "PAYABLES_NOT_CANCELABLE", + "message": "payable_not_cancelable", + "description": "Only draft payables can be deleted. Once a payout is executing this payable it can no longer be canceled.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_PIX_AMOUNT_REQUIRED": { + "summary": "PAYABLES_PIX_AMOUNT_REQUIRED", + "value": { + "success": false, + "code": "PAYABLES_PIX_AMOUNT_REQUIRED", + "message": "pix_code_amount_required", + "description": "This PIX code has no fixed amount and no amount was provided. Send the amount as line_items when registering a PIX code that lets the payer choose the value.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_AMOUNT_BELOW_MINIMUM": { + "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "value": { + "success": false, + "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "message": "swift_minimum_is_100_usd", + "description": "The amount is below the minimum for this payment rail.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_DOCUMENTS_NOT_ACCEPTED": { + "summary": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", + "value": { + "success": false, + "code": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", + "message": "document_upload_only_for_swift_payouts", + "description": "A document cannot be submitted for this payout in its current state.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_ALREADY_USED": { + "summary": "QUOTES_ALREADY_USED", + "value": { + "success": false, + "code": "QUOTES_ALREADY_USED", + "message": "quote_already_used", + "description": "This quote was already used. Request a new quote.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_AMOUNT_OUTSIDE_PROVIDER_LIMITS": { + "summary": "QUOTES_AMOUNT_OUTSIDE_PROVIDER_LIMITS", + "value": { + "success": false, + "code": "QUOTES_AMOUNT_OUTSIDE_PROVIDER_LIMITS", + "message": "amount_outside_limits", + "description": "The amount is outside the limits accepted for this payment rail. Adjust the amount and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_EXPIRED": { + "summary": "QUOTES_EXPIRED", + "value": { + "success": false, + "code": "QUOTES_EXPIRED", + "message": "quote_expired", + "description": "This quote has expired. Request a new quote and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_INVALID_STATE": { + "summary": "QUOTES_INVALID_STATE", + "value": { + "success": false, + "code": "QUOTES_INVALID_STATE", + "message": "quote_invalid_state", + "description": "This quote cannot be authorized in its current state. Request a new quote and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "TOS_NOT_ACCEPTED": { + "summary": "TOS_NOT_ACCEPTED", + "value": { + "success": false, + "code": "TOS_NOT_ACCEPTED", + "message": "please_accept_terms_of_service", + "description": "The terms of service must be accepted before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", "value": { "success": false, - "code": "AUTH_FORBIDDEN", - "message": "user_not_allowed", - "description": "You do not have permission to perform this action.", + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", + }, + "VALIDATION_INVALID_REQUEST": { + "summary": "VALIDATION_INVALID_REQUEST", "value": { "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", + "code": "VALIDATION_INVALID_REQUEST", + "message": "invalid_body", + "description": "The request is not valid for this operation. Check the parameters and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "500": { - "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", + }, + "VIRTUAL_ACCOUNTS_NOT_APPROVED": { + "summary": "VIRTUAL_ACCOUNTS_NOT_APPROVED", "value": { "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", + "code": "VIRTUAL_ACCOUNTS_NOT_APPROVED", + "message": "virtual_account_not_approved", + "description": "This virtual account is not approved yet.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + "VIRTUAL_ACCOUNTS_NOT_FOUND": { + "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "message": "virtual_account_not_found", + "description": "The requested virtual account was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - } - } - }, - "get": { - "x-sdk": true, - "tags": [ - "Customers" - ], - "summary": "Retrieve Customers", - "parameters": [ - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "enum": [ - "10", - "50", - "100", - "200", - "500", - "1000" - ], - "description": "Number of items to return", - "example": "50" - }, - "required": false, - "name": "limit", - "in": "query" - }, - { - "schema": { - "type": "string", - "enum": [ - "0", - "10", - "50", - "100", - "200", - "500", - "1000" - ], - "description": "Number of items to skip", - "example": "0" - }, - "required": false, - "name": "offset", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "A cursor for use in pagination. starting_after is an object ID that defines your place in the list.", - "example": "pi_123" - }, - "required": false, - "name": "starting_after", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "A cursor for use in pagination. ending_before is an object ID that defines your place in the list.", - "example": "pi_123" - }, - "required": false, - "name": "ending_before", - "in": "query" - }, - { - "schema": { - "type": "string" - }, - "required": false, - "name": "full_name", - "in": "query" - }, - { - "schema": { - "type": "string" - }, - "required": false, - "name": "customer_name", - "in": "query" - }, - { - "schema": { - "type": "string", - "enum": [ - "verifying", - "approved", - "rejected", - "deprecated", - "pending_review", - "awaiting_contract", - "compliance_request", - "approved_rfi" - ] - }, - "required": false, - "name": "status", - "in": "query" - }, - { - "schema": { - "type": "string" - }, - "required": false, - "name": "customer_id", - "in": "query" - }, - { - "schema": { - "type": "string" - }, - "required": false, - "name": "bank_account_id", - "in": "query" - }, - { - "schema": { - "type": "string" - }, - "required": false, - "name": "country", - "in": "query" - } - ], - "responses": { - "200": { - "description": "List customers with pagination", - "content": { - "application/json": { - "schema": { - "anyOf": [ - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CustomerOut" - } - }, - "pagination": { - "$ref": "#/components/schemas/PaginationMetadata" - } - }, - "required": [ - "data", - "pagination" - ] - }, - { - "type": "array", - "items": { - "$ref": "#/components/schemas/CustomerOut" - } - } - ] - } - } - } - }, - "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + }, + "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE": { + "summary": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "message": "banking_partner_not_eligible_for_customer", + "description": "This banking partner is not available for this customer. Choose a different banking partner.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -35281,105 +54423,25 @@ } } }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", - "value": { - "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, - "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "404": { + "description": "Possible error codes: `BANK_ACCOUNTS_NOT_FOUND`, `CUSTOMERS_NOT_FOUND`, `FEES_NOT_FOUND`, `INSTANCES_NOT_FOUND`, `PAYABLES_NOT_FOUND`, `PAYOUTS_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + "BANK_ACCOUNTS_NOT_FOUND": { + "summary": "BANK_ACCOUNTS_NOT_FOUND", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "BANK_ACCOUNTS_NOT_FOUND", + "message": "bank_account_not_found", + "description": "The requested bank account was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - } - } - } - }, - "/v1/instances/{instance_id}/customers/{id}": { - "get": { - "x-sdk": true, - "tags": [ - "Customers" - ], - "summary": "Retrieve Customer", - "parameters": [ - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" - }, - "required": true, - "name": "id", - "in": "path" - } - ], - "responses": { - "200": { - "description": "Get customer", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CustomerOut" - } - } - } - }, - "400": { - "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { + }, "CUSTOMERS_NOT_FOUND": { "summary": "CUSTOMERS_NOT_FOUND", "value": { @@ -35391,59 +54453,57 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "FEES_NOT_FOUND": { + "summary": "FEES_NOT_FOUND", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "FEES_NOT_FOUND", + "message": "partner_fee_not_found", + "description": "The requested fee configuration was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "401": { - "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_UNAUTHORIZED": { - "summary": "AUTH_UNAUTHORIZED", + }, + "INSTANCES_NOT_FOUND": { + "summary": "INSTANCES_NOT_FOUND", "value": { "success": false, - "code": "AUTH_UNAUTHORIZED", - "message": "unauthorized", - "description": "Authentication failed. Check your API key or session and try again.", + "code": "INSTANCES_NOT_FOUND", + "message": "instance_not_found", + "description": "The requested instance was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "403": { - "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_FORBIDDEN": { - "summary": "AUTH_FORBIDDEN", + }, + "PAYABLES_NOT_FOUND": { + "summary": "PAYABLES_NOT_FOUND", "value": { "success": false, - "code": "AUTH_FORBIDDEN", - "message": "user_not_allowed", - "description": "You do not have permission to perform this action.", + "code": "PAYABLES_NOT_FOUND", + "message": "payable_not_found", + "description": "This payable was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_NOT_FOUND": { + "summary": "PAYOUTS_NOT_FOUND", + "value": { + "success": false, + "code": "PAYOUTS_NOT_FOUND", + "message": "payout_not_found", + "description": "The requested payout was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", + "value": { + "success": false, + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -35453,20 +54513,20 @@ } }, "422": { - "description": "Possible error codes: `DATA_INTEGRITY_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `CUSTOMERS_INVALID_DATA`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "DATA_INTEGRITY_ERROR": { - "summary": "DATA_INTEGRITY_ERROR", + "CUSTOMERS_INVALID_DATA": { + "summary": "CUSTOMERS_INVALID_DATA", "value": { "success": false, - "code": "DATA_INTEGRITY_ERROR", - "message": "data_integrity_error", - "description": "This record could not be loaded because it contains invalid stored data. Contact support with the ID below.", + "code": "CUSTOMERS_INVALID_DATA", + "message": "invalid_customer_data", + "description": "The customer data was rejected by the banking provider. Check the highlighted fields and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -35488,7 +54548,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -35499,13 +54559,24 @@ } }, "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -35520,15 +54591,40 @@ } } } + }, + "503": { + "description": "Possible error codes: `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } } } - }, - "put": { + } + }, + "/v1/instances/{instance_id}/quotes/fx": { + "post": { "x-sdk": true, "tags": [ - "Customers" + "Payouts Quotes" ], - "summary": "Update Customer", + "summary": "Get FX Rate", "parameters": [ { "schema": { @@ -35541,17 +54637,6 @@ "name": "instance_id", "in": "path" }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" - }, - "required": true, - "name": "id", - "in": "path" - }, { "schema": { "type": "string", @@ -35565,96 +54650,149 @@ } ], "requestBody": { - "description": "Update a customer", + "description": "Check FX rate", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateCustomerIn" + "type": "object", + "properties": { + "from": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB" + ], + "example": "USDC" + }, + "to": { + "type": "string", + "enum": [ + "BRL", + "USD", + "MXN", + "COP", + "ARS", + "EUR", + "GBP" + ], + "example": "BRL" + }, + "request_amount": { + "type": "integer", + "minimum": 500, + "description": "1000 represents 10.00, 2050 represents 20.50", + "example": 1000 + }, + "currency_type": { + "type": "string", + "enum": [ + "sender", + "receiver" + ], + "description": "", + "example": "sender" + } + }, + "required": [ + "from", + "to", + "request_amount", + "currency_type" + ] } } } }, "responses": { "200": { - "description": "Customer updated", + "description": "Check FX rate response", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Success" + "type": "object", + "properties": { + "commercial_quotation": { + "type": [ + "number", + "null" + ], + "description": "1 USD = 4.95 BRL", + "example": 495 + }, + "blindpay_quotation": { + "type": [ + "number", + "null" + ], + "description": "1 USD = 4.85 BRL (commercial quotation - (blindpay taxes))", + "example": 485 + }, + "result_amount": { + "type": "number", + "minimum": 1 + }, + "instance_flat_fee": { + "type": [ + "number", + "null" + ], + "description": "0.5 USDC", + "example": 50 + }, + "instance_percentage_fee": { + "type": "number", + "minimum": 0, + "maximum": 10000 + } + }, + "required": [ + "commercial_quotation", + "blindpay_quotation", + "result_amount", + "instance_percentage_fee" + ] } } } }, "400": { - "description": "Possible error codes: `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_NOT_FOUND`, `FILES_TOO_LARGE`, `FILES_TYPE_NOT_ALLOWED`, `FILES_UNREADABLE`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR`, `FEES_PARTNER_FEE_EXCEEDED`, `QUOTES_RATE_UNAVAILABLE`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "CUSTOMERS_INVALID_PHONE": { - "summary": "CUSTOMERS_INVALID_PHONE", - "value": { - "success": false, - "code": "CUSTOMERS_INVALID_PHONE", - "message": "invalid_phone_number", - "description": "The phone number provided is not valid. Check the number and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_INVALID_TAX_ID": { - "summary": "CUSTOMERS_INVALID_TAX_ID", - "value": { - "success": false, - "code": "CUSTOMERS_INVALID_TAX_ID", - "message": "invalid_cpf_or_rg_tax_id", - "description": "The tax ID provided is not valid. Check the value and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_NOT_FOUND": { - "summary": "CUSTOMERS_NOT_FOUND", - "value": { - "success": false, - "code": "CUSTOMERS_NOT_FOUND", - "message": "customer_not_found", - "description": "The requested customer was not found.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "FILES_TOO_LARGE": { - "summary": "FILES_TOO_LARGE", + "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR": { + "summary": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", "value": { "success": false, - "code": "FILES_TOO_LARGE", - "message": "file_size_exceeded", - "description": "The file is too large. Upload a smaller file.", + "code": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "message": "sepa_iban_not_eur", + "description": "SEPA payouts are only available to EUR accounts. This IBAN is from a country that holds another currency, so the payment would fail at settlement. Use an IBAN from a EUR account instead.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "FILES_TYPE_NOT_ALLOWED": { - "summary": "FILES_TYPE_NOT_ALLOWED", + "FEES_PARTNER_FEE_EXCEEDED": { + "summary": "FEES_PARTNER_FEE_EXCEEDED", "value": { "success": false, - "code": "FILES_TYPE_NOT_ALLOWED", - "message": "file_type_not_allowed", - "description": "This file type is not allowed. Upload a supported file type.", + "code": "FEES_PARTNER_FEE_EXCEEDED", + "message": "partner_fee_exceeded", + "description": "The partner fee exceeds the allowed maximum for this transaction.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", "value": { "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -35733,7 +54871,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -35744,24 +54882,13 @@ } }, "500": { - "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", - "value": { - "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -35776,15 +54903,40 @@ } } } + }, + "503": { + "description": "Possible error codes: `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } } } - }, - "delete": { + } + }, + "/v1/instances/{instance_id}/payouts/{id}": { + "get": { "x-sdk": true, "tags": [ - "Customers" + "Payouts" ], - "summary": "Delete Customer", + "summary": "Retrieve Payout", "parameters": [ { "schema": { @@ -35802,31 +54954,20 @@ "type": "string", "minLength": 15, "maxLength": 15, - "example": "re_000000000000" + "example": "po_000000000000" }, "required": true, "name": "id", "in": "path" - }, - { - "schema": { - "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "required": false, - "name": "Idempotency-Key", - "in": "header" } ], "responses": { "200": { - "description": "Customer deleted", + "description": "List payouts", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Success" + "$ref": "#/components/schemas/PayoutOut" } } } @@ -35900,6 +55041,29 @@ } } }, + "404": { + "description": "Possible error codes: `PAYOUTS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "PAYOUTS_NOT_FOUND": { + "summary": "PAYOUTS_NOT_FOUND", + "value": { + "success": false, + "code": "PAYOUTS_NOT_FOUND", + "message": "payout_not_found", + "description": "The requested payout was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -35913,7 +55077,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -35949,31 +55113,21 @@ } } }, - "/v1/instances/{instance_id}/limits/customers/{id}": { + "/v1/e/payouts/{id}": { "get": { "x-sdk": true, + "x-mcp": false, "tags": [ - "Customers" + "Payouts" ], - "summary": "Retrieve Customer Limits", + "summary": "Retrieve Payout Track", "parameters": [ { "schema": { "type": "string", "minLength": 15, "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "re_000000000000" + "example": "po_000000000000" }, "required": true, "name": "id", @@ -35982,11 +55136,11 @@ ], "responses": { "200": { - "description": "Get customer limits", + "description": "List payouts", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetCustomerLimitsOut" + "$ref": "#/components/schemas/PayoutOut" } } } @@ -36061,20 +55215,20 @@ } }, "404": { - "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `PAYOUTS_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "CUSTOMERS_NOT_FOUND": { - "summary": "CUSTOMERS_NOT_FOUND", + "PAYOUTS_NOT_FOUND": { + "summary": "PAYOUTS_NOT_FOUND", "value": { "success": false, - "code": "CUSTOMERS_NOT_FOUND", - "message": "customer_not_found", - "description": "The requested customer was not found.", + "code": "PAYOUTS_NOT_FOUND", + "message": "payout_not_found", + "description": "The requested payout was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -36096,7 +55250,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -36132,14 +55286,13 @@ } } }, - "/v1/instances/{instance_id}/customers/{customer_id}/rfi": { + "/v1/instances/{instance_id}/payouts": { "get": { "x-sdk": true, "tags": [ - "Customers" + "Payouts" ], - "summary": "Get Open RFI for Customer", - "description": "Returns the open (pending) RFI for this customer, or null if the customer has no pending RFI.", + "summary": "Retrieve Payouts", "parameters": [ { "schema": { @@ -36152,26 +55305,184 @@ "name": "instance_id", "in": "path" }, + { + "schema": { + "type": "string", + "enum": [ + "10", + "50", + "100", + "200", + "500", + "1000" + ], + "description": "Number of items to return", + "example": "50" + }, + "required": false, + "name": "limit", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "0", + "10", + "50", + "100", + "200", + "500", + "1000" + ], + "description": "Number of items to skip", + "example": "0" + }, + "required": false, + "name": "offset", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "A cursor for use in pagination. starting_after is an object ID that defines your place in the list.", + "example": "pi_123" + }, + "required": false, + "name": "starting_after", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "A cursor for use in pagination. ending_before is an object ID that defines your place in the list.", + "example": "pi_123" + }, + "required": false, + "name": "ending_before", + "in": "query" + }, { "schema": { "type": "string", "minLength": 15, "maxLength": 15, - "description": "Customer ID", "example": "re_000000000000" }, - "required": true, + "required": false, "name": "customer_id", - "in": "path" + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "processing", + "failed", + "refunded", + "completed", + "on_hold" + ] + }, + "required": false, + "name": "status", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "customer_name", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "bank_account_id", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "country", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "wire", + "ach", + "pix", + "pix_safe", + "ted", + "spei_bitso", + "transfers_bitso", + "ach_cop_bitso", + "international_swift", + "rtp", + "sepa", + "faster_payments" + ] + }, + "required": false, + "name": "payment_method", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "network", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "token", + "in": "query" } ], "responses": { "200": { - "description": "Open RFI, or null if none", + "description": "List payouts with pagination and filtering", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Rfi" + "anyOf": [ + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PayoutOut" + } + }, + "pagination": { + "$ref": "#/components/schemas/PaginationMetadata" + } + }, + "required": [ + "data", + "pagination" + ] + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/PayoutOut" + } + } + ] } } } @@ -36258,7 +55569,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -36292,14 +55603,15 @@ } } } - }, + } + }, + "/v1/instances/{instance_id}/payouts/stellar/authorize": { "post": { "x-sdk": true, "tags": [ - "Customers" + "Payouts" ], - "summary": "Submit RFI Response", - "description": "Submit a flat response object for the open RFI. On success flips kyc_status back to verifying. Returns `{ success: false, reason }` when no pending RFI exists, callers should refetch the RFI state instead of retrying.", + "summary": "Authorize Token Stellar", "parameters": [ { "schema": { @@ -36312,18 +55624,6 @@ "name": "instance_id", "in": "path" }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, { "schema": { "type": "string", @@ -36340,68 +55640,49 @@ "content": { "application/json": { "schema": { - "type": "object", - "additionalProperties": {} + "$ref": "#/components/schemas/PayoutOnStellarAuthorizeIn" } } } }, "responses": { "200": { - "description": "RFI submitted (success: true) or rejected because no pending RFI exists (success: false)", + "description": "Payout started with success", "content": { "application/json": { "schema": { - "anyOf": [ - { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "enum": [ - true - ] - } - }, - "required": [ - "success" - ] - }, - { - "type": "object", - "properties": { - "success": { - "type": "boolean", - "enum": [ - false - ] - }, - "reason": { - "type": "string", - "enum": [ - "no_pending_rfi", - "already_resolved" - ] - } - }, - "required": [ - "success", - "reason" - ] + "type": "object", + "properties": { + "transaction_hash": { + "type": "string" } + }, + "required": [ + "transaction_hash" ] } } } }, "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `QUOTES_INVALID_STATE`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "QUOTES_INVALID_STATE": { + "summary": "QUOTES_INVALID_STATE", + "value": { + "success": false, + "code": "QUOTES_INVALID_STATE", + "message": "quote_invalid_state", + "description": "This quote cannot be authorized in its current state. Request a new quote and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -36463,6 +55744,29 @@ } } }, + "404": { + "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", + "value": { + "success": false, + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -36476,7 +55780,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -36487,24 +55791,13 @@ } }, "500": { - "description": "Possible error codes: `COMPLIANCE_RFI_INVALID`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "COMPLIANCE_RFI_INVALID": { - "summary": "COMPLIANCE_RFI_INVALID", - "value": { - "success": false, - "code": "COMPLIANCE_RFI_INVALID", - "message": "rfi_request_corrupt", - "description": "The information request could not be processed. Check the submitted fields.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -36523,13 +55816,13 @@ } } }, - "/v1/instances/{instance_id}/customers/{customer_id}/bank-accounts": { + "/v1/instances/{instance_id}/payouts/stellar": { "post": { "x-sdk": true, "tags": [ - "Bank Accounts" + "Payouts" ], - "summary": "Add Bank Account", + "summary": "Create Payout on Stellar", "parameters": [ { "schema": { @@ -36542,18 +55835,6 @@ "name": "instance_id", "in": "path" }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, { "schema": { "type": "string", @@ -36567,107 +55848,107 @@ } ], "requestBody": { - "description": "Create a new bank account", + "description": "Start payout on stellar blockchain", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateBankAccountIn" + "$ref": "#/components/schemas/PayoutOnStellarIn" } } } }, "responses": { "200": { - "description": "Add bank account", + "description": "Payout started with success", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/BankAccountOut" + "$ref": "#/components/schemas/PayoutOnEvmOut" } } } }, "400": { - "description": "Possible error codes: `BANK_ACCOUNTS_INVALID_BANK_CODE`, `BANK_ACCOUNTS_INVALID_ROUTING`, `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED`, `BANK_ACCOUNTS_RTP_NOT_SUPPORTED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `FILES_UNREADABLE`, `VALIDATION_FAILED`, `VALIDATION_INVALID_REQUEST`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BLOCKCHAIN_TX_FAILED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_NAME_INVALID`, `CUSTOMERS_ONBOARDING_INCOMPLETE`, `FILES_TOO_LARGE`, `FILES_UNREADABLE`, `PAYABLES_NETWORK_NOT_SUPPORTED`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `QUOTES_ALREADY_USED`, `QUOTES_EXPIRED`, `VALIDATION_FAILED`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_NOT_FOUND`, `VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "BANK_ACCOUNTS_INVALID_BANK_CODE": { - "summary": "BANK_ACCOUNTS_INVALID_BANK_CODE", + "BLOCKCHAIN_TX_FAILED": { + "summary": "BLOCKCHAIN_TX_FAILED", "value": { "success": false, - "code": "BANK_ACCOUNTS_INVALID_BANK_CODE", - "message": "bank_accounts_invalid_bank_code", - "description": "The bank code provided is not valid for this payment rail. The message lists where to fetch the valid codes.", + "code": "BLOCKCHAIN_TX_FAILED", + "message": "transaction_failed", + "description": "The blockchain transaction failed. Try again, and contact support if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "BANK_ACCOUNTS_INVALID_ROUTING": { - "summary": "BANK_ACCOUNTS_INVALID_ROUTING", + "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { + "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", "value": { "success": false, - "code": "BANK_ACCOUNTS_INVALID_ROUTING", - "message": "The routing number must be a valid 9-digit ABA routing number.", - "description": "The routing number provided is not valid. Check the number and try again.", + "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "message": "country_not_supported", + "description": "This country is not supported for this operation.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED": { - "summary": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "CUSTOMERS_INVALID_PHONE": { + "summary": "CUSTOMERS_INVALID_PHONE", "value": { "success": false, - "code": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", - "message": "unsupported_banking_partner", - "description": "This banking option is not supported for this operation.", + "code": "CUSTOMERS_INVALID_PHONE", + "message": "invalid_phone_number", + "description": "The phone number provided is not valid. Check the number and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "BANK_ACCOUNTS_RTP_NOT_SUPPORTED": { - "summary": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", + "CUSTOMERS_INVALID_TAX_ID": { + "summary": "CUSTOMERS_INVALID_TAX_ID", "value": { "success": false, - "code": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", - "message": "The provided routing number does not support RTP transactions.", - "description": "The provided routing number does not support instant payments.", + "code": "CUSTOMERS_INVALID_TAX_ID", + "message": "invalid_cpf_or_rg_tax_id", + "description": "The tax ID provided is not valid. Check the value and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { - "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "CUSTOMERS_NAME_INVALID": { + "summary": "CUSTOMERS_NAME_INVALID", "value": { "success": false, - "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", - "message": "country_not_supported", - "description": "This country is not supported for this operation.", + "code": "CUSTOMERS_NAME_INVALID", + "message": "legal_name_required", + "description": "The name registered for this customer is not accepted. Review it and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "CUSTOMERS_INVALID_PHONE": { - "summary": "CUSTOMERS_INVALID_PHONE", + "CUSTOMERS_ONBOARDING_INCOMPLETE": { + "summary": "CUSTOMERS_ONBOARDING_INCOMPLETE", "value": { "success": false, - "code": "CUSTOMERS_INVALID_PHONE", - "message": "invalid_phone_number", - "description": "The phone number provided is not valid. Check the number and try again.", + "code": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "message": "onboarding_incomplete", + "description": "Onboarding is not complete yet. Finish the remaining steps before continuing.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "CUSTOMERS_INVALID_TAX_ID": { - "summary": "CUSTOMERS_INVALID_TAX_ID", + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", "value": { "success": false, - "code": "CUSTOMERS_INVALID_TAX_ID", - "message": "invalid_cpf_or_rg_tax_id", - "description": "The tax ID provided is not valid. Check the value and try again.", + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -36683,6 +55964,50 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, + "PAYABLES_NETWORK_NOT_SUPPORTED": { + "summary": "PAYABLES_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYABLES_NETWORK_NOT_SUPPORTED", + "message": "payable_network_not_supported", + "description": "Only EVM wallets can fund payables right now.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_AMOUNT_BELOW_MINIMUM": { + "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "value": { + "success": false, + "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "message": "swift_minimum_is_100_usd", + "description": "The amount is below the minimum for this payment rail.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_ALREADY_USED": { + "summary": "QUOTES_ALREADY_USED", + "value": { + "success": false, + "code": "QUOTES_ALREADY_USED", + "message": "quote_already_used", + "description": "This quote was already used. Request a new quote.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_EXPIRED": { + "summary": "QUOTES_EXPIRED", + "value": { + "success": false, + "code": "QUOTES_EXPIRED", + "message": "quote_expired", + "description": "This quote has expired. Request a new quote and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -36694,24 +56019,35 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_INVALID_REQUEST": { - "summary": "VALIDATION_INVALID_REQUEST", + "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { + "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", "value": { "success": false, - "code": "VALIDATION_INVALID_REQUEST", - "message": "invalid_body", - "description": "The request is not valid for this operation. Check the parameters and try again.", + "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "message": "id_doc_front_file_required", + "description": "An identity document is required for this customer. Upload the front of a valid document and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { - "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "VIRTUAL_ACCOUNTS_NOT_FOUND": { + "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", - "message": "id_doc_front_file_required", - "description": "Additional documents are required to create this virtual account. Upload the requested documents.", + "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "message": "virtual_account_not_found", + "description": "The requested virtual account was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE": { + "summary": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "message": "banking_partner_not_eligible_for_customer", + "description": "This banking partner is not available for this customer. Choose a different banking partner.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -36777,6 +56113,40 @@ } } }, + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", + "value": { + "success": false, + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "422": { "description": "Possible error codes: `CUSTOMERS_INVALID_DATA`. See the Error responses section for retry semantics.", "content": { @@ -36813,7 +56183,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -36892,13 +56262,15 @@ } } } - }, - "get": { + } + }, + "/v1/instances/{instance_id}/payouts/solana": { + "post": { "x-sdk": true, "tags": [ - "Bank Accounts" + "Payouts" ], - "summary": "Retrieve Bank Accounts", + "summary": "Create Payout on Solana", "parameters": [ { "schema": { @@ -36914,269 +56286,165 @@ { "schema": { "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "enum": [ - "verifying", - "approved", - "rejected", - "deprecated" - ] - }, - "required": false, - "name": "status", - "in": "query" - }, - { - "schema": { - "type": "string", - "enum": [ - "wire", - "ach", - "pix", - "pix_safe", - "ted", - "spei_bitso", - "transfers_bitso", - "ach_cop_bitso", - "international_swift", - "rtp", - "sepa" - ] - }, - "required": false, - "name": "type", - "in": "query" - }, - { - "schema": { - "type": "string" - }, - "required": false, - "name": "name", - "in": "query" - }, - { - "schema": { - "type": "string" - }, - "required": false, - "name": "bank_account_id", - "in": "query" - }, - { - "schema": { - "type": "string" + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }, "required": false, - "name": "country", - "in": "query" + "name": "Idempotency-Key", + "in": "header" } ], + "requestBody": { + "description": "Start payout on solana blockchain", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PayoutOnSolanaIn" + } + } + } + }, "responses": { "200": { - "description": "Get bank accounts", + "description": "Payout started with success", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/BankAccountOut" - } + "$ref": "#/components/schemas/PayoutOnEvmOut" } } } }, "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_NAME_INVALID`, `CUSTOMERS_ONBOARDING_INCOMPLETE`, `FILES_TOO_LARGE`, `FILES_UNREADABLE`, `PAYABLES_NETWORK_NOT_SUPPORTED`, `QUOTES_ALREADY_USED`, `QUOTES_EXPIRED`, `VALIDATION_FAILED`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { + "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "message": "network_not_supported_on_dev_instance", + "description": "This network or token combination is not supported for this operation.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "401": { - "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_UNAUTHORIZED": { - "summary": "AUTH_UNAUTHORIZED", + }, + "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { + "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", "value": { "success": false, - "code": "AUTH_UNAUTHORIZED", - "message": "unauthorized", - "description": "Authentication failed. Check your API key or session and try again.", + "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "message": "country_not_supported", + "description": "This country is not supported for this operation.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "403": { - "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_FORBIDDEN": { - "summary": "AUTH_FORBIDDEN", + }, + "CUSTOMERS_INVALID_PHONE": { + "summary": "CUSTOMERS_INVALID_PHONE", "value": { "success": false, - "code": "AUTH_FORBIDDEN", - "message": "user_not_allowed", - "description": "You do not have permission to perform this action.", + "code": "CUSTOMERS_INVALID_PHONE", + "message": "invalid_phone_number", + "description": "The phone number provided is not valid. Check the number and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", + }, + "CUSTOMERS_INVALID_TAX_ID": { + "summary": "CUSTOMERS_INVALID_TAX_ID", "value": { "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", + "code": "CUSTOMERS_INVALID_TAX_ID", + "message": "invalid_cpf_or_rg_tax_id", + "description": "The tax ID provided is not valid. Check the value and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + }, + "CUSTOMERS_NAME_INVALID": { + "summary": "CUSTOMERS_NAME_INVALID", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "CUSTOMERS_NAME_INVALID", + "message": "legal_name_required", + "description": "The name registered for this customer is not accepted. Review it and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - } - } - } - }, - "/v1/instances/{instance_id}/customers/{customer_id}/bank-accounts/{id}": { - "get": { - "x-sdk": true, - "tags": [ - "Bank Accounts" - ], - "summary": "Retrieve Bank Account", - "parameters": [ - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "bk_000000000000" - }, - "required": true, - "name": "id", - "in": "path" - } - ], - "responses": { - "200": { - "description": "Get bank account", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BankAccountOut" - } - } - } - }, - "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { + }, + "CUSTOMERS_ONBOARDING_INCOMPLETE": { + "summary": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "value": { + "success": false, + "code": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "message": "onboarding_incomplete", + "description": "Onboarding is not complete yet. Finish the remaining steps before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_NETWORK_NOT_SUPPORTED": { + "summary": "PAYABLES_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYABLES_NETWORK_NOT_SUPPORTED", + "message": "payable_network_not_supported", + "description": "Only EVM wallets can fund payables right now.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_ALREADY_USED": { + "summary": "QUOTES_ALREADY_USED", + "value": { + "success": false, + "code": "QUOTES_ALREADY_USED", + "message": "quote_already_used", + "description": "This quote was already used. Request a new quote.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_EXPIRED": { + "summary": "QUOTES_EXPIRED", + "value": { + "success": false, + "code": "QUOTES_EXPIRED", + "message": "quote_expired", + "description": "This quote has expired. Request a new quote and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -37187,6 +56455,39 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { + "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "message": "id_doc_front_file_required", + "description": "An identity document is required for this customer. Upload the front of a valid document and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE": { + "summary": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "message": "banking_partner_not_eligible_for_customer", + "description": "This banking partner is not available for this customer. Choose a different banking partner.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } @@ -37238,44 +56539,32 @@ } } }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", "value": { "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + }, + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -37283,88 +56572,22 @@ } } } - } - } - }, - "delete": { - "x-sdk": true, - "tags": [ - "Bank Accounts" - ], - "summary": "Remove Bank Account", - "parameters": [ - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "bk_000000000000" - }, - "required": true, - "name": "id", - "in": "path" - }, - { - "schema": { - "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "required": false, - "name": "Idempotency-Key", - "in": "header" - } - ], - "responses": { - "200": { - "description": "Delete bank account", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Success" - } - } - } }, - "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "422": { + "description": "Possible error codes: `CUSTOMERS_INVALID_DATA`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "CUSTOMERS_INVALID_DATA": { + "summary": "CUSTOMERS_INVALID_DATA", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "CUSTOMERS_INVALID_DATA", + "message": "invalid_customer_data", + "description": "The customer data was rejected by the banking provider. Check the highlighted fields and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -37373,21 +56596,21 @@ } } }, - "401": { - "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "AUTH_UNAUTHORIZED": { - "summary": "AUTH_UNAUTHORIZED", + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", "value": { "success": false, - "code": "AUTH_UNAUTHORIZED", - "message": "unauthorized", - "description": "Authentication failed. Check your API key or session and try again.", + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -37396,44 +56619,43 @@ } } }, - "403": { - "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "500": { + "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "AUTH_FORBIDDEN": { - "summary": "AUTH_FORBIDDEN", + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", "value": { "success": false, - "code": "AUTH_FORBIDDEN", - "message": "user_not_allowed", - "description": "You do not have permission to perform this action.", + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", + }, + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", "value": { "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -37442,21 +56664,21 @@ } } }, - "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "502": { + "description": "Possible error codes: `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -37468,13 +56690,14 @@ } } }, - "/v1/instances/{instance_id}/customers/{customer_id}/virtual-accounts": { + "/v1/instances/{instance_id}/payouts/evm": { "post": { "x-sdk": true, "tags": [ - "Virtual Accounts" + "Payouts" ], - "summary": "Create Virtual Account", + "summary": "Create Payout on EVM Chains", + "description": "Executes a payout quote. Despite the name, this is the endpoint for payouts funded from a BlindPay-managed wallet on any network, Solana included; self-custodied EVM wallets must approve the token first. Execute before the quote expires (5 minutes). Send an Idempotency-Key header so a retry cannot create a second payout. On development instances the payout completes on its own; request_amount 66600 makes it fail and 77700 makes it refunded.", "parameters": [ { "schema": { @@ -37487,18 +56710,6 @@ "name": "instance_id", "in": "path" }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, { "schema": { "type": "string", @@ -37512,107 +56723,426 @@ } ], "requestBody": { - "description": "Create a new virtual account", + "description": "Start payout on evm blockchain", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateVirtualAccountIn" + "$ref": "#/components/schemas/PayoutOnEvmIn" } } } }, "responses": { "200": { - "description": "Create virtual account", + "description": "Payout started with success", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VirtualAccountOut" + "$ref": "#/components/schemas/PayoutOnEvmOut" } } } }, "400": { - "description": "Possible error codes: `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_ENHANCED_KYC_REQUIRED`, `CUSTOMERS_ID_DOCUMENT_INVALID`, `CUSTOMERS_KYC_NOT_APPROVED`, `FILES_UNREADABLE`, `VALIDATION_FAILED`, `VALIDATION_MISSING_REQUIRED_FIELDS`, `VIRTUAL_ACCOUNTS_DISABLED`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BANK_ACCOUNTS_INCOMPLETE`, `BANK_ACCOUNTS_INVALID_BANK_CODE`, `BANK_ACCOUNTS_INVALID_ROUTING`, `BANK_ACCOUNTS_NOT_APPROVED`, `BANK_ACCOUNTS_NOT_FOUND`, `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED`, `BANK_ACCOUNTS_RTP_NOT_SUPPORTED`, `BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `BLOCKCHAIN_TX_FAILED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_KYC_TYPE_NOT_AVAILABLE`, `CUSTOMERS_NAME_INVALID`, `CUSTOMERS_ONBOARDING_INCOMPLETE`, `FEES_PARTNER_FEE_EXCEEDED`, `FILES_TOO_LARGE`, `FILES_UNREADABLE`, `PAYABLES_ALREADY_PAID_OR_EXPIRED`, `PAYABLES_ALREADY_PAID_OR_IN_FLIGHT`, `PAYABLES_AMOUNT_NEGATIVE`, `PAYABLES_BANK_ACCOUNT_INVALID`, `PAYABLES_CODE_UNRESOLVABLE`, `PAYABLES_CURRENCY_MUST_BE_BRL`, `PAYABLES_DESTINATION_NOT_SUPPORTED`, `PAYABLES_DOCUMENT_INVALID`, `PAYABLES_DUPLICATE`, `PAYABLES_NETWORK_NOT_SUPPORTED`, `PAYABLES_NOT_CANCELABLE`, `PAYABLES_PIX_AMOUNT_REQUIRED`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `PAYOUTS_DOCUMENTS_NOT_ACCEPTED`, `QUOTES_ALREADY_USED`, `QUOTES_EXPIRED`, `QUOTES_INVALID_STATE`, `VALIDATION_FAILED`, `VALIDATION_INVALID_REQUEST`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_NOT_FOUND`, `VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "BANK_ACCOUNTS_INCOMPLETE": { + "summary": "BANK_ACCOUNTS_INCOMPLETE", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INCOMPLETE", + "message": "infinitus_missing_intermediary", + "description": "The banking provider cannot route payments to this bank automatically. Provide the US correspondent bank routing number (ABA, 9 digits) from the beneficiary bank USD wire instructions in swift_intermediary_bank_routing_number.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_INVALID_BANK_CODE": { + "summary": "BANK_ACCOUNTS_INVALID_BANK_CODE", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INVALID_BANK_CODE", + "message": "bank_accounts_invalid_bank_code", + "description": "The bank code provided is not valid for this payment rail. The message lists where to fetch the valid codes.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_INVALID_ROUTING": { + "summary": "BANK_ACCOUNTS_INVALID_ROUTING", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INVALID_ROUTING", + "message": "The routing number must be a valid 9-digit ABA routing number.", + "description": "The routing number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_NOT_APPROVED": { + "summary": "BANK_ACCOUNTS_NOT_APPROVED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_APPROVED", + "message": "bank_account_not_approved", + "description": "This bank account is not approved yet.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_NOT_FOUND": { + "summary": "BANK_ACCOUNTS_NOT_FOUND", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_FOUND", + "message": "bank_account_not_found", + "description": "The requested bank account was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED": { "summary": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", "value": { "success": false, - "code": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", - "message": "unsupported_banking_partner", - "description": "This banking option is not supported for this operation.", + "code": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "message": "unsupported_banking_partner", + "description": "This banking option is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_RTP_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", + "message": "The provided routing number does not support RTP transactions.", + "description": "The provided routing number does not support instant payments.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR": { + "summary": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "message": "sepa_iban_not_eur", + "description": "SEPA payouts are only available to EUR accounts. This IBAN is from a country that holds another currency, so the payment would fail at settlement. Use an IBAN from a EUR account instead.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { + "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "message": "network_not_supported_on_dev_instance", + "description": "This network or token combination is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_TX_FAILED": { + "summary": "BLOCKCHAIN_TX_FAILED", + "value": { + "success": false, + "code": "BLOCKCHAIN_TX_FAILED", + "message": "transaction_failed", + "description": "The blockchain transaction failed. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { + "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "value": { + "success": false, + "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "message": "country_not_supported", + "description": "This country is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_PHONE": { + "summary": "CUSTOMERS_INVALID_PHONE", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_PHONE", + "message": "invalid_phone_number", + "description": "The phone number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_TAX_ID": { + "summary": "CUSTOMERS_INVALID_TAX_ID", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_TAX_ID", + "message": "invalid_cpf_or_rg_tax_id", + "description": "The tax ID provided is not valid. Check the value and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE": { + "summary": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "message": "kyc_type_not_supported", + "description": "The requested verification type is not available for this customer. Use a supported verification type and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_NAME_INVALID": { + "summary": "CUSTOMERS_NAME_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_NAME_INVALID", + "message": "legal_name_required", + "description": "The name registered for this customer is not accepted. Review it and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ONBOARDING_INCOMPLETE": { + "summary": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "value": { + "success": false, + "code": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "message": "onboarding_incomplete", + "description": "Onboarding is not complete yet. Finish the remaining steps before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_PARTNER_FEE_EXCEEDED": { + "summary": "FEES_PARTNER_FEE_EXCEEDED", + "value": { + "success": false, + "code": "FEES_PARTNER_FEE_EXCEEDED", + "message": "partner_fee_exceeded", + "description": "The partner fee exceeds the allowed maximum for this transaction.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_ALREADY_PAID_OR_EXPIRED": { + "summary": "PAYABLES_ALREADY_PAID_OR_EXPIRED", + "value": { + "success": false, + "code": "PAYABLES_ALREADY_PAID_OR_EXPIRED", + "message": "payable_already_paid_or_expired", + "description": "This payment code was already paid or has expired and can no longer be paid.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT": { + "summary": "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT", + "value": { + "success": false, + "code": "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT", + "message": "payable_already_paid_or_in_flight", + "description": "This payable is already being paid or was already paid. Only draft payables can be quoted; a failed or refunded attempt returns the payable to draft.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_AMOUNT_NEGATIVE": { + "summary": "PAYABLES_AMOUNT_NEGATIVE", + "value": { + "success": false, + "code": "PAYABLES_AMOUNT_NEGATIVE", + "message": "payable_amount_negative", + "description": "The payable total (line items plus taxes minus discount) cannot be negative.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_BANK_ACCOUNT_INVALID": { + "summary": "PAYABLES_BANK_ACCOUNT_INVALID", + "value": { + "success": false, + "code": "PAYABLES_BANK_ACCOUNT_INVALID", + "message": "payable_bank_account_invalid", + "description": "The bank_account details on this invoice payable were rejected. Check the errors list for the field that failed.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_CODE_UNRESOLVABLE": { + "summary": "PAYABLES_CODE_UNRESOLVABLE", + "value": { + "success": false, + "code": "PAYABLES_CODE_UNRESOLVABLE", + "message": "unresolvable_payable_code", + "description": "We could not read this payment code. Check the code and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_CURRENCY_MUST_BE_BRL": { + "summary": "PAYABLES_CURRENCY_MUST_BE_BRL", + "value": { + "success": false, + "code": "PAYABLES_CURRENCY_MUST_BE_BRL", + "message": "payable_currency_must_be_brl", + "description": "Boleto and PIX payables must use BRL.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DESTINATION_NOT_SUPPORTED": { + "summary": "PAYABLES_DESTINATION_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYABLES_DESTINATION_NOT_SUPPORTED", + "message": "payable_destination_not_supported", + "description": "Only boleto, arrecadação (utility/tax) and PIX QR code payables can be paid right now. Bank-destination invoice payables are not payable yet.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DOCUMENT_INVALID": { + "summary": "PAYABLES_DOCUMENT_INVALID", + "value": { + "success": false, + "code": "PAYABLES_DOCUMENT_INVALID", + "message": "payable_document_invalid", + "description": "document_file must be a URL returned by POST /upload with bucket `documents`, uploaded by this instance.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { - "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "PAYABLES_DUPLICATE": { + "summary": "PAYABLES_DUPLICATE", "value": { "success": false, - "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", - "message": "network_not_supported_on_dev_instance", - "description": "This network or token combination is not supported for this operation.", + "code": "PAYABLES_DUPLICATE", + "message": "duplicate_payable", + "description": "This payment code already has a payable registered, in progress or completed for this instance.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { - "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "PAYABLES_NETWORK_NOT_SUPPORTED": { + "summary": "PAYABLES_NETWORK_NOT_SUPPORTED", "value": { "success": false, - "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", - "message": "country_not_supported", - "description": "This country is not supported for this operation.", + "code": "PAYABLES_NETWORK_NOT_SUPPORTED", + "message": "payable_network_not_supported", + "description": "Only EVM wallets can fund payables right now.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "CUSTOMERS_ENHANCED_KYC_REQUIRED": { - "summary": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "PAYABLES_NOT_CANCELABLE": { + "summary": "PAYABLES_NOT_CANCELABLE", "value": { "success": false, - "code": "CUSTOMERS_ENHANCED_KYC_REQUIRED", - "message": "only_enhanced_kyc_allowed_for_high_risk_countries", - "description": "Individuals from high-risk countries must use enhanced verification (kyc_type: enhanced); standard verification is not available for them. See https://www.blindpay.com/docs/kb/supported-countries for country tiers.", + "code": "PAYABLES_NOT_CANCELABLE", + "message": "payable_not_cancelable", + "description": "Only draft payables can be deleted. Once a payout is executing this payable it can no longer be canceled.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "CUSTOMERS_ID_DOCUMENT_INVALID": { - "summary": "CUSTOMERS_ID_DOCUMENT_INVALID", + "PAYABLES_PIX_AMOUNT_REQUIRED": { + "summary": "PAYABLES_PIX_AMOUNT_REQUIRED", "value": { "success": false, - "code": "CUSTOMERS_ID_DOCUMENT_INVALID", - "message": "id_doc_is_not_valid_passport_or_national_id", - "description": "The identity document is not an accepted passport or national ID. Provide a valid passport or national ID for this customer (a driver license is not accepted for high-risk countries).", + "code": "PAYABLES_PIX_AMOUNT_REQUIRED", + "message": "pix_code_amount_required", + "description": "This PIX code has no fixed amount and no amount was provided. Send the amount as line_items when registering a PIX code that lets the payer choose the value.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "CUSTOMERS_KYC_NOT_APPROVED": { - "summary": "CUSTOMERS_KYC_NOT_APPROVED", + "PAYOUTS_AMOUNT_BELOW_MINIMUM": { + "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", "value": { "success": false, - "code": "CUSTOMERS_KYC_NOT_APPROVED", - "message": "kyc_not_approved", - "description": "This customer has not completed verification yet. Complete the verification before continuing.", + "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "message": "swift_minimum_is_100_usd", + "description": "The amount is below the minimum for this payment rail.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", + "PAYOUTS_DOCUMENTS_NOT_ACCEPTED": { + "summary": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", "value": { "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", + "code": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", + "message": "document_upload_only_for_swift_payouts", + "description": "A document cannot be submitted for this payout in its current state.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_ALREADY_USED": { + "summary": "QUOTES_ALREADY_USED", + "value": { + "success": false, + "code": "QUOTES_ALREADY_USED", + "message": "quote_already_used", + "description": "This quote was already used. Request a new quote.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_EXPIRED": { + "summary": "QUOTES_EXPIRED", + "value": { + "success": false, + "code": "QUOTES_EXPIRED", + "message": "quote_expired", + "description": "This quote has expired. Request a new quote and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_INVALID_STATE": { + "summary": "QUOTES_INVALID_STATE", + "value": { + "success": false, + "code": "QUOTES_INVALID_STATE", + "message": "quote_invalid_state", + "description": "This quote cannot be authorized in its current state. Request a new quote and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -37628,46 +57158,57 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_MISSING_REQUIRED_FIELDS": { - "summary": "VALIDATION_MISSING_REQUIRED_FIELDS", + "VALIDATION_INVALID_REQUEST": { + "summary": "VALIDATION_INVALID_REQUEST", "value": { "success": false, - "code": "VALIDATION_MISSING_REQUIRED_FIELDS", - "message": "missing_required_fields", - "description": "Required fields are missing. Provide the missing fields and try again.", + "code": "VALIDATION_INVALID_REQUEST", + "message": "invalid_body", + "description": "The request is not valid for this operation. Check the parameters and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VIRTUAL_ACCOUNTS_DISABLED": { - "summary": "VIRTUAL_ACCOUNTS_DISABLED", + "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { + "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_DISABLED", - "message": "virtual_accounts_not_enabled", - "description": "Virtual accounts are not enabled for this account. Contact support to enable them.", + "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "message": "id_doc_front_file_required", + "description": "An identity document is required for this customer. Upload the front of a valid document and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { - "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "VIRTUAL_ACCOUNTS_NOT_FOUND": { + "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", - "message": "id_doc_front_file_required", - "description": "Additional documents are required to create this virtual account. Upload the requested documents.", + "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "message": "virtual_account_not_found", + "description": "The requested virtual account was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED": { - "summary": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", + "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE": { + "summary": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", - "message": "us_state_not_supported", - "description": "Virtual accounts are not available for this country or region.", + "code": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "message": "banking_partner_not_eligible_for_customer", + "description": "This banking partner is not available for this customer. Choose a different banking partner.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -37723,7 +57264,7 @@ } }, "404": { - "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `INSTANCES_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `PAYABLES_NOT_FOUND`, `PAYOUTS_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { @@ -37741,13 +57282,24 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "INSTANCES_NOT_FOUND": { - "summary": "INSTANCES_NOT_FOUND", + "PAYABLES_NOT_FOUND": { + "summary": "PAYABLES_NOT_FOUND", "value": { "success": false, - "code": "INSTANCES_NOT_FOUND", - "message": "instance_not_found", - "description": "The requested instance was not found.", + "code": "PAYABLES_NOT_FOUND", + "message": "payable_not_found", + "description": "This payable was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_NOT_FOUND": { + "summary": "PAYOUTS_NOT_FOUND", + "value": { + "success": false, + "code": "PAYOUTS_NOT_FOUND", + "message": "payout_not_found", + "description": "The requested payout was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -37767,6 +57319,29 @@ } } }, + "422": { + "description": "Possible error codes: `CUSTOMERS_INVALID_DATA`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_INVALID_DATA": { + "summary": "CUSTOMERS_INVALID_DATA", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_DATA", + "message": "invalid_customer_data", + "description": "The customer data was rejected by the banking provider. Check the highlighted fields and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -37780,7 +57355,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -37791,7 +57366,7 @@ } }, "500": { - "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { @@ -37819,19 +57394,56 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "502": { + "description": "Possible error codes: `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } } } } - }, - "get": { + } + }, + "/v1/instances/{instance_id}/payouts/{id}/documents": { + "post": { "x-sdk": true, "tags": [ - "Virtual Accounts" + "Payouts" ], - "summary": "Retrieve Virtual Accounts", + "summary": "Submit Payout Documents", + "description": "Submit a compliance document for a payout. SWIFT payouts waiting for documents require it and the submission resumes the compliance review; the optional payment description is written to the SWIFT memo. Other rails (wire, ACH, RTP, Pix and so on) may attach an optional document while the payout is processing or completed. It is stored for compliance without changing the payout status or tracking, the description is ignored, and submitting again replaces the previous document.", "parameters": [ { "schema": { @@ -37849,36 +57461,97 @@ "type": "string", "minLength": 15, "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" + "example": "po_000000000000" }, "required": true, - "name": "customer_id", + "name": "id", "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" } ], + "requestBody": { + "description": "Document details and optional payment description", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubmitPayoutDocumentsIn" + } + } + } + }, "responses": { "200": { - "description": "Get virtual accounts", + "description": "Documents submitted successfully", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/VirtualAccountOut" - } + "$ref": "#/components/schemas/Success" } } } }, "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `CUSTOMERS_NAME_INVALID`, `FILES_TOO_LARGE`, `FILES_UNREADABLE`, `PAYOUTS_DOCUMENTS_NOT_ACCEPTED`, `VALIDATION_FAILED`, `VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "CUSTOMERS_NAME_INVALID": { + "summary": "CUSTOMERS_NAME_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_NAME_INVALID", + "message": "legal_name_required", + "description": "The name registered for this customer is not accepted. Review it and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_DOCUMENTS_NOT_ACCEPTED": { + "summary": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", + "value": { + "success": false, + "code": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", + "message": "document_upload_only_for_swift_payouts", + "description": "A document cannot be submitted for this payout in its current state.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -37889,6 +57562,17 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE": { + "summary": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "message": "banking_partner_not_eligible_for_customer", + "description": "This banking partner is not available for this customer. Choose a different banking partner.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } @@ -37940,6 +57624,29 @@ } } }, + "404": { + "description": "Possible error codes: `PAYOUTS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "PAYOUTS_NOT_FOUND": { + "summary": "PAYOUTS_NOT_FOUND", + "value": { + "success": false, + "code": "PAYOUTS_NOT_FOUND", + "message": "payout_not_found", + "description": "The requested payout was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -37953,7 +57660,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -37964,13 +57671,24 @@ } }, "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -37989,13 +57707,14 @@ } } }, - "/v1/instances/{instance_id}/customers/{customer_id}/virtual-accounts/{id}": { - "get": { + "/v1/instances/{instance_id}/payin-quotes": { + "post": { "x-sdk": true, "tags": [ - "Virtual Accounts" + "Payin Quotes" ], - "summary": "Retrieve Virtual Account", + "summary": "Create Payin Quote", + "description": "Prices a payin from a local payment method into a stablecoin wallet. Send one of wallet_id (BlindPay-managed wallet) or blockchain_wallet_id. Do not send a network: the wallet decides where the tokens are delivered. request_amount is in cents; the minimum depends on the currency (1000, which is 10.00, for USD and BRL) and OTC quotes have a higher minimum. funding_bank_account_id is required when payment_method is ach_pull. The quote expires 5 minutes after creation, or 10 seconds for OTC quotes; create the payin with Create Payin before then.", "parameters": [ { "schema": { @@ -38011,56 +57730,209 @@ { "schema": { "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "bk_000000000000" + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }, - "required": true, - "name": "id", - "in": "path" + "required": false, + "name": "Idempotency-Key", + "in": "header" } ], + "requestBody": { + "description": "Create a new quote", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreatePayinQuoteIn" + } + } + } + }, "responses": { "200": { - "description": "Get virtual account", + "description": "Payin Quote creation details", "content": { "application/json": { "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/VirtualAccountOut" - }, - { - "type": [ - "object", - "null" - ] - } - ] + "$ref": "#/components/schemas/CreatePayinQuoteOut" } } } }, "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BANK_ACCOUNTS_PLAID_NOT_ENABLED`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_KYC_NOT_APPROVED`, `CUSTOMERS_NOT_FOUND`, `FEES_PARTNER_FEE_EXCEEDED`, `LIMITS_AMOUNT_OUT_OF_RANGE`, `LIMITS_VOLUME_EXCEEDED`, `PAYINS_CARD_GATEWAY_ENVIRONMENT_MISMATCH`, `PAYINS_FUNDING_ACCOUNT_INVALID`, `PAYINS_METHOD_NOT_SUPPORTED`, `PAYINS_TAX_ID_REQUIRED`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM`, `QUOTES_OTC_NOT_SUPPORTED`, `TOS_NOT_ACCEPTED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "BANK_ACCOUNTS_PLAID_NOT_ENABLED": { + "summary": "BANK_ACCOUNTS_PLAID_NOT_ENABLED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PLAID_NOT_ENABLED", + "message": "plaid_not_supported", + "description": "Instantly connected bank accounts are not enabled for this account. Contact support to enable them.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { + "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "message": "network_not_supported_on_dev_instance", + "description": "This network or token combination is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_NOT_APPROVED": { + "summary": "CUSTOMERS_KYC_NOT_APPROVED", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_NOT_APPROVED", + "message": "kyc_not_approved", + "description": "This customer has not completed verification yet. Complete the verification before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_PARTNER_FEE_EXCEEDED": { + "summary": "FEES_PARTNER_FEE_EXCEEDED", + "value": { + "success": false, + "code": "FEES_PARTNER_FEE_EXCEEDED", + "message": "partner_fee_exceeded", + "description": "The partner fee exceeds the allowed maximum for this transaction.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "LIMITS_AMOUNT_OUT_OF_RANGE": { + "summary": "LIMITS_AMOUNT_OUT_OF_RANGE", + "value": { + "success": false, + "code": "LIMITS_AMOUNT_OUT_OF_RANGE", + "message": "limits_amount_out_of_range", + "description": "The amount is outside the allowed range. The message includes the allowed range.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "LIMITS_VOLUME_EXCEEDED": { + "summary": "LIMITS_VOLUME_EXCEEDED", + "value": { + "success": false, + "code": "LIMITS_VOLUME_EXCEEDED", + "message": "limits_volume_exceeded", + "description": "You exceeded your transaction volume limit. The message includes the remaining amount available.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYINS_CARD_GATEWAY_ENVIRONMENT_MISMATCH": { + "summary": "PAYINS_CARD_GATEWAY_ENVIRONMENT_MISMATCH", + "value": { + "success": false, + "code": "PAYINS_CARD_GATEWAY_ENVIRONMENT_MISMATCH", + "message": "card_payin_gateway_environment_mismatch", + "description": "Card payins are not available in this environment. Contact support.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYINS_FUNDING_ACCOUNT_INVALID": { + "summary": "PAYINS_FUNDING_ACCOUNT_INVALID", + "value": { + "success": false, + "code": "PAYINS_FUNDING_ACCOUNT_INVALID", + "message": "funding_account_not_plaid_connected", + "description": "This bank account was entered manually and cannot be debited. Connect the account through Plaid to fund a payin from it.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYINS_METHOD_NOT_SUPPORTED": { + "summary": "PAYINS_METHOD_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYINS_METHOD_NOT_SUPPORTED", + "message": "ted_payin_not_supported", + "description": "This payment method is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYINS_TAX_ID_REQUIRED": { + "summary": "PAYINS_TAX_ID_REQUIRED", + "value": { + "success": false, + "code": "PAYINS_TAX_ID_REQUIRED", + "message": "tax_id_required", + "description": "A tax ID is required for this payment method. Provide the tax ID and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_AMOUNT_BELOW_MINIMUM": { + "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "value": { + "success": false, + "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "message": "swift_minimum_is_100_usd", + "description": "The amount is below the minimum for this payment rail.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM": { + "summary": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "value": { + "success": false, + "code": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "message": "otc_provider_minimum_not_met", + "description": "The amount is below the minimum the liquidity provider accepts for this pair. Try a larger amount.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_OTC_NOT_SUPPORTED": { + "summary": "QUOTES_OTC_NOT_SUPPORTED", + "value": { + "success": false, + "code": "QUOTES_OTC_NOT_SUPPORTED", + "message": "otc_only_supported_for_brl", + "description": "This OTC configuration is not supported. OTC requires BRL with USDT, and either the sender amount with fees not covered, or the receiver amount with fees covered.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "TOS_NOT_ACCEPTED": { + "summary": "TOS_NOT_ACCEPTED", + "value": { + "success": false, + "code": "TOS_NOT_ACCEPTED", + "message": "please_accept_terms_of_service", + "description": "The terms of service must be accepted before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -38122,21 +57994,43 @@ } } }, - "422": { - "description": "Possible error codes: `DATA_INTEGRITY_ERROR`. See the Error responses section for retry semantics.", + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `FEES_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "DATA_INTEGRITY_ERROR": { - "summary": "DATA_INTEGRITY_ERROR", + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", "value": { "success": false, - "code": "DATA_INTEGRITY_ERROR", - "message": "data_integrity_error", - "description": "This record could not be loaded because it contains invalid stored data. Contact support with the ID below.", + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_NOT_FOUND": { + "summary": "FEES_NOT_FOUND", + "value": { + "success": false, + "code": "FEES_NOT_FOUND", + "message": "partner_fee_not_found", + "description": "The requested fee configuration was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", + "value": { + "success": false, + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -38158,7 +58052,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -38169,7 +58063,7 @@ } }, "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `INTERNAL_ERROR`, `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { @@ -38186,19 +58080,32 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } } } } - }, - "put": { + } + }, + "/v1/instances/{instance_id}/payin-quotes/fx": { + "post": { "x-sdk": true, "tags": [ - "Virtual Accounts" + "Payin Quotes" ], - "summary": "Update Virtual Account", + "summary": "Get FX Rate", "parameters": [ { "schema": { @@ -38211,29 +58118,6 @@ "name": "instance_id", "in": "path" }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "bk_000000000000" - }, - "required": true, - "name": "id", - "in": "path" - }, { "schema": { "type": "string", @@ -38247,41 +58131,182 @@ } ], "requestBody": { - "description": "Update a virtual account", + "description": "Check FX rate", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateVirtualAccountIn" + "type": "object", + "properties": { + "from": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB", + "BRL", + "USD", + "MXN", + "COP", + "ARS", + "EUR", + "GBP" + ], + "example": "BRL" + }, + "to": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB", + "BRL", + "USD", + "MXN", + "COP", + "ARS", + "EUR", + "GBP" + ], + "example": "USDC" + }, + "request_amount": { + "type": "integer", + "minimum": 500, + "description": "1000 represents 10.00, 2050 represents 20.50", + "example": 1000 + }, + "currency_type": { + "type": "string", + "enum": [ + "sender", + "receiver" + ], + "description": "", + "example": "sender" + } + }, + "required": [ + "from", + "to", + "request_amount", + "currency_type" + ] } } } }, "responses": { "200": { - "description": "Update virtual account", + "description": "Check FX rate response", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Success" + "type": "object", + "properties": { + "commercial_quotation": { + "type": [ + "number", + "null" + ], + "description": "1 USD = 4.95 BRL", + "example": 495 + }, + "blindpay_quotation": { + "type": [ + "number", + "null" + ], + "description": "1 USD = 5.05 BRL (commercial quotation + (blindpay taxes))", + "example": 505 + }, + "result_amount": { + "type": "number", + "minimum": 1 + }, + "instance_flat_fee": { + "type": [ + "number", + "null" + ], + "description": "0.5 USDC", + "example": 50 + }, + "instance_percentage_fee": { + "type": "number", + "minimum": 0, + "maximum": 10000 + } + }, + "required": [ + "commercial_quotation", + "blindpay_quotation", + "result_amount", + "instance_flat_fee", + "instance_percentage_fee" + ] } } } }, "400": { - "description": "Possible error codes: `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR`, `FEES_PARTNER_FEE_EXCEEDED`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM`, `QUOTES_RATE_UNAVAILABLE`, `VALIDATION_FAILED`, `VALIDATION_INVALID_REQUEST`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { - "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR": { + "summary": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", "value": { "success": false, - "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", - "message": "network_not_supported_on_dev_instance", - "description": "This network or token combination is not supported for this operation.", + "code": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "message": "sepa_iban_not_eur", + "description": "SEPA payouts are only available to EUR accounts. This IBAN is from a country that holds another currency, so the payment would fail at settlement. Use an IBAN from a EUR account instead.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_PARTNER_FEE_EXCEEDED": { + "summary": "FEES_PARTNER_FEE_EXCEEDED", + "value": { + "success": false, + "code": "FEES_PARTNER_FEE_EXCEEDED", + "message": "partner_fee_exceeded", + "description": "The partner fee exceeds the allowed maximum for this transaction.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_AMOUNT_BELOW_MINIMUM": { + "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "value": { + "success": false, + "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "message": "swift_minimum_is_100_usd", + "description": "The amount is below the minimum for this payment rail.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM": { + "summary": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "value": { + "success": false, + "code": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "message": "otc_provider_minimum_not_met", + "description": "The amount is below the minimum the liquidity provider accepts for this pair. Try a larger amount.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -38296,6 +58321,17 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "VALIDATION_INVALID_REQUEST": { + "summary": "VALIDATION_INVALID_REQUEST", + "value": { + "success": false, + "code": "VALIDATION_INVALID_REQUEST", + "message": "invalid_body", + "description": "The request is not valid for this operation. Check the parameters and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } @@ -38348,20 +58384,20 @@ } }, "404": { - "description": "Possible error codes: `VIRTUAL_ACCOUNTS_NOT_FOUND`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "VIRTUAL_ACCOUNTS_NOT_FOUND": { - "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", - "message": "virtual_account_not_found", - "description": "The requested virtual account was not found.", + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -38383,7 +58419,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -38394,7 +58430,7 @@ } }, "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `INTERNAL_ERROR`, `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { @@ -38411,6 +58447,40 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "503": { + "description": "Possible error codes: `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } @@ -38419,13 +58489,13 @@ } } }, - "/v1/instances/{instance_id}/customers/{customer_id}/blockchain-wallets/sign-message": { + "/v1/instances/{instance_id}/payins/{id}": { "get": { "x-sdk": true, "tags": [ - "Blockchain Wallets" + "Payins" ], - "summary": "Retrieve Blockchain Wallet Message", + "summary": "Retrieve Payin", "parameters": [ { "schema": { @@ -38443,21 +58513,20 @@ "type": "string", "minLength": 15, "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" + "example": "pi_000000000000" }, "required": true, - "name": "customer_id", + "name": "id", "in": "path" } ], "responses": { "200": { - "description": "Get blockchain wallet sign message", + "description": "List payins", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/BlockchainWalletMessageOut" + "$ref": "#/components/schemas/PayinOut" } } } @@ -38531,6 +58600,29 @@ } } }, + "404": { + "description": "Possible error codes: `PAYINS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "PAYINS_NOT_FOUND": { + "summary": "PAYINS_NOT_FOUND", + "value": { + "success": false, + "code": "PAYINS_NOT_FOUND", + "message": "payin_not_found", + "description": "The requested payin was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -38544,7 +58636,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -38580,89 +58672,46 @@ } } }, - "/v1/instances/{instance_id}/customers/{customer_id}/blockchain-wallets": { - "post": { + "/v1/e/payins/{id}": { + "get": { "x-sdk": true, + "x-mcp": false, "tags": [ - "Blockchain Wallets" + "Payins" ], - "summary": "Add Blockchain Wallet", + "summary": "Retrieve Payin Track", "parameters": [ { "schema": { "type": "string", "minLength": 15, "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" + "example": "pi_000000000000" }, "required": true, - "name": "customer_id", + "name": "id", "in": "path" - }, - { - "schema": { - "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "required": false, - "name": "Idempotency-Key", - "in": "header" } ], - "requestBody": { - "description": "Create a new blockchain wallet", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateBlockchainWalletIn" - } - } - } - }, "responses": { "200": { - "description": "Add blockchain wallet", + "description": "List payins", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/BlockchainWalletOut" + "$ref": "#/components/schemas/PayinOut" } } } }, "400": { - "description": "Possible error codes: `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `VALIDATION_FAILED`, `WEBHOOKS_SIGNATURE_INVALID`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { - "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", - "value": { - "success": false, - "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", - "message": "network_not_supported_on_dev_instance", - "description": "This network or token combination is not supported for this operation.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -38673,17 +58722,6 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - }, - "WEBHOOKS_SIGNATURE_INVALID": { - "summary": "WEBHOOKS_SIGNATURE_INVALID", - "value": { - "success": false, - "code": "WEBHOOKS_SIGNATURE_INVALID", - "message": "invalid_signature", - "description": "The webhook signature is missing or invalid.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } } } } @@ -38735,6 +58773,29 @@ } } }, + "404": { + "description": "Possible error codes: `PAYINS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "PAYINS_NOT_FOUND": { + "summary": "PAYINS_NOT_FOUND", + "value": { + "success": false, + "code": "PAYINS_NOT_FOUND", + "message": "payin_not_found", + "description": "The requested payin was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -38748,7 +58809,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -38782,48 +58843,205 @@ } } } - }, + } + }, + "/v1/instances/{instance_id}/payins": { "get": { "x-sdk": true, "tags": [ - "Blockchain Wallets" + "Payins" ], - "summary": "Retrieve Blockchain Wallets", + "summary": "Retrieve Payins", "parameters": [ { "schema": { "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "enum": [ + "10", + "50", + "100", + "200", + "500", + "1000" + ], + "description": "Number of items to return", + "example": "50" + }, + "required": false, + "name": "limit", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "0", + "10", + "50", + "100", + "200", + "500", + "1000" + ], + "description": "Number of items to skip", + "example": "0" + }, + "required": false, + "name": "offset", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "A cursor for use in pagination. starting_after is an object ID that defines your place in the list.", + "example": "pi_123" + }, + "required": false, + "name": "starting_after", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "A cursor for use in pagination. ending_before is an object ID that defines your place in the list.", + "example": "pi_123" + }, + "required": false, + "name": "ending_before", + "in": "query" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "required": false, + "name": "customer_id", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "processing", + "on_hold", + "failed", + "refunded", + "completed" + ] }, - "required": true, - "name": "instance_id", - "in": "path" + "required": false, + "name": "status", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "customer_name", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "bank_account_id", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "country", + "in": "query" }, { "schema": { "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" + "enum": [ + "ach", + "ach_pull", + "wire", + "pix", + "card", + "ted", + "spei", + "transfers", + "pse", + "bre_b", + "international_swift", + "rtp" + ] }, - "required": true, - "name": "customer_id", - "in": "path" + "required": false, + "name": "payment_method", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "network", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "token", + "in": "query" } ], "responses": { "200": { - "description": "Get blockchain wallets", + "description": "List payins with pagination", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/BlockchainWalletOut" - } + "anyOf": [ + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PayinOut" + } + }, + "pagination": { + "$ref": "#/components/schemas/PaginationMetadata" + } + }, + "required": [ + "data", + "pagination" + ] + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/PayinOut" + } + } + ] } } } @@ -38910,7 +59128,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -38946,13 +59164,14 @@ } } }, - "/v1/instances/{instance_id}/customers/{customer_id}/blockchain-wallets/{id}": { - "get": { + "/v1/instances/{instance_id}/payins/evm": { + "post": { "x-sdk": true, "tags": [ - "Blockchain Wallets" + "Payins" ], - "summary": "Retrieve Blockchain Wallet", + "summary": "Create Payin", + "description": "Creates a payin from a payin quote and returns the instructions the payer uses to send funds (for example a Pix code or bank details). Create it before the payin quote expires. Send an Idempotency-Key header so a retry cannot create a second payin. On development instances the payin completes on its own about 30 seconds after creation; request_amount 66600 makes it fail and 77700 makes it refunded.", "parameters": [ { "schema": { @@ -38968,250 +59187,616 @@ { "schema": { "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "bk_000000000000" + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }, - "required": true, - "name": "id", - "in": "path" + "required": false, + "name": "Idempotency-Key", + "in": "header" } ], + "requestBody": { + "description": "Start payin", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreatePayinIn" + } + } + } + }, "responses": { "200": { - "description": "Get blockchain wallet", + "description": "Payin started with success", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/BlockchainWalletOut" + "$ref": "#/components/schemas/CreatePayinOut" } } } }, "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BANK_ACCOUNTS_INCOMPLETE`, `BANK_ACCOUNTS_INVALID_BANK_CODE`, `BANK_ACCOUNTS_INVALID_ROUTING`, `BANK_ACCOUNTS_NOT_APPROVED`, `BANK_ACCOUNTS_NOT_FOUND`, `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED`, `BANK_ACCOUNTS_PLAID_NOT_ENABLED`, `BANK_ACCOUNTS_PLAID_NOT_FIRST_PARTY`, `BANK_ACCOUNTS_RTP_NOT_SUPPORTED`, `BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `BLOCKCHAIN_TX_FAILED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_ENHANCED_KYC_REQUIRED`, `CUSTOMERS_ID_DOCUMENT_INVALID`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_KYC_NOT_APPROVED`, `CUSTOMERS_KYC_TYPE_NOT_AVAILABLE`, `CUSTOMERS_NAME_INVALID`, `CUSTOMERS_NOT_FOUND`, `CUSTOMERS_ONBOARDING_INCOMPLETE`, `CUSTOMERS_OWNERSHIP_INVALID`, `FEES_PARTNER_FEE_EXCEEDED`, `FILES_TOO_LARGE`, `FILES_UNREADABLE`, `PAYABLES_ALREADY_PAID_OR_EXPIRED`, `PAYABLES_ALREADY_PAID_OR_IN_FLIGHT`, `PAYABLES_AMOUNT_NEGATIVE`, `PAYABLES_BANK_ACCOUNT_INVALID`, `PAYABLES_CODE_UNRESOLVABLE`, `PAYABLES_CURRENCY_MUST_BE_BRL`, `PAYABLES_DESTINATION_NOT_SUPPORTED`, `PAYABLES_DOCUMENT_INVALID`, `PAYABLES_DUPLICATE`, `PAYABLES_NETWORK_NOT_SUPPORTED`, `PAYABLES_NOT_CANCELABLE`, `PAYABLES_PIX_AMOUNT_REQUIRED`, `PAYINS_CUSTOMER_USD_REGISTRATION_PENDING`, `PAYINS_CUSTOMER_USD_REGISTRATION_REJECTED`, `PAYINS_FUNDING_ACCOUNT_INVALID`, `PAYINS_METHOD_NOT_SUPPORTED`, `PAYINS_VIRTUAL_ACCOUNT_REQUIRED`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `PAYOUTS_DOCUMENTS_NOT_ACCEPTED`, `PAYOUTS_INSUFFICIENT_BALANCE`, `QUOTES_ALREADY_USED`, `QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM`, `QUOTES_EXPIRED`, `QUOTES_INVALID_STATE`, `QUOTES_NOT_FOUND`, `QUOTES_RATE_UNAVAILABLE`, `VALIDATION_FAILED`, `VALIDATION_INVALID_REQUEST`, `VALIDATION_MISSING_REQUIRED_FIELDS`, `VIRTUAL_ACCOUNTS_DISABLED`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_NOT_FOUND`, `VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`, `VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED`, `WALLETS_NOT_OWNED_BY_CUSTOMER`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "BANK_ACCOUNTS_INCOMPLETE": { + "summary": "BANK_ACCOUNTS_INCOMPLETE", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INCOMPLETE", + "message": "infinitus_missing_intermediary", + "description": "The banking provider cannot route payments to this bank automatically. Provide the US correspondent bank routing number (ABA, 9 digits) from the beneficiary bank USD wire instructions in swift_intermediary_bank_routing_number.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_INVALID_BANK_CODE": { + "summary": "BANK_ACCOUNTS_INVALID_BANK_CODE", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INVALID_BANK_CODE", + "message": "bank_accounts_invalid_bank_code", + "description": "The bank code provided is not valid for this payment rail. The message lists where to fetch the valid codes.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_INVALID_ROUTING": { + "summary": "BANK_ACCOUNTS_INVALID_ROUTING", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INVALID_ROUTING", + "message": "The routing number must be a valid 9-digit ABA routing number.", + "description": "The routing number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_NOT_APPROVED": { + "summary": "BANK_ACCOUNTS_NOT_APPROVED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_APPROVED", + "message": "bank_account_not_approved", + "description": "This bank account is not approved yet.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_NOT_FOUND": { + "summary": "BANK_ACCOUNTS_NOT_FOUND", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_FOUND", + "message": "bank_account_not_found", + "description": "The requested bank account was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "message": "unsupported_banking_partner", + "description": "This banking option is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_PLAID_NOT_ENABLED": { + "summary": "BANK_ACCOUNTS_PLAID_NOT_ENABLED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PLAID_NOT_ENABLED", + "message": "plaid_not_supported", + "description": "Instantly connected bank accounts are not enabled for this account. Contact support to enable them.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_PLAID_NOT_FIRST_PARTY": { + "summary": "BANK_ACCOUNTS_PLAID_NOT_FIRST_PARTY", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PLAID_NOT_FIRST_PARTY", + "message": "plaid_account_not_first_party", + "description": "The connected bank account does not belong to this customer. Only accounts held in the customer's own name can be connected.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_RTP_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", + "message": "The provided routing number does not support RTP transactions.", + "description": "The provided routing number does not support instant payments.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR": { + "summary": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "message": "sepa_iban_not_eur", + "description": "SEPA payouts are only available to EUR accounts. This IBAN is from a country that holds another currency, so the payment would fail at settlement. Use an IBAN from a EUR account instead.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { + "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "message": "network_not_supported_on_dev_instance", + "description": "This network or token combination is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_TX_FAILED": { + "summary": "BLOCKCHAIN_TX_FAILED", + "value": { + "success": false, + "code": "BLOCKCHAIN_TX_FAILED", + "message": "transaction_failed", + "description": "The blockchain transaction failed. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { + "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "value": { + "success": false, + "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "message": "country_not_supported", + "description": "This country is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ENHANCED_KYC_REQUIRED": { + "summary": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "value": { + "success": false, + "code": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "message": "only_enhanced_kyc_allowed_for_high_risk_countries", + "description": "Individuals from high-risk countries must use enhanced verification (kyc_type: enhanced); standard verification is not available for them. See https://www.blindpay.com/docs/kb/supported-countries for country tiers.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ID_DOCUMENT_INVALID": { + "summary": "CUSTOMERS_ID_DOCUMENT_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_ID_DOCUMENT_INVALID", + "message": "id_doc_is_not_valid_passport_or_national_id", + "description": "The identity document is not accepted for this customer. Use a national ID, a passport with a valid passport number as the tax ID, or a driver license with a valid SSN or ITIN as the tax ID.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_PHONE": { + "summary": "CUSTOMERS_INVALID_PHONE", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_PHONE", + "message": "invalid_phone_number", + "description": "The phone number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_TAX_ID": { + "summary": "CUSTOMERS_INVALID_TAX_ID", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_TAX_ID", + "message": "invalid_cpf_or_rg_tax_id", + "description": "The tax ID provided is not valid. Check the value and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_NOT_APPROVED": { + "summary": "CUSTOMERS_KYC_NOT_APPROVED", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_NOT_APPROVED", + "message": "kyc_not_approved", + "description": "This customer has not completed verification yet. Complete the verification before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE": { + "summary": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "message": "kyc_type_not_supported", + "description": "The requested verification type is not available for this customer. Use a supported verification type and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_NAME_INVALID": { + "summary": "CUSTOMERS_NAME_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_NAME_INVALID", + "message": "legal_name_required", + "description": "The name registered for this customer is not accepted. Review it and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ONBOARDING_INCOMPLETE": { + "summary": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "value": { + "success": false, + "code": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "message": "onboarding_incomplete", + "description": "Onboarding is not complete yet. Finish the remaining steps before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_OWNERSHIP_INVALID": { + "summary": "CUSTOMERS_OWNERSHIP_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_OWNERSHIP_INVALID", + "message": "business_owner_required", + "description": "The ownership information for this business customer is incomplete or inconsistent. Review the registered owners and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_PARTNER_FEE_EXCEEDED": { + "summary": "FEES_PARTNER_FEE_EXCEEDED", + "value": { + "success": false, + "code": "FEES_PARTNER_FEE_EXCEEDED", + "message": "partner_fee_exceeded", + "description": "The partner fee exceeds the allowed maximum for this transaction.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_ALREADY_PAID_OR_EXPIRED": { + "summary": "PAYABLES_ALREADY_PAID_OR_EXPIRED", + "value": { + "success": false, + "code": "PAYABLES_ALREADY_PAID_OR_EXPIRED", + "message": "payable_already_paid_or_expired", + "description": "This payment code was already paid or has expired and can no longer be paid.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT": { + "summary": "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT", + "value": { + "success": false, + "code": "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT", + "message": "payable_already_paid_or_in_flight", + "description": "This payable is already being paid or was already paid. Only draft payables can be quoted; a failed or refunded attempt returns the payable to draft.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_AMOUNT_NEGATIVE": { + "summary": "PAYABLES_AMOUNT_NEGATIVE", + "value": { + "success": false, + "code": "PAYABLES_AMOUNT_NEGATIVE", + "message": "payable_amount_negative", + "description": "The payable total (line items plus taxes minus discount) cannot be negative.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_BANK_ACCOUNT_INVALID": { + "summary": "PAYABLES_BANK_ACCOUNT_INVALID", + "value": { + "success": false, + "code": "PAYABLES_BANK_ACCOUNT_INVALID", + "message": "payable_bank_account_invalid", + "description": "The bank_account details on this invoice payable were rejected. Check the errors list for the field that failed.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_CODE_UNRESOLVABLE": { + "summary": "PAYABLES_CODE_UNRESOLVABLE", + "value": { + "success": false, + "code": "PAYABLES_CODE_UNRESOLVABLE", + "message": "unresolvable_payable_code", + "description": "We could not read this payment code. Check the code and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_CURRENCY_MUST_BE_BRL": { + "summary": "PAYABLES_CURRENCY_MUST_BE_BRL", + "value": { + "success": false, + "code": "PAYABLES_CURRENCY_MUST_BE_BRL", + "message": "payable_currency_must_be_brl", + "description": "Boleto and PIX payables must use BRL.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DESTINATION_NOT_SUPPORTED": { + "summary": "PAYABLES_DESTINATION_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYABLES_DESTINATION_NOT_SUPPORTED", + "message": "payable_destination_not_supported", + "description": "Only boleto, arrecadação (utility/tax) and PIX QR code payables can be paid right now. Bank-destination invoice payables are not payable yet.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DOCUMENT_INVALID": { + "summary": "PAYABLES_DOCUMENT_INVALID", + "value": { + "success": false, + "code": "PAYABLES_DOCUMENT_INVALID", + "message": "payable_document_invalid", + "description": "document_file must be a URL returned by POST /upload with bucket `documents`, uploaded by this instance.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DUPLICATE": { + "summary": "PAYABLES_DUPLICATE", + "value": { + "success": false, + "code": "PAYABLES_DUPLICATE", + "message": "duplicate_payable", + "description": "This payment code already has a payable registered, in progress or completed for this instance.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_NETWORK_NOT_SUPPORTED": { + "summary": "PAYABLES_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYABLES_NETWORK_NOT_SUPPORTED", + "message": "payable_network_not_supported", + "description": "Only EVM wallets can fund payables right now.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_NOT_CANCELABLE": { + "summary": "PAYABLES_NOT_CANCELABLE", + "value": { + "success": false, + "code": "PAYABLES_NOT_CANCELABLE", + "message": "payable_not_cancelable", + "description": "Only draft payables can be deleted. Once a payout is executing this payable it can no longer be canceled.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_PIX_AMOUNT_REQUIRED": { + "summary": "PAYABLES_PIX_AMOUNT_REQUIRED", + "value": { + "success": false, + "code": "PAYABLES_PIX_AMOUNT_REQUIRED", + "message": "pix_code_amount_required", + "description": "This PIX code has no fixed amount and no amount was provided. Send the amount as line_items when registering a PIX code that lets the payer choose the value.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYINS_CUSTOMER_USD_REGISTRATION_PENDING": { + "summary": "PAYINS_CUSTOMER_USD_REGISTRATION_PENDING", + "value": { + "success": false, + "code": "PAYINS_CUSTOMER_USD_REGISTRATION_PENDING", + "message": "customer_usd_registration_pending", + "description": "The customer is still being set up for US bank transfer payins (ACH, wire, RTP). Wait about a minute, then create a new payin quote and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYINS_CUSTOMER_USD_REGISTRATION_REJECTED": { + "summary": "PAYINS_CUSTOMER_USD_REGISTRATION_REJECTED", + "value": { + "success": false, + "code": "PAYINS_CUSTOMER_USD_REGISTRATION_REJECTED", + "message": "customer_usd_registration_rejected", + "description": "The customer could not be set up for US bank transfer payins (ACH, wire, RTP) because some of their details were rejected. Correct the tax_id or phone_number listed in errors with PUT /customers/{id}, create a new payin quote, wait about a minute, and try again. For any other reason, contact support with the trace_id.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYINS_FUNDING_ACCOUNT_INVALID": { + "summary": "PAYINS_FUNDING_ACCOUNT_INVALID", + "value": { + "success": false, + "code": "PAYINS_FUNDING_ACCOUNT_INVALID", + "message": "funding_account_not_plaid_connected", + "description": "This bank account was entered manually and cannot be debited. Connect the account through Plaid to fund a payin from it.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYINS_METHOD_NOT_SUPPORTED": { + "summary": "PAYINS_METHOD_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYINS_METHOD_NOT_SUPPORTED", + "message": "ted_payin_not_supported", + "description": "This payment method is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYINS_VIRTUAL_ACCOUNT_REQUIRED": { + "summary": "PAYINS_VIRTUAL_ACCOUNT_REQUIRED", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "PAYINS_VIRTUAL_ACCOUNT_REQUIRED", + "message": "international_swift_payins_require_virtual_account", + "description": "International SWIFT payins require the receiver to have an approved virtual account. Create a virtual account for this receiver and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "401": { - "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_UNAUTHORIZED": { - "summary": "AUTH_UNAUTHORIZED", + }, + "PAYOUTS_AMOUNT_BELOW_MINIMUM": { + "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", "value": { "success": false, - "code": "AUTH_UNAUTHORIZED", - "message": "unauthorized", - "description": "Authentication failed. Check your API key or session and try again.", + "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "message": "swift_minimum_is_100_usd", + "description": "The amount is below the minimum for this payment rail.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "403": { - "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_FORBIDDEN": { - "summary": "AUTH_FORBIDDEN", + }, + "PAYOUTS_DOCUMENTS_NOT_ACCEPTED": { + "summary": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", "value": { "success": false, - "code": "AUTH_FORBIDDEN", - "message": "user_not_allowed", - "description": "You do not have permission to perform this action.", + "code": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", + "message": "document_upload_only_for_swift_payouts", + "description": "A document cannot be submitted for this payout in its current state.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "422": { - "description": "Possible error codes: `DATA_INTEGRITY_ERROR`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "DATA_INTEGRITY_ERROR": { - "summary": "DATA_INTEGRITY_ERROR", + }, + "PAYOUTS_INSUFFICIENT_BALANCE": { + "summary": "PAYOUTS_INSUFFICIENT_BALANCE", "value": { "success": false, - "code": "DATA_INTEGRITY_ERROR", - "message": "data_integrity_error", - "description": "This record could not be loaded because it contains invalid stored data. Contact support with the ID below.", + "code": "PAYOUTS_INSUFFICIENT_BALANCE", + "message": "not_enough_balance", + "description": "There is not enough balance to complete this payout. Fund your balance and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", + }, + "QUOTES_ALREADY_USED": { + "summary": "QUOTES_ALREADY_USED", "value": { "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", + "code": "QUOTES_ALREADY_USED", + "message": "quote_already_used", + "description": "This quote was already used. Request a new quote.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + }, + "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM": { + "summary": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "message": "otc_provider_minimum_not_met", + "description": "The amount is below the minimum the liquidity provider accepts for this pair. Try a larger amount.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - } - } - }, - "delete": { - "x-sdk": true, - "tags": [ - "Blockchain Wallets" - ], - "summary": "Remove Blockchain Wallet", - "parameters": [ - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "bk_000000000000" - }, - "required": true, - "name": "id", - "in": "path" - }, - { - "schema": { - "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "required": false, - "name": "Idempotency-Key", - "in": "header" - } - ], - "responses": { - "200": { - "description": "Delete blockchain wallet", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Success" - } - } - } - }, - "400": { - "description": "Possible error codes: `VALIDATION_FAILED`, `WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { + }, + "QUOTES_EXPIRED": { + "summary": "QUOTES_EXPIRED", + "value": { + "success": false, + "code": "QUOTES_EXPIRED", + "message": "quote_expired", + "description": "This quote has expired. Request a new quote and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_INVALID_STATE": { + "summary": "QUOTES_INVALID_STATE", + "value": { + "success": false, + "code": "QUOTES_INVALID_STATE", + "message": "quote_invalid_state", + "description": "This quote cannot be authorized in its current state. Request a new quote and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_NOT_FOUND": { + "summary": "QUOTES_NOT_FOUND", + "value": { + "success": false, + "code": "QUOTES_NOT_FOUND", + "message": "quote_not_found", + "description": "The requested quote was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -39223,328 +59808,101 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT": { - "summary": "WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT", + "VALIDATION_INVALID_REQUEST": { + "summary": "VALIDATION_INVALID_REQUEST", "value": { "success": false, - "code": "WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT", - "message": "wallet_attached_to_virtual_account", - "description": "This wallet is attached to a virtual account and cannot be deleted. Delete the virtual account first.", + "code": "VALIDATION_INVALID_REQUEST", + "message": "invalid_body", + "description": "The request is not valid for this operation. Check the parameters and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "401": { - "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_UNAUTHORIZED": { - "summary": "AUTH_UNAUTHORIZED", + }, + "VALIDATION_MISSING_REQUIRED_FIELDS": { + "summary": "VALIDATION_MISSING_REQUIRED_FIELDS", "value": { "success": false, - "code": "AUTH_UNAUTHORIZED", - "message": "unauthorized", - "description": "Authentication failed. Check your API key or session and try again.", + "code": "VALIDATION_MISSING_REQUIRED_FIELDS", + "message": "missing_required_fields", + "description": "Required fields are missing. Provide the missing fields and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "403": { - "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_FORBIDDEN": { - "summary": "AUTH_FORBIDDEN", + }, + "VIRTUAL_ACCOUNTS_DISABLED": { + "summary": "VIRTUAL_ACCOUNTS_DISABLED", "value": { "success": false, - "code": "AUTH_FORBIDDEN", - "message": "user_not_allowed", - "description": "You do not have permission to perform this action.", + "code": "VIRTUAL_ACCOUNTS_DISABLED", + "message": "virtual_accounts_not_enabled", + "description": "Virtual accounts are not enabled for this account. Contact support to enable them.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "404": { - "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "WALLETS_NOT_FOUND": { - "summary": "WALLETS_NOT_FOUND", + }, + "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { + "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", "value": { "success": false, - "code": "WALLETS_NOT_FOUND", - "message": "wallet_not_found", - "description": "The requested wallet was not found.", + "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "message": "id_doc_front_file_required", + "description": "An identity document is required for this customer. Upload the front of a valid document and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", + }, + "VIRTUAL_ACCOUNTS_NOT_FOUND": { + "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", "value": { "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", + "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "message": "virtual_account_not_found", + "description": "The requested virtual account was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + }, + "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE": { + "summary": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "message": "banking_partner_not_eligible_for_customer", + "description": "This banking partner is not available for this customer. Choose a different banking partner.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - } - } - } - }, - "/v1/instances/{instance_id}/customers/{customer_id}/bank-accounts/{bank_account_id}/offramp-wallets": { - "post": { - "x-sdk": true, - "tags": [ - "Offramp Wallets" - ], - "summary": "Create Offramp Wallet", - "parameters": [ - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "ba_000000000000" - }, - "required": true, - "name": "bank_account_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "required": false, - "name": "Idempotency-Key", - "in": "header" - } - ], - "requestBody": { - "description": "Create a new offramp wallet", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "external_id": { - "type": [ - "string", - "null" - ], - "example": "your_external_id" - }, - "network": { - "type": "string", - "enum": [ - "tron", - "solana", - "solana_devnet", - "arbitrum", - "base", - "ethereum", - "polygon", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "polygon_amoy" - ], - "example": "tron" - } - }, - "required": [ - "network" - ] - } - } - } - }, - "responses": { - "200": { - "description": "Create offramp wallet", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "id": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "ow_000000000000" - }, - "external_id": { - "type": [ - "string", - "null" - ], - "example": "your_external_id" - }, - "circle_wallet_id": { - "type": [ - "string", - "null" - ], - "example": "01234567-abcd-efgh-ijkl-012345678901" - }, - "network": { - "type": "string", - "enum": [ - "tron", - "solana", - "solana_devnet", - "arbitrum", - "base", - "ethereum", - "polygon", - "sepolia", - "arbitrum_sepolia", - "base_sepolia", - "polygon_amoy" - ], - "example": "tron" - }, - "address": { - "type": "string", - "example": "TALJN9zTTEL9TVBb4WuTt6wLvPqJZr3hvb" - } }, - "required": [ - "id", - "network", - "address" - ] - } - } - } - }, - "400": { - "description": "Possible error codes: `BANK_ACCOUNTS_INCOMPLETE`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "BANK_ACCOUNTS_INCOMPLETE": { - "summary": "BANK_ACCOUNTS_INCOMPLETE", + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", "value": { "success": false, - "code": "BANK_ACCOUNTS_INCOMPLETE", - "message": "sepa_bank_account_incomplete", - "description": "The bank account details are incomplete for this payment method. Provide the missing fields.", + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { - "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED": { + "summary": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", "value": { "success": false, - "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", - "message": "network_not_supported_on_dev_instance", - "description": "This network or token combination is not supported for this operation.", + "code": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", + "message": "us_state_not_supported", + "description": "Virtual accounts are not available for this country or region.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "WALLETS_NOT_OWNED_BY_CUSTOMER": { + "summary": "WALLETS_NOT_OWNED_BY_CUSTOMER", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "WALLETS_NOT_OWNED_BY_CUSTOMER", + "message": "blockchain_wallet_does_not_belong_to_customer", + "description": "The selected wallet belongs to a different customer. Choose one of this customer's wallets.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -39599,6 +59957,129 @@ } } }, + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `FEES_NOT_FOUND`, `INSTANCES_NOT_FOUND`, `PAYABLES_NOT_FOUND`, `PAYINS_NOT_FOUND`, `PAYOUTS_NOT_FOUND`, `QUOTES_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", + "value": { + "success": false, + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_NOT_FOUND": { + "summary": "FEES_NOT_FOUND", + "value": { + "success": false, + "code": "FEES_NOT_FOUND", + "message": "partner_fee_not_found", + "description": "The requested fee configuration was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "INSTANCES_NOT_FOUND": { + "summary": "INSTANCES_NOT_FOUND", + "value": { + "success": false, + "code": "INSTANCES_NOT_FOUND", + "message": "instance_not_found", + "description": "The requested instance was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_NOT_FOUND": { + "summary": "PAYABLES_NOT_FOUND", + "value": { + "success": false, + "code": "PAYABLES_NOT_FOUND", + "message": "payable_not_found", + "description": "This payable was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYINS_NOT_FOUND": { + "summary": "PAYINS_NOT_FOUND", + "value": { + "success": false, + "code": "PAYINS_NOT_FOUND", + "message": "payin_not_found", + "description": "The requested payin was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_NOT_FOUND": { + "summary": "PAYOUTS_NOT_FOUND", + "value": { + "success": false, + "code": "PAYOUTS_NOT_FOUND", + "message": "payout_not_found", + "description": "The requested payout was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_NOT_FOUND": { + "summary": "QUOTES_NOT_FOUND", + "value": { + "success": false, + "code": "QUOTES_NOT_FOUND", + "message": "quote_not_found", + "description": "The requested quote was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", + "value": { + "success": false, + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "422": { + "description": "Possible error codes: `CUSTOMERS_INVALID_DATA`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "CUSTOMERS_INVALID_DATA": { + "summary": "CUSTOMERS_INVALID_DATA", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_DATA", + "message": "invalid_customer_data", + "description": "The customer data was rejected by the banking provider. Check the highlighted fields and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -39612,7 +60093,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -39623,13 +60104,24 @@ } }, "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `QUOTES_RATE_UNAVAILABLE`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -39640,19 +60132,100 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "502": { + "description": "Possible error codes: `PAYINS_FUNDING_PULL_FAILED`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "PAYINS_FUNDING_PULL_FAILED": { + "summary": "PAYINS_FUNDING_PULL_FAILED", + "value": { + "success": false, + "code": "PAYINS_FUNDING_PULL_FAILED", + "message": "funding_pull_failed", + "description": "We could not debit the selected bank account. The payin was not started. Request a new quote and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "503": { + "description": "Possible error codes: `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", + "value": { + "success": false, + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } } } } - }, - "get": { - "x-sdk": true, + } + }, + "/v1/instances/{instance_id}/payins/{payin_id}/card-payment": { + "post": { + "x-sdk": false, "tags": [ - "Offramp Wallets" + "Payins" ], - "summary": "Get Offramp Wallets", + "summary": "Submit Card Payment", "parameters": [ { "schema": { @@ -39670,47 +60243,64 @@ "type": "string", "minLength": 15, "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "ba_000000000000" + "example": "pi_000000000000" }, "required": true, - "name": "bank_account_id", + "name": "payin_id", "in": "path" } ], + "requestBody": { + "description": "Charge a tokenized card for a card payin. Stablecoins are released only after the gateway confirms the sale and every risk gate passes.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateCardPaymentIn" + } + } + } + }, "responses": { "200": { - "description": "Get offramp wallets", + "description": "Card payment confirmed; the stablecoin delivery pipeline was released", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OfframpWallet" - } + "$ref": "#/components/schemas/CreateCardPaymentOut" } } } }, "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `PAYINS_CARD_GATEWAY_ENVIRONMENT_MISMATCH`, `PAYINS_METHOD_NOT_SUPPORTED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "PAYINS_CARD_GATEWAY_ENVIRONMENT_MISMATCH": { + "summary": "PAYINS_CARD_GATEWAY_ENVIRONMENT_MISMATCH", + "value": { + "success": false, + "code": "PAYINS_CARD_GATEWAY_ENVIRONMENT_MISMATCH", + "message": "card_payin_gateway_environment_mismatch", + "description": "Card payins are not available in this environment. Contact support.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYINS_METHOD_NOT_SUPPORTED": { + "summary": "PAYINS_METHOD_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYINS_METHOD_NOT_SUPPORTED", + "message": "ted_payin_not_supported", + "description": "This payment method is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -39749,6 +60339,29 @@ } } }, + "402": { + "description": "Possible error codes: `PAYINS_CARD_PAYMENT_DECLINED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "PAYINS_CARD_PAYMENT_DECLINED": { + "summary": "PAYINS_CARD_PAYMENT_DECLINED", + "value": { + "success": false, + "code": "PAYINS_CARD_PAYMENT_DECLINED", + "message": "card_payment_declined", + "description": "The card payment was declined by the gateway or issuer. The payin is still open: tokenize the card again and retry, or use another card.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "403": { "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", "content": { @@ -39773,20 +60386,54 @@ } }, "404": { - "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `INSTANCES_NOT_FOUND`, `PAYINS_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "WALLETS_NOT_FOUND": { - "summary": "WALLETS_NOT_FOUND", + "INSTANCES_NOT_FOUND": { + "summary": "INSTANCES_NOT_FOUND", "value": { "success": false, - "code": "WALLETS_NOT_FOUND", - "message": "wallet_not_found", - "description": "The requested wallet was not found.", + "code": "INSTANCES_NOT_FOUND", + "message": "instance_not_found", + "description": "The requested instance was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYINS_NOT_FOUND": { + "summary": "PAYINS_NOT_FOUND", + "value": { + "success": false, + "code": "PAYINS_NOT_FOUND", + "message": "payin_not_found", + "description": "The requested payin was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "409": { + "description": "Possible error codes: `PAYINS_CARD_ALREADY_CHARGED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "PAYINS_CARD_ALREADY_CHARGED": { + "summary": "PAYINS_CARD_ALREADY_CHARGED", + "value": { + "success": false, + "code": "PAYINS_CARD_ALREADY_CHARGED", + "message": "card_already_charged", + "description": "A card charge attempt is already recorded for this payin. Each payin accepts exactly one card charge.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -39808,7 +60455,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -39840,83 +60487,105 @@ } } } + }, + "502": { + "description": "Possible error codes: `PAYINS_CARD_PAYMENT_PENDING`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "PAYINS_CARD_PAYMENT_PENDING": { + "summary": "PAYINS_CARD_PAYMENT_PENDING", + "value": { + "success": false, + "code": "PAYINS_CARD_PAYMENT_PENDING", + "message": "card_payment_pending_confirmation", + "description": "The card charge outcome could not be confirmed with the gateway. Do not retry: the charge may have gone through. The gateway webhook or an operator resolves the final state.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } } } } }, - "/v1/instances/{instance_id}/customers/{customer_id}/bank-accounts/{bank_account_id}/offramp-wallets/{id}": { - "get": { - "x-sdk": true, + "/v1/e/payins/{payin_id}/card-payment": { + "post": { + "x-sdk": false, + "x-mcp": false, "tags": [ - "Offramp Wallets" + "Payins" ], - "summary": "Get Offramp Wallet", + "summary": "Submit Card Payment (hosted checkout, development instances only)", "parameters": [ { "schema": { "type": "string", "minLength": 15, "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "ba_000000000000" - }, - "required": true, - "name": "bank_account_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "ow_000000000000" + "example": "pi_000000000000" }, "required": true, - "name": "id", + "name": "payin_id", "in": "path" } ], + "requestBody": { + "description": "Charge a tokenized card from the hosted checkout page. Development instances only: this route carries no API key, so it may never reach the live gateway, and a payer-authentication result submitted here would be unverifiable.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateCardPaymentIn" + } + } + } + }, "responses": { "200": { - "description": "Get offramp wallet", + "description": "Card payment confirmed; the stablecoin delivery pipeline was released", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OfframpWallet" + "$ref": "#/components/schemas/CreateCardPaymentOut" } } } }, "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `PAYINS_CARD_GATEWAY_ENVIRONMENT_MISMATCH`, `PAYINS_METHOD_NOT_SUPPORTED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "PAYINS_CARD_GATEWAY_ENVIRONMENT_MISMATCH": { + "summary": "PAYINS_CARD_GATEWAY_ENVIRONMENT_MISMATCH", + "value": { + "success": false, + "code": "PAYINS_CARD_GATEWAY_ENVIRONMENT_MISMATCH", + "message": "card_payin_gateway_environment_mismatch", + "description": "Card payins are not available in this environment. Contact support.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYINS_METHOD_NOT_SUPPORTED": { + "summary": "PAYINS_METHOD_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYINS_METHOD_NOT_SUPPORTED", + "message": "ted_payin_not_supported", + "description": "This payment method is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -39944,9 +60613,89 @@ "summary": "AUTH_UNAUTHORIZED", "value": { "success": false, - "code": "AUTH_UNAUTHORIZED", - "message": "unauthorized", - "description": "Authentication failed. Check your API key or session and try again.", + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "402": { + "description": "Possible error codes: `PAYINS_CARD_PAYMENT_DECLINED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "PAYINS_CARD_PAYMENT_DECLINED": { + "summary": "PAYINS_CARD_PAYMENT_DECLINED", + "value": { + "success": false, + "code": "PAYINS_CARD_PAYMENT_DECLINED", + "message": "card_payment_declined", + "description": "The card payment was declined by the gateway or issuer. The payin is still open: tokenize the card again and retry, or use another card.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "404": { + "description": "Possible error codes: `INSTANCES_NOT_FOUND`, `PAYINS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INSTANCES_NOT_FOUND": { + "summary": "INSTANCES_NOT_FOUND", + "value": { + "success": false, + "code": "INSTANCES_NOT_FOUND", + "message": "instance_not_found", + "description": "The requested instance was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYINS_NOT_FOUND": { + "summary": "PAYINS_NOT_FOUND", + "value": { + "success": false, + "code": "PAYINS_NOT_FOUND", + "message": "payin_not_found", + "description": "The requested payin was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -39955,21 +60704,21 @@ } } }, - "403": { - "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "409": { + "description": "Possible error codes: `PAYINS_CARD_ALREADY_CHARGED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "AUTH_FORBIDDEN": { - "summary": "AUTH_FORBIDDEN", + "PAYINS_CARD_ALREADY_CHARGED": { + "summary": "PAYINS_CARD_ALREADY_CHARGED", "value": { "success": false, - "code": "AUTH_FORBIDDEN", - "message": "user_not_allowed", - "description": "You do not have permission to perform this action.", + "code": "PAYINS_CARD_ALREADY_CHARGED", + "message": "card_already_charged", + "description": "A card charge attempt is already recorded for this payin. Each payin accepts exactly one card charge.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -39991,7 +60740,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -40023,17 +60772,40 @@ } } } + }, + "502": { + "description": "Possible error codes: `PAYINS_CARD_PAYMENT_PENDING`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "PAYINS_CARD_PAYMENT_PENDING": { + "summary": "PAYINS_CARD_PAYMENT_PENDING", + "value": { + "success": false, + "code": "PAYINS_CARD_PAYMENT_PENDING", + "message": "card_payment_pending_confirmation", + "description": "The card charge outcome could not be confirmed with the gateway. Do not retry: the charge may have gone through. The gateway webhook or an operator resolves the final state.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } } } } }, - "/v1/instances/{instance_id}/quotes": { + "/v1/instances/{instance_id}/customers/{customer_id}/wallets": { "post": { "x-sdk": true, "tags": [ - "Payouts Quotes" + "Wallets" ], - "summary": "Create Quote", + "summary": "Create Wallet", "parameters": [ { "schema": { @@ -40046,6 +60818,18 @@ "name": "instance_id", "in": "path" }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + }, { "schema": { "type": "string", @@ -40059,56 +60843,34 @@ } ], "requestBody": { - "description": "Create a new quote", + "description": "Create a new wallet", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/QuoteIn" + "$ref": "#/components/schemas/CreateWalletIn" } } } }, "responses": { "200": { - "description": "Quote creation details", + "description": "Wallet created", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/QuoteOut" + "$ref": "#/components/schemas/WalletOut" } } } }, "400": { - "description": "Possible error codes: `BANK_ACCOUNTS_INCOMPLETE`, `BANK_ACCOUNTS_NOT_APPROVED`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_KYC_NOT_APPROVED`, `FEES_PARTNER_FEE_EXCEEDED`, `FILES_UNREADABLE`, `LIMITS_AMOUNT_OUT_OF_RANGE`, `LIMITS_VOLUME_EXCEEDED`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `QUOTES_RATE_UNAVAILABLE`, `TOS_NOT_ACCEPTED`, `VALIDATION_FAILED`, `VIRTUAL_ACCOUNTS_NOT_APPROVED`, `VIRTUAL_ACCOUNTS_NOT_FOUND`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_KYC_NOT_APPROVED`, `VALIDATION_FAILED`, `VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED`, `WALLETS_LIMIT_REACHED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "BANK_ACCOUNTS_INCOMPLETE": { - "summary": "BANK_ACCOUNTS_INCOMPLETE", - "value": { - "success": false, - "code": "BANK_ACCOUNTS_INCOMPLETE", - "message": "sepa_bank_account_incomplete", - "description": "The bank account details are incomplete for this payment method. Provide the missing fields.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "BANK_ACCOUNTS_NOT_APPROVED": { - "summary": "BANK_ACCOUNTS_NOT_APPROVED", - "value": { - "success": false, - "code": "BANK_ACCOUNTS_NOT_APPROVED", - "message": "bank_account_not_approved", - "description": "This bank account is not approved yet.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", "value": { @@ -40120,17 +60882,6 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { - "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", - "value": { - "success": false, - "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", - "message": "country_not_supported", - "description": "This country is not supported for this operation.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "CUSTOMERS_KYC_NOT_APPROVED": { "summary": "CUSTOMERS_KYC_NOT_APPROVED", "value": { @@ -40142,83 +60893,6 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "FEES_PARTNER_FEE_EXCEEDED": { - "summary": "FEES_PARTNER_FEE_EXCEEDED", - "value": { - "success": false, - "code": "FEES_PARTNER_FEE_EXCEEDED", - "message": "partner_fee_exceeded", - "description": "The partner fee exceeds the allowed maximum for this transaction.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", - "value": { - "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "LIMITS_AMOUNT_OUT_OF_RANGE": { - "summary": "LIMITS_AMOUNT_OUT_OF_RANGE", - "value": { - "success": false, - "code": "LIMITS_AMOUNT_OUT_OF_RANGE", - "message": "limits_amount_out_of_range", - "description": "The amount is outside the allowed range. The message includes the allowed range.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "LIMITS_VOLUME_EXCEEDED": { - "summary": "LIMITS_VOLUME_EXCEEDED", - "value": { - "success": false, - "code": "LIMITS_VOLUME_EXCEEDED", - "message": "limits_volume_exceeded", - "description": "You exceeded your transaction volume limit. The message includes the remaining amount available.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "PAYOUTS_AMOUNT_BELOW_MINIMUM": { - "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", - "value": { - "success": false, - "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", - "message": "swift_minimum_is_100_usd", - "description": "The amount is below the minimum for this payment rail.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "QUOTES_RATE_UNAVAILABLE": { - "summary": "QUOTES_RATE_UNAVAILABLE", - "value": { - "success": false, - "code": "QUOTES_RATE_UNAVAILABLE", - "message": "fx_rate_unavailable", - "description": "An exchange rate is temporarily unavailable. Try again shortly.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "TOS_NOT_ACCEPTED": { - "summary": "TOS_NOT_ACCEPTED", - "value": { - "success": false, - "code": "TOS_NOT_ACCEPTED", - "message": "please_accept_terms_of_service", - "description": "The terms of service must be accepted before continuing.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -40230,24 +60904,24 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VIRTUAL_ACCOUNTS_NOT_APPROVED": { - "summary": "VIRTUAL_ACCOUNTS_NOT_APPROVED", + "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED": { + "summary": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_NOT_APPROVED", - "message": "virtual_account_not_approved", - "description": "This virtual account is not approved yet.", + "code": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", + "message": "us_state_not_supported", + "description": "Virtual accounts are not available for this country or region.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VIRTUAL_ACCOUNTS_NOT_FOUND": { - "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "WALLETS_LIMIT_REACHED": { + "summary": "WALLETS_LIMIT_REACHED", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", - "message": "virtual_account_not_found", - "description": "The requested virtual account was not found.", + "code": "WALLETS_LIMIT_REACHED", + "message": "wallet_limit_reached", + "description": "You reached the maximum of 10 wallets for this customer. Delete an existing wallet first.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -40302,54 +60976,114 @@ } } }, - "404": { - "description": "Possible error codes: `BANK_ACCOUNTS_NOT_FOUND`, `CUSTOMERS_NOT_FOUND`, `FEES_NOT_FOUND`, `INSTANCES_NOT_FOUND`. See the Error responses section for retry semantics.", + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "BANK_ACCOUNTS_NOT_FOUND": { - "summary": "BANK_ACCOUNTS_NOT_FOUND", - "value": { - "success": false, - "code": "BANK_ACCOUNTS_NOT_FOUND", - "message": "bank_account_not_found", - "description": "The requested bank account was not found.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_NOT_FOUND": { - "summary": "CUSTOMERS_NOT_FOUND", + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", "value": { "success": false, - "code": "CUSTOMERS_NOT_FOUND", - "message": "customer_not_found", - "description": "The requested customer was not found.", + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - }, - "FEES_NOT_FOUND": { - "summary": "FEES_NOT_FOUND", + } + } + } + } + }, + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", "value": { "success": false, - "code": "FEES_NOT_FOUND", - "message": "partner_fee_not_found", - "description": "The requested fee configuration was not found.", + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - }, - "INSTANCES_NOT_FOUND": { - "summary": "INSTANCES_NOT_FOUND", + } + } + } + } + } + } + }, + "get": { + "x-sdk": true, + "tags": [ + "Wallets" + ], + "summary": "Retrieve Wallets", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Get wallets", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WalletOut" + } + } + } + } + }, + "400": { + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", "value": { "success": false, - "code": "INSTANCES_NOT_FOUND", - "message": "instance_not_found", - "description": "The requested instance was not found.", + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -40358,21 +61092,21 @@ } } }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", "value": { "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -40381,32 +61115,44 @@ } } }, - "500": { - "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", "value": { "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - }, - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -40415,21 +61161,21 @@ } } }, - "503": { - "description": "Possible error codes: `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "QUOTES_RATE_UNAVAILABLE": { - "summary": "QUOTES_RATE_UNAVAILABLE", + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", "value": { "success": false, - "code": "QUOTES_RATE_UNAVAILABLE", - "message": "fx_rate_unavailable", - "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -40441,13 +61187,13 @@ } } }, - "/v1/instances/{instance_id}/quotes/fx": { - "post": { + "/v1/instances/{instance_id}/customers/{customer_id}/wallets/{id}": { + "get": { "x-sdk": true, "tags": [ - "Payouts Quotes" + "Wallets" ], - "summary": "Get FX Rate", + "summary": "Retrieve Wallet", "parameters": [ { "schema": { @@ -40463,151 +61209,46 @@ { "schema": { "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" }, - "required": false, - "name": "Idempotency-Key", - "in": "header" + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" + }, + "required": true, + "name": "id", + "in": "path" } ], - "requestBody": { - "description": "Check FX rate", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "from": { - "type": "string", - "enum": [ - "USDC", - "USDT", - "USDB" - ], - "example": "USDC" - }, - "to": { - "type": "string", - "enum": [ - "BRL", - "USD", - "MXN", - "COP", - "ARS", - "EUR" - ], - "example": "BRL" - }, - "request_amount": { - "type": "integer", - "minimum": 500, - "description": "1000 represents 10.00, 2050 represents 20.50", - "example": 1000 - }, - "currency_type": { - "type": "string", - "enum": [ - "sender", - "receiver" - ], - "description": "", - "example": "sender" - } - }, - "required": [ - "from", - "to", - "request_amount", - "currency_type" - ] - } - } - } - }, "responses": { "200": { - "description": "Check FX rate response", + "description": "Get wallet", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "commercial_quotation": { - "type": [ - "number", - "null" - ], - "description": "1 USD = 4.95 BRL", - "example": 495 - }, - "blindpay_quotation": { - "type": [ - "number", - "null" - ], - "description": "1 USD = 4.85 BRL (commercial quotation - (blindpay taxes))", - "example": 485 - }, - "result_amount": { - "type": "number", - "minimum": 1 - }, - "instance_flat_fee": { - "type": [ - "number", - "null" - ], - "description": "0.5 USDC", - "example": 50 - }, - "instance_percentage_fee": { - "type": "number", - "minimum": 0, - "maximum": 10000 - } - }, - "required": [ - "commercial_quotation", - "blindpay_quotation", - "result_amount", - "instance_percentage_fee" - ] + "$ref": "#/components/schemas/WalletOut" } } } }, "400": { - "description": "Possible error codes: `BANK_ACCOUNTS_INCOMPLETE`, `QUOTES_RATE_UNAVAILABLE`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "BANK_ACCOUNTS_INCOMPLETE": { - "summary": "BANK_ACCOUNTS_INCOMPLETE", - "value": { - "success": false, - "code": "BANK_ACCOUNTS_INCOMPLETE", - "message": "sepa_bank_account_incomplete", - "description": "The bank account details are incomplete for this payment method. Provide the missing fields.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "QUOTES_RATE_UNAVAILABLE": { - "summary": "QUOTES_RATE_UNAVAILABLE", - "value": { - "success": false, - "code": "QUOTES_RATE_UNAVAILABLE", - "message": "fx_rate_unavailable", - "description": "An exchange rate is temporarily unavailable. Try again shortly.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -40682,7 +61323,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -40714,40 +61355,15 @@ } } } - }, - "503": { - "description": "Possible error codes: `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "QUOTES_RATE_UNAVAILABLE": { - "summary": "QUOTES_RATE_UNAVAILABLE", - "value": { - "success": false, - "code": "QUOTES_RATE_UNAVAILABLE", - "message": "fx_rate_unavailable", - "description": "An exchange rate is temporarily unavailable. Try again shortly.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } } } - } - }, - "/v1/instances/{instance_id}/payouts/{id}": { - "get": { + }, + "delete": { "x-sdk": true, "tags": [ - "Payouts" + "Wallets" ], - "summary": "Retrieve Payout", + "summary": "Remove Wallet", "parameters": [ { "schema": { @@ -40765,26 +61381,49 @@ "type": "string", "minLength": 15, "maxLength": 15, - "example": "pa_000000000000" + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" }, "required": true, "name": "id", "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 255, + "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", + "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + }, + "required": false, + "name": "Idempotency-Key", + "in": "header" } ], "responses": { "200": { - "description": "List payouts", + "description": "Delete wallet", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PayoutOut" + "$ref": "#/components/schemas/Success" } } } }, "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `VALIDATION_FAILED`, `WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT`, `WALLETS_HAS_FUNDS`, `YIELD_WALLET_NOT_EMPTY`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { @@ -40801,6 +61440,39 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT": { + "summary": "WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT", + "value": { + "success": false, + "code": "WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT", + "message": "wallet_attached_to_virtual_account", + "description": "This wallet is attached to a virtual account and cannot be deleted. Delete the virtual account first.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_HAS_FUNDS": { + "summary": "WALLETS_HAS_FUNDS", + "value": { + "success": false, + "code": "WALLETS_HAS_FUNDS", + "message": "wallet_has_funds", + "description": "This wallet still holds funds. Transfer them out before deleting it.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "YIELD_WALLET_NOT_EMPTY": { + "summary": "YIELD_WALLET_NOT_EMPTY", + "value": { + "success": false, + "code": "YIELD_WALLET_NOT_EMPTY", + "message": "wallet_yield_not_empty", + "description": "This wallet still has funds earning yield. Disable yield and wait for it to settle before deleting the wallet.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } @@ -40852,29 +61524,6 @@ } } }, - "404": { - "description": "Possible error codes: `PAYOUTS_NOT_FOUND`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "PAYOUTS_NOT_FOUND": { - "summary": "PAYOUTS_NOT_FOUND", - "value": { - "success": false, - "code": "PAYOUTS_NOT_FOUND", - "message": "payout_not_found", - "description": "The requested payout was not found.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -40888,7 +61537,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -40924,20 +61573,44 @@ } } }, - "/v1/e/payouts/{id}": { + "/v1/instances/{instance_id}/customers/{customer_id}/wallets/{id}/balance": { "get": { "x-sdk": true, "tags": [ - "Payouts" + "Wallets" ], - "summary": "Retrieve Payout Track", + "summary": "Retrieve Wallet Balance", + "description": "Returns the balance of a BlindPay-managed wallet for USDC, USDT and USDB, plus EURC (EURB on development instances) on Base. Unlike quote and payout amounts, these values are whole tokens, not cents: amount 10.5 means 10.5 USDC. total_amount is amount plus earning_amount from yield.", "parameters": [ { "schema": { "type": "string", "minLength": 15, "maxLength": 15, - "example": "pa_000000000000" + "example": "in_000000000000" + }, + "required": true, + "name": "instance_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" }, "required": true, "name": "id", @@ -40946,11 +61619,11 @@ ], "responses": { "200": { - "description": "List payouts", + "description": "Get wallet balance", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PayoutOut" + "$ref": "#/components/schemas/WalletBalanceOut" } } } @@ -41024,21 +61697,21 @@ } } }, - "404": { - "description": "Possible error codes: `PAYOUTS_NOT_FOUND`. See the Error responses section for retry semantics.", + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "PAYOUTS_NOT_FOUND": { - "summary": "PAYOUTS_NOT_FOUND", + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", "value": { "success": false, - "code": "PAYOUTS_NOT_FOUND", - "message": "payout_not_found", - "description": "The requested payout was not found.", + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -41047,21 +61720,21 @@ } } }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", "value": { "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -41070,21 +61743,32 @@ } } }, - "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "503": { + "description": "Possible error codes: `WALLETS_BALANCE_UNAVAILABLE`, `YIELD_POSITION_UNAVAILABLE`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + "WALLETS_BALANCE_UNAVAILABLE": { + "summary": "WALLETS_BALANCE_UNAVAILABLE", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "WALLETS_BALANCE_UNAVAILABLE", + "message": "balance_temporarily_unavailable", + "description": "The wallet balance is temporarily unavailable. Try again shortly.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "YIELD_POSITION_UNAVAILABLE": { + "summary": "YIELD_POSITION_UNAVAILABLE", + "value": { + "success": false, + "code": "YIELD_POSITION_UNAVAILABLE", + "message": "yield_position_unavailable", + "description": "The wallet yield position is temporarily unavailable. Try again shortly.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -41096,13 +61780,14 @@ } } }, - "/v1/instances/{instance_id}/payouts": { + "/v1/instances/{instance_id}/customers/{customer_id}/wallets/{id}/deposits": { "get": { "x-sdk": true, "tags": [ - "Payouts" + "Wallets" ], - "summary": "Retrieve Payouts", + "summary": "List Wallet Deposits", + "description": "Incoming stablecoin deposits to a managed wallet, newest first.", "parameters": [ { "schema": { @@ -41115,189 +61800,109 @@ "name": "instance_id", "in": "path" }, - { - "schema": { - "type": "string", - "enum": [ - "10", - "50", - "100", - "200", - "500", - "1000" - ], - "description": "Number of items to return", - "example": "50" - }, - "required": false, - "name": "limit", - "in": "query" - }, - { - "schema": { - "type": "string", - "enum": [ - "0", - "10", - "50", - "100", - "200", - "500", - "1000" - ], - "description": "Number of items to skip", - "example": "0" - }, - "required": false, - "name": "offset", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "A cursor for use in pagination. starting_after is an object ID that defines your place in the list.", - "example": "pi_123" - }, - "required": false, - "name": "starting_after", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "A cursor for use in pagination. ending_before is an object ID that defines your place in the list.", - "example": "pi_123" - }, - "required": false, - "name": "ending_before", - "in": "query" - }, { "schema": { "type": "string", "minLength": 15, "maxLength": 15, + "description": "Customer ID", "example": "re_000000000000" }, - "required": false, + "required": true, "name": "customer_id", - "in": "query" + "in": "path" }, { "schema": { "type": "string", - "enum": [ - "processing", - "failed", - "refunded", - "completed", - "on_hold" - ] + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" }, - "required": false, - "name": "status", - "in": "query" + "required": true, + "name": "id", + "in": "path" }, { "schema": { - "type": "string" + "type": "string", + "enum": [ + "5", + "10", + "50", + "100", + "200" + ], + "description": "Number of items to return", + "example": "10" }, "required": false, - "name": "customer_name", + "name": "limit", "in": "query" }, { "schema": { - "type": "string" + "type": "string", + "description": "A cursor for use in pagination. starting_after is an object ID that defines your place in the list.", + "example": "pi_123" }, "required": false, - "name": "bank_account_id", + "name": "starting_after", "in": "query" }, { "schema": { - "type": "string" + "type": "string", + "description": "A cursor for use in pagination. ending_before is an object ID that defines your place in the list.", + "example": "pi_123" }, "required": false, - "name": "country", + "name": "ending_before", "in": "query" }, { "schema": { "type": "string", "enum": [ - "wire", - "ach", - "pix", - "pix_safe", - "ted", - "spei_bitso", - "transfers_bitso", - "ach_cop_bitso", - "international_swift", - "rtp", - "sepa" + "USDC", + "USDT", + "USDB", + "EURC", + "EURB" ] }, "required": false, - "name": "payment_method", - "in": "query" - }, - { - "schema": { - "type": "string" - }, - "required": false, - "name": "network", + "name": "token", "in": "query" }, { "schema": { - "type": "string" + "type": "string", + "enum": [ + "processing", + "completed", + "on_hold", + "refunded" + ] }, "required": false, - "name": "token", + "name": "status", "in": "query" } ], "responses": { "200": { - "description": "List payouts with pagination and filtering", + "description": "List wallet deposits", "content": { "application/json": { "schema": { - "anyOf": [ - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PayoutOut" - } - }, - "pagination": { - "$ref": "#/components/schemas/PaginationMetadata" - } - }, - "required": [ - "data", - "pagination" - ] - }, - { - "type": "array", - "items": { - "$ref": "#/components/schemas/PayoutOut" - } - } - ] + "$ref": "#/components/schemas/WalletDepositsOut" } } } }, "400": { - "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `VALIDATION_FAILED`, `VALIDATION_INVALID_REQUEST`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { @@ -41314,6 +61919,17 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "VALIDATION_INVALID_REQUEST": { + "summary": "VALIDATION_INVALID_REQUEST", + "value": { + "success": false, + "code": "VALIDATION_INVALID_REQUEST", + "message": "invalid_body", + "description": "The request is not valid for this operation. Check the parameters and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } @@ -41365,6 +61981,29 @@ } } }, + "404": { + "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", + "value": { + "success": false, + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -41378,7 +62017,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -41414,13 +62053,14 @@ } } }, - "/v1/instances/{instance_id}/payouts/stellar/authorize": { + "/v1/instances/{instance_id}/customers/{customer_id}/wallets/{id}/yield/enable": { "post": { - "x-sdk": true, + "x-sdk": false, "tags": [ - "Payouts" + "Wallets" ], - "summary": "Authorize Token Stellar", + "summary": "Enable Wallet Yield", + "description": "Turns yield on for the wallet. Returns the wallet, not the yield object: read yield_status here and use Retrieve Wallet Yield for positions. Idle balance is swept into the vault within the hour.", "parameters": [ { "schema": { @@ -41433,6 +62073,29 @@ "name": "instance_id", "in": "path" }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" + }, + "required": true, + "name": "id", + "in": "path" + }, { "schema": { "type": "string", @@ -41445,60 +62108,43 @@ "in": "header" } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PayoutOnStellarAuthorizeIn" - } - } - } - }, "responses": { "200": { - "description": "Payout started with success", + "description": "Wallet with yield_status enabled. Calling again while enabled returns the same wallet.", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "transaction_hash": { - "type": "string" - } - }, - "required": [ - "transaction_hash" - ] + "$ref": "#/components/schemas/WalletOut" } } } }, "400": { - "description": "Possible error codes: `QUOTES_INVALID_STATE`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `VALIDATION_FAILED`, `YIELD_NOT_AVAILABLE_FOR_NETWORK`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "QUOTES_INVALID_STATE": { - "summary": "QUOTES_INVALID_STATE", + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", "value": { "success": false, - "code": "QUOTES_INVALID_STATE", - "message": "quote_invalid_state", - "description": "This quote cannot be authorized in its current state. Request a new quote and try again.", + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "YIELD_NOT_AVAILABLE_FOR_NETWORK": { + "summary": "YIELD_NOT_AVAILABLE_FOR_NETWORK", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "YIELD_NOT_AVAILABLE_FOR_NETWORK", + "message": "yield_not_available_for_network", + "description": "Yield is not available on this wallet network.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -41531,7 +62177,7 @@ } }, "403": { - "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `AUTH_FORBIDDEN`, `YIELD_NOT_ENABLED_FOR_INSTANCE`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { @@ -41548,6 +62194,63 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "YIELD_NOT_ENABLED_FOR_INSTANCE": { + "summary": "YIELD_NOT_ENABLED_FOR_INSTANCE", + "value": { + "success": false, + "code": "YIELD_NOT_ENABLED_FOR_INSTANCE", + "message": "yield_not_enabled_for_instance", + "description": "Yield is not enabled for this account. Contact support to enable it.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "404": { + "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", + "value": { + "success": false, + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "409": { + "description": "Possible error codes: `YIELD_INVALID_STATE`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "YIELD_INVALID_STATE": { + "summary": "YIELD_INVALID_STATE", + "value": { + "success": false, + "code": "YIELD_INVALID_STATE", + "message": "yield_status_transition_in_progress", + "description": "The wallet yield status is changing. Check the current yield_status and retry when it settles.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } @@ -41566,7 +62269,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -41602,13 +62305,14 @@ } } }, - "/v1/instances/{instance_id}/payouts/stellar": { + "/v1/instances/{instance_id}/customers/{customer_id}/wallets/{id}/yield/disable": { "post": { - "x-sdk": true, + "x-sdk": false, "tags": [ - "Payouts" + "Wallets" ], - "summary": "Create Payout on Stellar", + "summary": "Disable Wallet Yield", + "description": "Turns yield off for the wallet. Returns the wallet, not the yield object. The wallet moves to disabling, the vault position is redeemed back to the wallet and any accrued fee is collected, then yield_status settles to disabled and a wallet.update webhook fires.", "parameters": [ { "schema": { @@ -41621,6 +62325,29 @@ "name": "instance_id", "in": "path" }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" + }, + "required": true, + "name": "id", + "in": "path" + }, { "schema": { "type": "string", @@ -41633,145 +62360,35 @@ "in": "header" } ], - "requestBody": { - "description": "Start payout on stellar blockchain", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PayoutOnStellarIn" - } - } - } - }, "responses": { "200": { - "description": "Payout started with success", + "description": "Wallet with yield_status disabled. Calling again while disabled returns the same wallet.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PayoutOnEvmOut" + "$ref": "#/components/schemas/WalletOut" + } + } + } + }, + "202": { + "description": "Wallet with yield_status disabling. Poll Retrieve Wallet or wait for the wallet.update webhook to see it settle to disabled.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WalletOut" } } } }, "400": { - "description": "Possible error codes: `BANK_ACCOUNTS_INCOMPLETE`, `BLOCKCHAIN_TX_FAILED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_ONBOARDING_INCOMPLETE`, `FILES_UNREADABLE`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `QUOTES_ALREADY_USED`, `QUOTES_EXPIRED`, `VALIDATION_FAILED`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_NOT_FOUND`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "BANK_ACCOUNTS_INCOMPLETE": { - "summary": "BANK_ACCOUNTS_INCOMPLETE", - "value": { - "success": false, - "code": "BANK_ACCOUNTS_INCOMPLETE", - "message": "sepa_bank_account_incomplete", - "description": "The bank account details are incomplete for this payment method. Provide the missing fields.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "BLOCKCHAIN_TX_FAILED": { - "summary": "BLOCKCHAIN_TX_FAILED", - "value": { - "success": false, - "code": "BLOCKCHAIN_TX_FAILED", - "message": "transaction_failed", - "description": "The blockchain transaction failed. Try again, and contact support if the problem persists.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { - "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", - "value": { - "success": false, - "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", - "message": "country_not_supported", - "description": "This country is not supported for this operation.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_INVALID_PHONE": { - "summary": "CUSTOMERS_INVALID_PHONE", - "value": { - "success": false, - "code": "CUSTOMERS_INVALID_PHONE", - "message": "invalid_phone_number", - "description": "The phone number provided is not valid. Check the number and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_INVALID_TAX_ID": { - "summary": "CUSTOMERS_INVALID_TAX_ID", - "value": { - "success": false, - "code": "CUSTOMERS_INVALID_TAX_ID", - "message": "invalid_cpf_or_rg_tax_id", - "description": "The tax ID provided is not valid. Check the value and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_ONBOARDING_INCOMPLETE": { - "summary": "CUSTOMERS_ONBOARDING_INCOMPLETE", - "value": { - "success": false, - "code": "CUSTOMERS_ONBOARDING_INCOMPLETE", - "message": "onboarding_incomplete", - "description": "Onboarding is not complete yet. Finish the remaining steps before continuing.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", - "value": { - "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "PAYOUTS_AMOUNT_BELOW_MINIMUM": { - "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", - "value": { - "success": false, - "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", - "message": "swift_minimum_is_100_usd", - "description": "The amount is below the minimum for this payment rail.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "QUOTES_ALREADY_USED": { - "summary": "QUOTES_ALREADY_USED", - "value": { - "success": false, - "code": "QUOTES_ALREADY_USED", - "message": "quote_already_used", - "description": "This quote was already used. Request a new quote.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "QUOTES_EXPIRED": { - "summary": "QUOTES_EXPIRED", - "value": { - "success": false, - "code": "QUOTES_EXPIRED", - "message": "quote_expired", - "description": "This quote has expired. Request a new quote and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -41782,39 +62399,6 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - }, - "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { - "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", - "message": "id_doc_front_file_required", - "description": "Additional documents are required to create this virtual account. Upload the requested documents.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "VIRTUAL_ACCOUNTS_NOT_FOUND": { - "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", - "message": "virtual_account_not_found", - "description": "The requested virtual account was not found.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { - "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "message": "virtual_account_provision_failed", - "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } } } } @@ -41866,21 +62450,21 @@ } } }, - "422": { - "description": "Possible error codes: `CUSTOMERS_INVALID_DATA`. See the Error responses section for retry semantics.", + "404": { + "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "CUSTOMERS_INVALID_DATA": { - "summary": "CUSTOMERS_INVALID_DATA", + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", "value": { "success": false, - "code": "CUSTOMERS_INVALID_DATA", - "message": "invalid_customer_data", - "description": "The customer data was rejected by the banking provider. Check the highlighted fields and try again.", + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -41902,7 +62486,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -41913,24 +62497,13 @@ } }, "500": { - "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", - "value": { - "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -41941,40 +62514,6 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - }, - "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { - "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "message": "virtual_account_provision_failed", - "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, - "502": { - "description": "Possible error codes: `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { - "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "message": "virtual_account_provision_failed", - "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } } } } @@ -41983,13 +62522,13 @@ } } }, - "/v1/instances/{instance_id}/payouts/solana": { - "post": { - "x-sdk": true, + "/v1/instances/{instance_id}/customers/{customer_id}/wallets/{id}/yield/history": { + "get": { + "x-sdk": false, "tags": [ - "Payouts" + "Wallets" ], - "summary": "Create Payout on Solana", + "summary": "Retrieve Wallet Yield History", "parameters": [ { "schema": { @@ -42005,143 +62544,81 @@ { "schema": { "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" + }, + "required": true, + "name": "id", + "in": "path" + }, + { + "schema": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB" + ] + }, + "required": false, + "name": "token", + "in": "query" + }, + { + "schema": { + "type": "string", + "format": "date", + "description": "First day, UTC, inclusive. Defaults to 30 days before `to`. The window is capped at 366 days.", + "example": "2026-09-01" + }, + "required": false, + "name": "from", + "in": "query" + }, + { + "schema": { + "type": "string", + "format": "date", + "description": "Last day, UTC, inclusive. Defaults to today.", + "example": "2026-09-30" }, "required": false, - "name": "Idempotency-Key", - "in": "header" + "name": "to", + "in": "query" } ], - "requestBody": { - "description": "Start payout on solana blockchain", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PayoutOnSolanaIn" - } - } - } - }, "responses": { "200": { - "description": "Payout started with success", + "description": "Get wallet yield history", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PayoutOnEvmOut" + "$ref": "#/components/schemas/YieldHistoryOut" } } } }, "400": { - "description": "Possible error codes: `BANK_ACCOUNTS_INCOMPLETE`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_ONBOARDING_INCOMPLETE`, `FILES_UNREADABLE`, `QUOTES_ALREADY_USED`, `QUOTES_EXPIRED`, `VALIDATION_FAILED`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `VALIDATION_FAILED`, `VALIDATION_INVALID_REQUEST`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "BANK_ACCOUNTS_INCOMPLETE": { - "summary": "BANK_ACCOUNTS_INCOMPLETE", - "value": { - "success": false, - "code": "BANK_ACCOUNTS_INCOMPLETE", - "message": "sepa_bank_account_incomplete", - "description": "The bank account details are incomplete for this payment method. Provide the missing fields.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { - "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", - "value": { - "success": false, - "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", - "message": "network_not_supported_on_dev_instance", - "description": "This network or token combination is not supported for this operation.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { - "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", - "value": { - "success": false, - "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", - "message": "country_not_supported", - "description": "This country is not supported for this operation.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_INVALID_PHONE": { - "summary": "CUSTOMERS_INVALID_PHONE", - "value": { - "success": false, - "code": "CUSTOMERS_INVALID_PHONE", - "message": "invalid_phone_number", - "description": "The phone number provided is not valid. Check the number and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_INVALID_TAX_ID": { - "summary": "CUSTOMERS_INVALID_TAX_ID", - "value": { - "success": false, - "code": "CUSTOMERS_INVALID_TAX_ID", - "message": "invalid_cpf_or_rg_tax_id", - "description": "The tax ID provided is not valid. Check the value and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_ONBOARDING_INCOMPLETE": { - "summary": "CUSTOMERS_ONBOARDING_INCOMPLETE", - "value": { - "success": false, - "code": "CUSTOMERS_ONBOARDING_INCOMPLETE", - "message": "onboarding_incomplete", - "description": "Onboarding is not complete yet. Finish the remaining steps before continuing.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", - "value": { - "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "QUOTES_ALREADY_USED": { - "summary": "QUOTES_ALREADY_USED", - "value": { - "success": false, - "code": "QUOTES_ALREADY_USED", - "message": "quote_already_used", - "description": "This quote was already used. Request a new quote.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "QUOTES_EXPIRED": { - "summary": "QUOTES_EXPIRED", - "value": { - "success": false, - "code": "QUOTES_EXPIRED", - "message": "quote_expired", - "description": "This quote has expired. Request a new quote and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -42153,24 +62630,13 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { - "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", - "message": "id_doc_front_file_required", - "description": "Additional documents are required to create this virtual account. Upload the requested documents.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { - "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "VALIDATION_INVALID_REQUEST": { + "summary": "VALIDATION_INVALID_REQUEST", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "message": "virtual_account_provision_failed", - "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "code": "VALIDATION_INVALID_REQUEST", + "message": "invalid_body", + "description": "The request is not valid for this operation. Check the parameters and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -42225,21 +62691,21 @@ } } }, - "422": { - "description": "Possible error codes: `CUSTOMERS_INVALID_DATA`. See the Error responses section for retry semantics.", + "404": { + "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "CUSTOMERS_INVALID_DATA": { - "summary": "CUSTOMERS_INVALID_DATA", + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", "value": { "success": false, - "code": "CUSTOMERS_INVALID_DATA", - "message": "invalid_customer_data", - "description": "The customer data was rejected by the banking provider. Check the highlighted fields and try again.", + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -42261,7 +62727,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -42272,24 +62738,13 @@ } }, "500": { - "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", - "value": { - "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -42300,40 +62755,6 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - }, - "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { - "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "message": "virtual_account_provision_failed", - "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, - "502": { - "description": "Possible error codes: `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { - "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "message": "virtual_account_provision_failed", - "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } } } } @@ -42342,13 +62763,13 @@ } } }, - "/v1/instances/{instance_id}/payouts/evm": { - "post": { - "x-sdk": true, + "/v1/instances/{instance_id}/customers/{customer_id}/wallets/{id}/yield/transactions": { + "get": { + "x-sdk": false, "tags": [ - "Payouts" + "Wallets" ], - "summary": "Create Payout on EVM Chains", + "summary": "Retrieve Wallet Yield Transactions", "parameters": [ { "schema": { @@ -42364,154 +62785,116 @@ { "schema": { "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + "minLength": 15, + "maxLength": 15, + "description": "Customer ID", + "example": "re_000000000000" + }, + "required": true, + "name": "customer_id", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" + }, + "required": true, + "name": "id", + "in": "path" + }, + { + "schema": { + "type": "string", + "enum": [ + "10", + "50", + "100", + "200", + "500", + "1000" + ], + "description": "Number of items to return", + "example": "50" }, "required": false, - "name": "Idempotency-Key", - "in": "header" + "name": "limit", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "0", + "10", + "50", + "100", + "200", + "500", + "1000" + ], + "description": "Number of items to skip", + "example": "0" + }, + "required": false, + "name": "offset", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "A cursor for use in pagination. starting_after is an object ID that defines your place in the list.", + "example": "pi_123" + }, + "required": false, + "name": "starting_after", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "A cursor for use in pagination. ending_before is an object ID that defines your place in the list.", + "example": "pi_123" + }, + "required": false, + "name": "ending_before", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB" + ] + }, + "required": false, + "name": "token", + "in": "query" } ], - "requestBody": { - "description": "Start payout on evm blockchain", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PayoutOnEvmIn" - } - } - } - }, "responses": { "200": { - "description": "Payout started with success", + "description": "List wallet yield transactions", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PayoutOnEvmOut" + "$ref": "#/components/schemas/YieldTransactionsOut" } } } }, "400": { - "description": "Possible error codes: `BANK_ACCOUNTS_INCOMPLETE`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_ONBOARDING_INCOMPLETE`, `FILES_UNREADABLE`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `QUOTES_ALREADY_USED`, `QUOTES_EXPIRED`, `VALIDATION_FAILED`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_NOT_FOUND`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `VALIDATION_FAILED`, `VALIDATION_INVALID_REQUEST`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "BANK_ACCOUNTS_INCOMPLETE": { - "summary": "BANK_ACCOUNTS_INCOMPLETE", - "value": { - "success": false, - "code": "BANK_ACCOUNTS_INCOMPLETE", - "message": "sepa_bank_account_incomplete", - "description": "The bank account details are incomplete for this payment method. Provide the missing fields.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { - "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", - "value": { - "success": false, - "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", - "message": "network_not_supported_on_dev_instance", - "description": "This network or token combination is not supported for this operation.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { - "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", - "value": { - "success": false, - "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", - "message": "country_not_supported", - "description": "This country is not supported for this operation.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_INVALID_PHONE": { - "summary": "CUSTOMERS_INVALID_PHONE", - "value": { - "success": false, - "code": "CUSTOMERS_INVALID_PHONE", - "message": "invalid_phone_number", - "description": "The phone number provided is not valid. Check the number and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_INVALID_TAX_ID": { - "summary": "CUSTOMERS_INVALID_TAX_ID", - "value": { - "success": false, - "code": "CUSTOMERS_INVALID_TAX_ID", - "message": "invalid_cpf_or_rg_tax_id", - "description": "The tax ID provided is not valid. Check the value and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_ONBOARDING_INCOMPLETE": { - "summary": "CUSTOMERS_ONBOARDING_INCOMPLETE", - "value": { - "success": false, - "code": "CUSTOMERS_ONBOARDING_INCOMPLETE", - "message": "onboarding_incomplete", - "description": "Onboarding is not complete yet. Finish the remaining steps before continuing.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", - "value": { - "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "PAYOUTS_AMOUNT_BELOW_MINIMUM": { - "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", - "value": { - "success": false, - "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", - "message": "swift_minimum_is_100_usd", - "description": "The amount is below the minimum for this payment rail.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "QUOTES_ALREADY_USED": { - "summary": "QUOTES_ALREADY_USED", - "value": { - "success": false, - "code": "QUOTES_ALREADY_USED", - "message": "quote_already_used", - "description": "This quote was already used. Request a new quote.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "QUOTES_EXPIRED": { - "summary": "QUOTES_EXPIRED", - "value": { - "success": false, - "code": "QUOTES_EXPIRED", - "message": "quote_expired", - "description": "This quote has expired. Request a new quote and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -42523,35 +62906,13 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { - "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", - "message": "id_doc_front_file_required", - "description": "Additional documents are required to create this virtual account. Upload the requested documents.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "VIRTUAL_ACCOUNTS_NOT_FOUND": { - "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", - "message": "virtual_account_not_found", - "description": "The requested virtual account was not found.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { - "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "VALIDATION_INVALID_REQUEST": { + "summary": "VALIDATION_INVALID_REQUEST", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "message": "virtual_account_provision_failed", - "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "code": "VALIDATION_INVALID_REQUEST", + "message": "invalid_body", + "description": "The request is not valid for this operation. Check the parameters and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -42606,21 +62967,21 @@ } } }, - "422": { - "description": "Possible error codes: `CUSTOMERS_INVALID_DATA`. See the Error responses section for retry semantics.", + "404": { + "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "CUSTOMERS_INVALID_DATA": { - "summary": "CUSTOMERS_INVALID_DATA", + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", "value": { "success": false, - "code": "CUSTOMERS_INVALID_DATA", - "message": "invalid_customer_data", - "description": "The customer data was rejected by the banking provider. Check the highlighted fields and try again.", + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -42631,64 +62992,19 @@ }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", - "value": { - "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, - "500": { - "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", - "value": { - "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", - "value": { - "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { - "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "message": "virtual_account_provision_failed", - "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -42697,21 +63013,21 @@ } } }, - "502": { - "description": "Possible error codes: `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { - "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "message": "virtual_account_provision_failed", - "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -42723,14 +63039,13 @@ } } }, - "/v1/instances/{instance_id}/payouts/{id}/documents": { - "post": { - "x-sdk": true, + "/v1/instances/{instance_id}/customers/{customer_id}/wallets/{id}/yield": { + "get": { + "x-sdk": false, "tags": [ - "Payouts" + "Wallets" ], - "summary": "Submit Payout Documents", - "description": "Submit compliance documents for SWIFT payouts requiring review. Includes optional payment description.", + "summary": "Retrieve Wallet Yield", "parameters": [ { "schema": { @@ -42748,75 +63063,44 @@ "type": "string", "minLength": 15, "maxLength": 15, - "example": "pa_000000000000" + "description": "Customer ID", + "example": "re_000000000000" }, "required": true, - "name": "id", + "name": "customer_id", "in": "path" }, { "schema": { "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + "minLength": 15, + "maxLength": 15, + "example": "bk_000000000000" }, - "required": false, - "name": "Idempotency-Key", - "in": "header" + "required": true, + "name": "id", + "in": "path" } ], - "requestBody": { - "description": "Document details and optional payment description", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SubmitPayoutDocumentsIn" - } - } - } - }, "responses": { "200": { - "description": "Documents submitted successfully", + "description": "Get wallet yield", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Success" + "$ref": "#/components/schemas/YieldOut" } } } }, "400": { - "description": "Possible error codes: `FILES_UNREADABLE`, `PAYOUTS_DOCUMENTS_NOT_ACCEPTED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", - "value": { - "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "PAYOUTS_DOCUMENTS_NOT_ACCEPTED": { - "summary": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", - "value": { - "success": false, - "code": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", - "message": "document_upload_only_for_swift_payouts", - "description": "Document upload is only available for international wire payouts.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -42879,20 +63163,20 @@ } }, "404": { - "description": "Possible error codes: `PAYOUTS_NOT_FOUND`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "PAYOUTS_NOT_FOUND": { - "summary": "PAYOUTS_NOT_FOUND", + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", "value": { "success": false, - "code": "PAYOUTS_NOT_FOUND", - "message": "payout_not_found", - "description": "The requested payout was not found.", + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -42914,7 +63198,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -42925,24 +63209,13 @@ } }, "500": { - "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", - "value": { - "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -42961,13 +63234,13 @@ } } }, - "/v1/instances/{instance_id}/payin-quotes": { + "/v1/instances/{instance_id}/transfer-quotes": { "post": { "x-sdk": true, "tags": [ - "Payin Quotes" + "Transfer Quotes" ], - "summary": "Create Payin Quote", + "summary": "Create Transfer Quote", "parameters": [ { "schema": { @@ -42997,158 +63270,675 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreatePayinQuoteIn" + "$ref": "#/components/schemas/CreateTransferQuoteIn" } } } }, "responses": { "200": { - "description": "Payin Quote creation details", + "description": "Transfer Quote creation details", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreatePayinQuoteOut" + "$ref": "#/components/schemas/CreateTransferQuoteOut" } } } }, "400": { - "description": "Possible error codes: `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_KYC_NOT_APPROVED`, `CUSTOMERS_NOT_FOUND`, `FEES_PARTNER_FEE_EXCEEDED`, `LIMITS_AMOUNT_OUT_OF_RANGE`, `LIMITS_VOLUME_EXCEEDED`, `PAYINS_METHOD_NOT_SUPPORTED`, `PAYINS_TAX_ID_REQUIRED`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `QUOTES_OTC_NOT_SUPPORTED`, `TOS_NOT_ACCEPTED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BANK_ACCOUNTS_INCOMPLETE`, `BANK_ACCOUNTS_INVALID_BANK_CODE`, `BANK_ACCOUNTS_INVALID_ROUTING`, `BANK_ACCOUNTS_NOT_APPROVED`, `BANK_ACCOUNTS_NOT_FOUND`, `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED`, `BANK_ACCOUNTS_PLAID_CONNECTION_INVALID`, `BANK_ACCOUNTS_PLAID_NOT_FIRST_PARTY`, `BANK_ACCOUNTS_RTP_NOT_SUPPORTED`, `BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `BLOCKCHAIN_TX_FAILED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_ENHANCED_KYC_REQUIRED`, `CUSTOMERS_ID_DOCUMENT_INVALID`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_KYC_NOT_APPROVED`, `CUSTOMERS_KYC_TYPE_NOT_AVAILABLE`, `CUSTOMERS_NAME_INVALID`, `CUSTOMERS_ONBOARDING_INCOMPLETE`, `CUSTOMERS_OWNERSHIP_INVALID`, `FEES_PARTNER_FEE_EXCEEDED`, `FILES_TOO_LARGE`, `FILES_UNREADABLE`, `LIMITS_AMOUNT_OUT_OF_RANGE`, `PAYABLES_ALREADY_PAID_OR_EXPIRED`, `PAYABLES_ALREADY_PAID_OR_IN_FLIGHT`, `PAYABLES_AMOUNT_NEGATIVE`, `PAYABLES_BANK_ACCOUNT_INVALID`, `PAYABLES_CODE_UNRESOLVABLE`, `PAYABLES_CURRENCY_MUST_BE_BRL`, `PAYABLES_DESTINATION_NOT_SUPPORTED`, `PAYABLES_DOCUMENT_INVALID`, `PAYABLES_DUPLICATE`, `PAYABLES_NETWORK_NOT_SUPPORTED`, `PAYABLES_NOT_CANCELABLE`, `PAYABLES_PIX_AMOUNT_REQUIRED`, `PAYINS_FUNDING_ACCOUNT_INVALID`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `PAYOUTS_DOCUMENTS_NOT_ACCEPTED`, `PAYOUTS_INSUFFICIENT_BALANCE`, `QUOTES_ALREADY_USED`, `QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM`, `QUOTES_EXPIRED`, `QUOTES_INVALID_STATE`, `QUOTES_RATE_UNAVAILABLE`, `VALIDATION_FAILED`, `VALIDATION_INVALID_REQUEST`, `VALIDATION_MISSING_REQUIRED_FIELDS`, `VIRTUAL_ACCOUNTS_DISABLED`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_NOT_FOUND`, `VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`, `VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED`, `WALLETS_DEPOSIT_UNDER_REVIEW`, `WALLETS_DESTINATION_SANCTIONED`, `WALLETS_NOT_OWNED_BY_CUSTOMER`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "BANK_ACCOUNTS_INCOMPLETE": { + "summary": "BANK_ACCOUNTS_INCOMPLETE", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INCOMPLETE", + "message": "infinitus_missing_intermediary", + "description": "The banking provider cannot route payments to this bank automatically. Provide the US correspondent bank routing number (ABA, 9 digits) from the beneficiary bank USD wire instructions in swift_intermediary_bank_routing_number.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_INVALID_BANK_CODE": { + "summary": "BANK_ACCOUNTS_INVALID_BANK_CODE", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INVALID_BANK_CODE", + "message": "bank_accounts_invalid_bank_code", + "description": "The bank code provided is not valid for this payment rail. The message lists where to fetch the valid codes.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_INVALID_ROUTING": { + "summary": "BANK_ACCOUNTS_INVALID_ROUTING", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INVALID_ROUTING", + "message": "The routing number must be a valid 9-digit ABA routing number.", + "description": "The routing number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_NOT_APPROVED": { + "summary": "BANK_ACCOUNTS_NOT_APPROVED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_APPROVED", + "message": "bank_account_not_approved", + "description": "This bank account is not approved yet.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_NOT_FOUND": { + "summary": "BANK_ACCOUNTS_NOT_FOUND", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_FOUND", + "message": "bank_account_not_found", + "description": "The requested bank account was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "message": "unsupported_banking_partner", + "description": "This banking option is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_PLAID_CONNECTION_INVALID": { + "summary": "BANK_ACCOUNTS_PLAID_CONNECTION_INVALID", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PLAID_CONNECTION_INVALID", + "message": "plaid_account_not_found", + "description": "The bank connection could not be completed. Connect the account again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_PLAID_NOT_FIRST_PARTY": { + "summary": "BANK_ACCOUNTS_PLAID_NOT_FIRST_PARTY", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PLAID_NOT_FIRST_PARTY", + "message": "plaid_account_not_first_party", + "description": "The connected bank account does not belong to this customer. Only accounts held in the customer's own name can be connected.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_RTP_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", + "message": "The provided routing number does not support RTP transactions.", + "description": "The provided routing number does not support instant payments.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR": { + "summary": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "message": "sepa_iban_not_eur", + "description": "SEPA payouts are only available to EUR accounts. This IBAN is from a country that holds another currency, so the payment would fail at settlement. Use an IBAN from a EUR account instead.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", "value": { "success": false, - "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", - "message": "network_not_supported_on_dev_instance", - "description": "This network or token combination is not supported for this operation.", + "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "message": "network_not_supported_on_dev_instance", + "description": "This network or token combination is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_TX_FAILED": { + "summary": "BLOCKCHAIN_TX_FAILED", + "value": { + "success": false, + "code": "BLOCKCHAIN_TX_FAILED", + "message": "transaction_failed", + "description": "The blockchain transaction failed. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { + "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "value": { + "success": false, + "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "message": "country_not_supported", + "description": "This country is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ENHANCED_KYC_REQUIRED": { + "summary": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "value": { + "success": false, + "code": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "message": "only_enhanced_kyc_allowed_for_high_risk_countries", + "description": "Individuals from high-risk countries must use enhanced verification (kyc_type: enhanced); standard verification is not available for them. See https://www.blindpay.com/docs/kb/supported-countries for country tiers.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ID_DOCUMENT_INVALID": { + "summary": "CUSTOMERS_ID_DOCUMENT_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_ID_DOCUMENT_INVALID", + "message": "id_doc_is_not_valid_passport_or_national_id", + "description": "The identity document is not accepted for this customer. Use a national ID, a passport with a valid passport number as the tax ID, or a driver license with a valid SSN or ITIN as the tax ID.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_PHONE": { + "summary": "CUSTOMERS_INVALID_PHONE", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_PHONE", + "message": "invalid_phone_number", + "description": "The phone number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_TAX_ID": { + "summary": "CUSTOMERS_INVALID_TAX_ID", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_TAX_ID", + "message": "invalid_cpf_or_rg_tax_id", + "description": "The tax ID provided is not valid. Check the value and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_NOT_APPROVED": { + "summary": "CUSTOMERS_KYC_NOT_APPROVED", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_NOT_APPROVED", + "message": "kyc_not_approved", + "description": "This customer has not completed verification yet. Complete the verification before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE": { + "summary": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "message": "kyc_type_not_supported", + "description": "The requested verification type is not available for this customer. Use a supported verification type and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_NAME_INVALID": { + "summary": "CUSTOMERS_NAME_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_NAME_INVALID", + "message": "legal_name_required", + "description": "The name registered for this customer is not accepted. Review it and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ONBOARDING_INCOMPLETE": { + "summary": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "value": { + "success": false, + "code": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "message": "onboarding_incomplete", + "description": "Onboarding is not complete yet. Finish the remaining steps before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_OWNERSHIP_INVALID": { + "summary": "CUSTOMERS_OWNERSHIP_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_OWNERSHIP_INVALID", + "message": "business_owner_required", + "description": "The ownership information for this business customer is incomplete or inconsistent. Review the registered owners and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_PARTNER_FEE_EXCEEDED": { + "summary": "FEES_PARTNER_FEE_EXCEEDED", + "value": { + "success": false, + "code": "FEES_PARTNER_FEE_EXCEEDED", + "message": "partner_fee_exceeded", + "description": "The partner fee exceeds the allowed maximum for this transaction.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "LIMITS_AMOUNT_OUT_OF_RANGE": { + "summary": "LIMITS_AMOUNT_OUT_OF_RANGE", + "value": { + "success": false, + "code": "LIMITS_AMOUNT_OUT_OF_RANGE", + "message": "limits_amount_out_of_range", + "description": "The amount is outside the allowed range. The message includes the allowed range.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_ALREADY_PAID_OR_EXPIRED": { + "summary": "PAYABLES_ALREADY_PAID_OR_EXPIRED", + "value": { + "success": false, + "code": "PAYABLES_ALREADY_PAID_OR_EXPIRED", + "message": "payable_already_paid_or_expired", + "description": "This payment code was already paid or has expired and can no longer be paid.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT": { + "summary": "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT", + "value": { + "success": false, + "code": "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT", + "message": "payable_already_paid_or_in_flight", + "description": "This payable is already being paid or was already paid. Only draft payables can be quoted; a failed or refunded attempt returns the payable to draft.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_AMOUNT_NEGATIVE": { + "summary": "PAYABLES_AMOUNT_NEGATIVE", + "value": { + "success": false, + "code": "PAYABLES_AMOUNT_NEGATIVE", + "message": "payable_amount_negative", + "description": "The payable total (line items plus taxes minus discount) cannot be negative.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_BANK_ACCOUNT_INVALID": { + "summary": "PAYABLES_BANK_ACCOUNT_INVALID", + "value": { + "success": false, + "code": "PAYABLES_BANK_ACCOUNT_INVALID", + "message": "payable_bank_account_invalid", + "description": "The bank_account details on this invoice payable were rejected. Check the errors list for the field that failed.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_CODE_UNRESOLVABLE": { + "summary": "PAYABLES_CODE_UNRESOLVABLE", + "value": { + "success": false, + "code": "PAYABLES_CODE_UNRESOLVABLE", + "message": "unresolvable_payable_code", + "description": "We could not read this payment code. Check the code and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_CURRENCY_MUST_BE_BRL": { + "summary": "PAYABLES_CURRENCY_MUST_BE_BRL", + "value": { + "success": false, + "code": "PAYABLES_CURRENCY_MUST_BE_BRL", + "message": "payable_currency_must_be_brl", + "description": "Boleto and PIX payables must use BRL.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DESTINATION_NOT_SUPPORTED": { + "summary": "PAYABLES_DESTINATION_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYABLES_DESTINATION_NOT_SUPPORTED", + "message": "payable_destination_not_supported", + "description": "Only boleto, arrecadação (utility/tax) and PIX QR code payables can be paid right now. Bank-destination invoice payables are not payable yet.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DOCUMENT_INVALID": { + "summary": "PAYABLES_DOCUMENT_INVALID", + "value": { + "success": false, + "code": "PAYABLES_DOCUMENT_INVALID", + "message": "payable_document_invalid", + "description": "document_file must be a URL returned by POST /upload with bucket `documents`, uploaded by this instance.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DUPLICATE": { + "summary": "PAYABLES_DUPLICATE", + "value": { + "success": false, + "code": "PAYABLES_DUPLICATE", + "message": "duplicate_payable", + "description": "This payment code already has a payable registered, in progress or completed for this instance.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_NETWORK_NOT_SUPPORTED": { + "summary": "PAYABLES_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYABLES_NETWORK_NOT_SUPPORTED", + "message": "payable_network_not_supported", + "description": "Only EVM wallets can fund payables right now.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_NOT_CANCELABLE": { + "summary": "PAYABLES_NOT_CANCELABLE", + "value": { + "success": false, + "code": "PAYABLES_NOT_CANCELABLE", + "message": "payable_not_cancelable", + "description": "Only draft payables can be deleted. Once a payout is executing this payable it can no longer be canceled.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_PIX_AMOUNT_REQUIRED": { + "summary": "PAYABLES_PIX_AMOUNT_REQUIRED", + "value": { + "success": false, + "code": "PAYABLES_PIX_AMOUNT_REQUIRED", + "message": "pix_code_amount_required", + "description": "This PIX code has no fixed amount and no amount was provided. Send the amount as line_items when registering a PIX code that lets the payer choose the value.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYINS_FUNDING_ACCOUNT_INVALID": { + "summary": "PAYINS_FUNDING_ACCOUNT_INVALID", + "value": { + "success": false, + "code": "PAYINS_FUNDING_ACCOUNT_INVALID", + "message": "funding_account_not_plaid_connected", + "description": "This bank account was entered manually and cannot be debited. Connect the account through Plaid to fund a payin from it.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_AMOUNT_BELOW_MINIMUM": { + "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "value": { + "success": false, + "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "message": "swift_minimum_is_100_usd", + "description": "The amount is below the minimum for this payment rail.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_DOCUMENTS_NOT_ACCEPTED": { + "summary": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", + "value": { + "success": false, + "code": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", + "message": "document_upload_only_for_swift_payouts", + "description": "A document cannot be submitted for this payout in its current state.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_INSUFFICIENT_BALANCE": { + "summary": "PAYOUTS_INSUFFICIENT_BALANCE", + "value": { + "success": false, + "code": "PAYOUTS_INSUFFICIENT_BALANCE", + "message": "not_enough_balance", + "description": "There is not enough balance to complete this payout. Fund your balance and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_ALREADY_USED": { + "summary": "QUOTES_ALREADY_USED", + "value": { + "success": false, + "code": "QUOTES_ALREADY_USED", + "message": "quote_already_used", + "description": "This quote was already used. Request a new quote.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM": { + "summary": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "value": { + "success": false, + "code": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "message": "otc_provider_minimum_not_met", + "description": "The amount is below the minimum the liquidity provider accepts for this pair. Try a larger amount.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_EXPIRED": { + "summary": "QUOTES_EXPIRED", + "value": { + "success": false, + "code": "QUOTES_EXPIRED", + "message": "quote_expired", + "description": "This quote has expired. Request a new quote and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_INVALID_STATE": { + "summary": "QUOTES_INVALID_STATE", + "value": { + "success": false, + "code": "QUOTES_INVALID_STATE", + "message": "quote_invalid_state", + "description": "This quote cannot be authorized in its current state. Request a new quote and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "CUSTOMERS_KYC_NOT_APPROVED": { - "summary": "CUSTOMERS_KYC_NOT_APPROVED", + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", "value": { "success": false, - "code": "CUSTOMERS_KYC_NOT_APPROVED", - "message": "kyc_not_approved", - "description": "This customer has not completed verification yet. Complete the verification before continuing.", + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "CUSTOMERS_NOT_FOUND": { - "summary": "CUSTOMERS_NOT_FOUND", + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", "value": { "success": false, - "code": "CUSTOMERS_NOT_FOUND", - "message": "customer_not_found", - "description": "The requested customer was not found.", + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "FEES_PARTNER_FEE_EXCEEDED": { - "summary": "FEES_PARTNER_FEE_EXCEEDED", + "VALIDATION_INVALID_REQUEST": { + "summary": "VALIDATION_INVALID_REQUEST", "value": { "success": false, - "code": "FEES_PARTNER_FEE_EXCEEDED", - "message": "partner_fee_exceeded", - "description": "The partner fee exceeds the allowed maximum for this transaction.", + "code": "VALIDATION_INVALID_REQUEST", + "message": "invalid_body", + "description": "The request is not valid for this operation. Check the parameters and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "LIMITS_AMOUNT_OUT_OF_RANGE": { - "summary": "LIMITS_AMOUNT_OUT_OF_RANGE", + "VALIDATION_MISSING_REQUIRED_FIELDS": { + "summary": "VALIDATION_MISSING_REQUIRED_FIELDS", "value": { "success": false, - "code": "LIMITS_AMOUNT_OUT_OF_RANGE", - "message": "limits_amount_out_of_range", - "description": "The amount is outside the allowed range. The message includes the allowed range.", + "code": "VALIDATION_MISSING_REQUIRED_FIELDS", + "message": "missing_required_fields", + "description": "Required fields are missing. Provide the missing fields and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "LIMITS_VOLUME_EXCEEDED": { - "summary": "LIMITS_VOLUME_EXCEEDED", + "VIRTUAL_ACCOUNTS_DISABLED": { + "summary": "VIRTUAL_ACCOUNTS_DISABLED", "value": { "success": false, - "code": "LIMITS_VOLUME_EXCEEDED", - "message": "limits_volume_exceeded", - "description": "You exceeded your transaction volume limit. The message includes the remaining amount available.", + "code": "VIRTUAL_ACCOUNTS_DISABLED", + "message": "virtual_accounts_not_enabled", + "description": "Virtual accounts are not enabled for this account. Contact support to enable them.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "PAYINS_METHOD_NOT_SUPPORTED": { - "summary": "PAYINS_METHOD_NOT_SUPPORTED", + "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { + "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", "value": { "success": false, - "code": "PAYINS_METHOD_NOT_SUPPORTED", - "message": "ted_payin_not_supported", - "description": "This payment method is not supported for this operation.", + "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "message": "id_doc_front_file_required", + "description": "An identity document is required for this customer. Upload the front of a valid document and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "PAYINS_TAX_ID_REQUIRED": { - "summary": "PAYINS_TAX_ID_REQUIRED", + "VIRTUAL_ACCOUNTS_NOT_FOUND": { + "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", "value": { "success": false, - "code": "PAYINS_TAX_ID_REQUIRED", - "message": "tax_id_required", - "description": "A tax ID is required for this payment method. Provide the tax ID and try again.", + "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "message": "virtual_account_not_found", + "description": "The requested virtual account was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "PAYOUTS_AMOUNT_BELOW_MINIMUM": { - "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE": { + "summary": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", "value": { "success": false, - "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", - "message": "swift_minimum_is_100_usd", - "description": "The amount is below the minimum for this payment rail.", + "code": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "message": "banking_partner_not_eligible_for_customer", + "description": "This banking partner is not available for this customer. Choose a different banking partner.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "QUOTES_OTC_NOT_SUPPORTED": { - "summary": "QUOTES_OTC_NOT_SUPPORTED", + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", "value": { "success": false, - "code": "QUOTES_OTC_NOT_SUPPORTED", - "message": "otc_only_supported_for_brl", - "description": "This OTC configuration is not supported. OTC requires BRL with USDT, and either the sender amount with fees not covered, or the receiver amount with fees covered.", + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "TOS_NOT_ACCEPTED": { - "summary": "TOS_NOT_ACCEPTED", + "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED": { + "summary": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", "value": { "success": false, - "code": "TOS_NOT_ACCEPTED", - "message": "please_accept_terms_of_service", - "description": "The terms of service must be accepted before continuing.", + "code": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", + "message": "us_state_not_supported", + "description": "Virtual accounts are not available for this country or region.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "WALLETS_DEPOSIT_UNDER_REVIEW": { + "summary": "WALLETS_DEPOSIT_UNDER_REVIEW", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "WALLETS_DEPOSIT_UNDER_REVIEW", + "message": "wallet_deposit_under_review", + "description": "A deposit into this wallet is under compliance review. Transfers out of the wallet are paused until the review is resolved.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_DESTINATION_SANCTIONED": { + "summary": "WALLETS_DESTINATION_SANCTIONED", + "value": { + "success": false, + "code": "WALLETS_DESTINATION_SANCTIONED", + "message": "wallet_destination_sanctioned", + "description": "The destination wallet address is on a sanctions list. Funds cannot be sent to it.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_NOT_OWNED_BY_CUSTOMER": { + "summary": "WALLETS_NOT_OWNED_BY_CUSTOMER", + "value": { + "success": false, + "code": "WALLETS_NOT_OWNED_BY_CUSTOMER", + "message": "blockchain_wallet_does_not_belong_to_customer", + "description": "The selected wallet belongs to a different customer. Choose one of this customer's wallets.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -43204,351 +63994,97 @@ } }, "404": { - "description": "Possible error codes: `FEES_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `FEES_NOT_FOUND`, `INSTANCES_NOT_FOUND`, `PAYABLES_NOT_FOUND`, `PAYINS_NOT_FOUND`, `PAYOUTS_NOT_FOUND`, `QUOTES_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "FEES_NOT_FOUND": { - "summary": "FEES_NOT_FOUND", + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", "value": { "success": false, - "code": "FEES_NOT_FOUND", - "message": "partner_fee_not_found", - "description": "The requested fee configuration was not found.", + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "WALLETS_NOT_FOUND": { - "summary": "WALLETS_NOT_FOUND", - "value": { - "success": false, - "code": "WALLETS_NOT_FOUND", - "message": "wallet_not_found", - "description": "The requested wallet was not found.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", - "value": { - "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, - "500": { - "description": "Possible error codes: `INTERNAL_ERROR`, `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + "FEES_NOT_FOUND": { + "summary": "FEES_NOT_FOUND", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "FEES_NOT_FOUND", + "message": "partner_fee_not_found", + "description": "The requested fee configuration was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "QUOTES_RATE_UNAVAILABLE": { - "summary": "QUOTES_RATE_UNAVAILABLE", + "INSTANCES_NOT_FOUND": { + "summary": "INSTANCES_NOT_FOUND", "value": { "success": false, - "code": "QUOTES_RATE_UNAVAILABLE", - "message": "fx_rate_unavailable", - "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "code": "INSTANCES_NOT_FOUND", + "message": "instance_not_found", + "description": "The requested instance was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - } - } - } - }, - "/v1/instances/{instance_id}/payin-quotes/fx": { - "post": { - "x-sdk": true, - "tags": [ - "Payin Quotes" - ], - "summary": "Get FX Rate", - "parameters": [ - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "required": false, - "name": "Idempotency-Key", - "in": "header" - } - ], - "requestBody": { - "description": "Check FX rate", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "from": { - "type": "string", - "enum": [ - "USDC", - "USDT", - "USDB", - "BRL", - "USD", - "MXN", - "COP", - "ARS", - "EUR" - ], - "example": "BRL" - }, - "to": { - "type": "string", - "enum": [ - "USDC", - "USDT", - "USDB", - "BRL", - "USD", - "MXN", - "COP", - "ARS", - "EUR" - ], - "example": "USDC" - }, - "request_amount": { - "type": "integer", - "minimum": 500, - "description": "1000 represents 10.00, 2050 represents 20.50", - "example": 1000 - }, - "currency_type": { - "type": "string", - "enum": [ - "sender", - "receiver" - ], - "description": "", - "example": "sender" - } - }, - "required": [ - "from", - "to", - "request_amount", - "currency_type" - ] - } - } - } - }, - "responses": { - "200": { - "description": "Check FX rate response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "commercial_quotation": { - "type": [ - "number", - "null" - ], - "description": "1 USD = 4.95 BRL", - "example": 495 - }, - "blindpay_quotation": { - "type": [ - "number", - "null" - ], - "description": "1 USD = 5.05 BRL (commercial quotation + (blindpay taxes))", - "example": 505 - }, - "result_amount": { - "type": "number", - "minimum": 1 - }, - "instance_flat_fee": { - "type": [ - "number", - "null" - ], - "description": "0.5 USDC", - "example": 50 - }, - "instance_percentage_fee": { - "type": "number", - "minimum": 0, - "maximum": 10000 - } }, - "required": [ - "commercial_quotation", - "blindpay_quotation", - "result_amount", - "instance_flat_fee", - "instance_percentage_fee" - ] - } - } - } - }, - "400": { - "description": "Possible error codes: `BANK_ACCOUNTS_INCOMPLETE`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `QUOTES_RATE_UNAVAILABLE`, `VALIDATION_FAILED`, `VALIDATION_INVALID_REQUEST`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "BANK_ACCOUNTS_INCOMPLETE": { - "summary": "BANK_ACCOUNTS_INCOMPLETE", + "PAYABLES_NOT_FOUND": { + "summary": "PAYABLES_NOT_FOUND", "value": { "success": false, - "code": "BANK_ACCOUNTS_INCOMPLETE", - "message": "sepa_bank_account_incomplete", - "description": "The bank account details are incomplete for this payment method. Provide the missing fields.", + "code": "PAYABLES_NOT_FOUND", + "message": "payable_not_found", + "description": "This payable was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "PAYOUTS_AMOUNT_BELOW_MINIMUM": { - "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "PAYINS_NOT_FOUND": { + "summary": "PAYINS_NOT_FOUND", "value": { "success": false, - "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", - "message": "swift_minimum_is_100_usd", - "description": "The amount is below the minimum for this payment rail.", + "code": "PAYINS_NOT_FOUND", + "message": "payin_not_found", + "description": "The requested payin was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "QUOTES_RATE_UNAVAILABLE": { - "summary": "QUOTES_RATE_UNAVAILABLE", + "PAYOUTS_NOT_FOUND": { + "summary": "PAYOUTS_NOT_FOUND", "value": { "success": false, - "code": "QUOTES_RATE_UNAVAILABLE", - "message": "fx_rate_unavailable", - "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "code": "PAYOUTS_NOT_FOUND", + "message": "payout_not_found", + "description": "The requested payout was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "QUOTES_NOT_FOUND": { + "summary": "QUOTES_NOT_FOUND", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "QUOTES_NOT_FOUND", + "message": "quote_not_found", + "description": "The requested quote was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_INVALID_REQUEST": { - "summary": "VALIDATION_INVALID_REQUEST", - "value": { - "success": false, - "code": "VALIDATION_INVALID_REQUEST", - "message": "invalid_body", - "description": "The request is not valid for this operation. Check the parameters and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, - "401": { - "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_UNAUTHORIZED": { - "summary": "AUTH_UNAUTHORIZED", - "value": { - "success": false, - "code": "AUTH_UNAUTHORIZED", - "message": "unauthorized", - "description": "Authentication failed. Check your API key or session and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, - "403": { - "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_FORBIDDEN": { - "summary": "AUTH_FORBIDDEN", + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", "value": { "success": false, - "code": "AUTH_FORBIDDEN", - "message": "user_not_allowed", - "description": "You do not have permission to perform this action.", + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -43557,21 +64093,21 @@ } } }, - "404": { - "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", + "422": { + "description": "Possible error codes: `CUSTOMERS_INVALID_DATA`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "WALLETS_NOT_FOUND": { - "summary": "WALLETS_NOT_FOUND", + "CUSTOMERS_INVALID_DATA": { + "summary": "CUSTOMERS_INVALID_DATA", "value": { "success": false, - "code": "WALLETS_NOT_FOUND", - "message": "wallet_not_found", - "description": "The requested wallet was not found.", + "code": "CUSTOMERS_INVALID_DATA", + "message": "invalid_customer_data", + "description": "The customer data was rejected by the banking provider. Check the highlighted fields and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -43593,7 +64129,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -43604,13 +64140,24 @@ } }, "500": { - "description": "Possible error codes: `INTERNAL_ERROR`, `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `QUOTES_RATE_UNAVAILABLE`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -43632,6 +64179,40 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } + }, + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "502": { + "description": "Possible error codes: `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "value": { + "success": false, + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } } } } @@ -43663,13 +64244,13 @@ } } }, - "/v1/instances/{instance_id}/payins/{id}": { + "/v1/instances/{instance_id}/transfers/{id}": { "get": { "x-sdk": true, "tags": [ - "Payins" + "Transfers" ], - "summary": "Retrieve Payin", + "summary": "Retrieve Transfer", "parameters": [ { "schema": { @@ -43687,7 +64268,7 @@ "type": "string", "minLength": 15, "maxLength": 15, - "example": "pi_000000000000" + "example": "tr_000000000000" }, "required": true, "name": "id", @@ -43696,11 +64277,11 @@ ], "responses": { "200": { - "description": "List payins", + "description": "List transfers", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PayinOut" + "$ref": "#/components/schemas/TransferOut" } } } @@ -43774,29 +64355,6 @@ } } }, - "404": { - "description": "Possible error codes: `PAYINS_NOT_FOUND`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "PAYINS_NOT_FOUND": { - "summary": "PAYINS_NOT_FOUND", - "value": { - "success": false, - "code": "PAYINS_NOT_FOUND", - "message": "payin_not_found", - "description": "The requested payin was not found.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -43810,7 +64368,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -43846,20 +64404,21 @@ } } }, - "/v1/e/payins/{id}": { + "/v1/e/transfers/{id}": { "get": { "x-sdk": true, + "x-mcp": false, "tags": [ - "Payins" + "Transfers" ], - "summary": "Retrieve Payin Track", + "summary": "Retrieve Transfer Track", "parameters": [ { "schema": { "type": "string", "minLength": 15, "maxLength": 15, - "example": "pi_000000000000" + "example": "tr_000000000000" }, "required": true, "name": "id", @@ -43868,11 +64427,11 @@ ], "responses": { "200": { - "description": "List payins", + "description": "List transfers", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PayinOut" + "$ref": "#/components/schemas/TransferOut" } } } @@ -43946,29 +64505,6 @@ } } }, - "404": { - "description": "Possible error codes: `PAYINS_NOT_FOUND`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "PAYINS_NOT_FOUND": { - "summary": "PAYINS_NOT_FOUND", - "value": { - "success": false, - "code": "PAYINS_NOT_FOUND", - "message": "payin_not_found", - "description": "The requested payin was not found.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -43982,7 +64518,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -44018,13 +64554,13 @@ } } }, - "/v1/instances/{instance_id}/payins": { + "/v1/instances/{instance_id}/transfers": { "get": { "x-sdk": true, "tags": [ - "Payins" + "Transfers" ], - "summary": "Retrieve Payins", + "summary": "Retrieve Transfers", "parameters": [ { "schema": { @@ -44108,64 +64644,51 @@ { "schema": { "type": "string", - "enum": [ - "processing", - "on_hold", - "failed", - "refunded", - "completed" - ] - }, - "required": false, - "name": "status", - "in": "query" - }, - { - "schema": { - "type": "string" - }, - "required": false, - "name": "customer_name", - "in": "query" - }, - { - "schema": { - "type": "string" - }, - "required": false, - "name": "bank_account_id", - "in": "query" - }, - { - "schema": { - "type": "string" + "minLength": 15, + "maxLength": 15, + "example": "bl_000000000000" }, "required": false, - "name": "country", + "name": "wallet_id", "in": "query" }, { "schema": { "type": "string", "enum": [ - "ach", - "wire", - "pix", - "ted", - "spei", - "transfers", - "pse", - "international_swift", - "rtp" + "processing", + "failed", + "refunded", + "completed" ] }, "required": false, - "name": "payment_method", + "name": "status", "in": "query" }, { "schema": { - "type": "string" + "type": "string", + "enum": [ + "base", + "sepolia", + "arbitrum_sepolia", + "base_sepolia", + "arbitrum", + "polygon", + "polygon_amoy", + "ethereum", + "stellar", + "stellar_testnet", + "tron", + "solana", + "solana_devnet", + "tempo", + "tempo_testnet", + "arc", + "arc_testnet" + ], + "description": "Network of the sending wallet" }, "required": false, "name": "network", @@ -44173,7 +64696,15 @@ }, { "schema": { - "type": "string" + "type": "string", + "enum": [ + "USDC", + "USDT", + "USDB", + "EURC", + "EURB" + ], + "description": "Token sent from the wallet" }, "required": false, "name": "token", @@ -44182,35 +64713,25 @@ ], "responses": { "200": { - "description": "List payins with pagination", + "description": "List transfers", "content": { "application/json": { "schema": { - "anyOf": [ - { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PayinOut" - } - }, - "pagination": { - "$ref": "#/components/schemas/PaginationMetadata" - } - }, - "required": [ - "data", - "pagination" - ] - }, - { + "type": "object", + "properties": { + "data": { "type": "array", "items": { - "$ref": "#/components/schemas/PayinOut" + "$ref": "#/components/schemas/TransferOut" } + }, + "pagination": { + "$ref": "#/components/schemas/PaginationMetadata" } + }, + "required": [ + "data", + "pagination" ] } } @@ -44298,7 +64819,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -44332,15 +64853,13 @@ } } } - } - }, - "/v1/instances/{instance_id}/payins/evm": { + }, "post": { "x-sdk": true, "tags": [ - "Payins" + "Transfers" ], - "summary": "Create Payin", + "summary": "Create Transfer", "parameters": [ { "schema": { @@ -44366,28 +64885,28 @@ } ], "requestBody": { - "description": "Start payin", + "description": "Start transfer", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreatePayinIn" + "$ref": "#/components/schemas/CreateTransferIn" } } } }, "responses": { "200": { - "description": "Payin started with success", + "description": "Transfer started with success", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreatePayinOut" + "$ref": "#/components/schemas/CreateTransferOut" } } } }, "400": { - "description": "Possible error codes: `BANK_ACCOUNTS_INCOMPLETE`, `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_NOT_FOUND`, `FILES_UNREADABLE`, `PAYINS_METHOD_NOT_SUPPORTED`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `PAYOUTS_INSUFFICIENT_BALANCE`, `QUOTES_ALREADY_USED`, `QUOTES_EXPIRED`, `QUOTES_NOT_FOUND`, `QUOTES_RATE_UNAVAILABLE`, `VALIDATION_FAILED`, `VALIDATION_MISSING_REQUIRED_FIELDS`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_NOT_FOUND`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`, `VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BANK_ACCOUNTS_INCOMPLETE`, `BANK_ACCOUNTS_INVALID_BANK_CODE`, `BANK_ACCOUNTS_INVALID_ROUTING`, `BANK_ACCOUNTS_NOT_APPROVED`, `BANK_ACCOUNTS_NOT_FOUND`, `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED`, `BANK_ACCOUNTS_PLAID_NOT_FIRST_PARTY`, `BANK_ACCOUNTS_RTP_NOT_SUPPORTED`, `BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `BLOCKCHAIN_TX_FAILED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_ENHANCED_KYC_REQUIRED`, `CUSTOMERS_ID_DOCUMENT_INVALID`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_KYC_NOT_APPROVED`, `CUSTOMERS_KYC_TYPE_NOT_AVAILABLE`, `CUSTOMERS_NAME_INVALID`, `CUSTOMERS_ONBOARDING_INCOMPLETE`, `CUSTOMERS_OWNERSHIP_INVALID`, `FEES_PARTNER_FEE_EXCEEDED`, `FILES_TOO_LARGE`, `FILES_UNREADABLE`, `PAYABLES_ALREADY_PAID_OR_EXPIRED`, `PAYABLES_ALREADY_PAID_OR_IN_FLIGHT`, `PAYABLES_AMOUNT_NEGATIVE`, `PAYABLES_BANK_ACCOUNT_INVALID`, `PAYABLES_CODE_UNRESOLVABLE`, `PAYABLES_CURRENCY_MUST_BE_BRL`, `PAYABLES_DESTINATION_NOT_SUPPORTED`, `PAYABLES_DOCUMENT_INVALID`, `PAYABLES_DUPLICATE`, `PAYABLES_NETWORK_NOT_SUPPORTED`, `PAYABLES_NOT_CANCELABLE`, `PAYABLES_PIX_AMOUNT_REQUIRED`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `PAYOUTS_DOCUMENTS_NOT_ACCEPTED`, `PAYOUTS_INSUFFICIENT_BALANCE`, `QUOTES_ALREADY_USED`, `QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM`, `QUOTES_EXPIRED`, `QUOTES_INVALID_STATE`, `QUOTES_RATE_UNAVAILABLE`, `VALIDATION_FAILED`, `VALIDATION_INVALID_REQUEST`, `VALIDATION_MISSING_REQUIRED_FIELDS`, `VIRTUAL_ACCOUNTS_DISABLED`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_NOT_FOUND`, `VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`, `VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED`, `WALLETS_DEPOSIT_UNDER_REVIEW`, `WALLETS_DESTINATION_SANCTIONED`, `WALLETS_NOT_OWNED_BY_CUSTOMER`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { @@ -44399,8 +64918,52 @@ "value": { "success": false, "code": "BANK_ACCOUNTS_INCOMPLETE", - "message": "sepa_bank_account_incomplete", - "description": "The bank account details are incomplete for this payment method. Provide the missing fields.", + "message": "infinitus_missing_intermediary", + "description": "The banking provider cannot route payments to this bank automatically. Provide the US correspondent bank routing number (ABA, 9 digits) from the beneficiary bank USD wire instructions in swift_intermediary_bank_routing_number.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_INVALID_BANK_CODE": { + "summary": "BANK_ACCOUNTS_INVALID_BANK_CODE", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INVALID_BANK_CODE", + "message": "bank_accounts_invalid_bank_code", + "description": "The bank code provided is not valid for this payment rail. The message lists where to fetch the valid codes.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_INVALID_ROUTING": { + "summary": "BANK_ACCOUNTS_INVALID_ROUTING", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INVALID_ROUTING", + "message": "The routing number must be a valid 9-digit ABA routing number.", + "description": "The routing number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_NOT_APPROVED": { + "summary": "BANK_ACCOUNTS_NOT_APPROVED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_APPROVED", + "message": "bank_account_not_approved", + "description": "This bank account is not approved yet.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_NOT_FOUND": { + "summary": "BANK_ACCOUNTS_NOT_FOUND", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_FOUND", + "message": "bank_account_not_found", + "description": "The requested bank account was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -44416,6 +64979,39 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, + "BANK_ACCOUNTS_PLAID_NOT_FIRST_PARTY": { + "summary": "BANK_ACCOUNTS_PLAID_NOT_FIRST_PARTY", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PLAID_NOT_FIRST_PARTY", + "message": "plaid_account_not_first_party", + "description": "The connected bank account does not belong to this customer. Only accounts held in the customer's own name can be connected.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_RTP_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", + "message": "The provided routing number does not support RTP transactions.", + "description": "The provided routing number does not support instant payments.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR": { + "summary": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "message": "sepa_iban_not_eur", + "description": "SEPA payouts are only available to EUR accounts. This IBAN is from a country that holds another currency, so the payment would fail at settlement. Use an IBAN from a EUR account instead.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", "value": { @@ -44427,6 +65023,17 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, + "BLOCKCHAIN_TX_FAILED": { + "summary": "BLOCKCHAIN_TX_FAILED", + "value": { + "success": false, + "code": "BLOCKCHAIN_TX_FAILED", + "message": "transaction_failed", + "description": "The blockchain transaction failed. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", "value": { @@ -44438,6 +65045,28 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, + "CUSTOMERS_ENHANCED_KYC_REQUIRED": { + "summary": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "value": { + "success": false, + "code": "CUSTOMERS_ENHANCED_KYC_REQUIRED", + "message": "only_enhanced_kyc_allowed_for_high_risk_countries", + "description": "Individuals from high-risk countries must use enhanced verification (kyc_type: enhanced); standard verification is not available for them. See https://www.blindpay.com/docs/kb/supported-countries for country tiers.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ID_DOCUMENT_INVALID": { + "summary": "CUSTOMERS_ID_DOCUMENT_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_ID_DOCUMENT_INVALID", + "message": "id_doc_is_not_valid_passport_or_national_id", + "description": "The identity document is not accepted for this customer. Use a national ID, a passport with a valid passport number as the tax ID, or a driver license with a valid SSN or ITIN as the tax ID.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, "CUSTOMERS_INVALID_PHONE": { "summary": "CUSTOMERS_INVALID_PHONE", "value": { @@ -44460,13 +65089,79 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "CUSTOMERS_NOT_FOUND": { - "summary": "CUSTOMERS_NOT_FOUND", + "CUSTOMERS_KYC_NOT_APPROVED": { + "summary": "CUSTOMERS_KYC_NOT_APPROVED", "value": { "success": false, - "code": "CUSTOMERS_NOT_FOUND", - "message": "customer_not_found", - "description": "The requested customer was not found.", + "code": "CUSTOMERS_KYC_NOT_APPROVED", + "message": "kyc_not_approved", + "description": "This customer has not completed verification yet. Complete the verification before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE": { + "summary": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "message": "kyc_type_not_supported", + "description": "The requested verification type is not available for this customer. Use a supported verification type and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_NAME_INVALID": { + "summary": "CUSTOMERS_NAME_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_NAME_INVALID", + "message": "legal_name_required", + "description": "The name registered for this customer is not accepted. Review it and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ONBOARDING_INCOMPLETE": { + "summary": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "value": { + "success": false, + "code": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "message": "onboarding_incomplete", + "description": "Onboarding is not complete yet. Finish the remaining steps before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_OWNERSHIP_INVALID": { + "summary": "CUSTOMERS_OWNERSHIP_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_OWNERSHIP_INVALID", + "message": "business_owner_required", + "description": "The ownership information for this business customer is incomplete or inconsistent. Review the registered owners and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_PARTNER_FEE_EXCEEDED": { + "summary": "FEES_PARTNER_FEE_EXCEEDED", + "value": { + "success": false, + "code": "FEES_PARTNER_FEE_EXCEEDED", + "message": "partner_fee_exceeded", + "description": "The partner fee exceeds the allowed maximum for this transaction.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -44482,332 +65177,303 @@ "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "PAYINS_METHOD_NOT_SUPPORTED": { - "summary": "PAYINS_METHOD_NOT_SUPPORTED", + "PAYABLES_ALREADY_PAID_OR_EXPIRED": { + "summary": "PAYABLES_ALREADY_PAID_OR_EXPIRED", "value": { "success": false, - "code": "PAYINS_METHOD_NOT_SUPPORTED", - "message": "ted_payin_not_supported", - "description": "This payment method is not supported for this operation.", + "code": "PAYABLES_ALREADY_PAID_OR_EXPIRED", + "message": "payable_already_paid_or_expired", + "description": "This payment code was already paid or has expired and can no longer be paid.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "PAYOUTS_AMOUNT_BELOW_MINIMUM": { - "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT": { + "summary": "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT", "value": { "success": false, - "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", - "message": "swift_minimum_is_100_usd", - "description": "The amount is below the minimum for this payment rail.", + "code": "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT", + "message": "payable_already_paid_or_in_flight", + "description": "This payable is already being paid or was already paid. Only draft payables can be quoted; a failed or refunded attempt returns the payable to draft.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "PAYOUTS_INSUFFICIENT_BALANCE": { - "summary": "PAYOUTS_INSUFFICIENT_BALANCE", + "PAYABLES_AMOUNT_NEGATIVE": { + "summary": "PAYABLES_AMOUNT_NEGATIVE", "value": { "success": false, - "code": "PAYOUTS_INSUFFICIENT_BALANCE", - "message": "not_enough_balance", - "description": "There is not enough balance to complete this payout. Fund your balance and try again.", + "code": "PAYABLES_AMOUNT_NEGATIVE", + "message": "payable_amount_negative", + "description": "The payable total (line items plus taxes minus discount) cannot be negative.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "QUOTES_ALREADY_USED": { - "summary": "QUOTES_ALREADY_USED", + "PAYABLES_BANK_ACCOUNT_INVALID": { + "summary": "PAYABLES_BANK_ACCOUNT_INVALID", "value": { "success": false, - "code": "QUOTES_ALREADY_USED", - "message": "quote_already_used", - "description": "This quote was already used. Request a new quote.", + "code": "PAYABLES_BANK_ACCOUNT_INVALID", + "message": "payable_bank_account_invalid", + "description": "The bank_account details on this invoice payable were rejected. Check the errors list for the field that failed.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "QUOTES_EXPIRED": { - "summary": "QUOTES_EXPIRED", + "PAYABLES_CODE_UNRESOLVABLE": { + "summary": "PAYABLES_CODE_UNRESOLVABLE", "value": { "success": false, - "code": "QUOTES_EXPIRED", - "message": "quote_expired", - "description": "This quote has expired. Request a new quote and try again.", + "code": "PAYABLES_CODE_UNRESOLVABLE", + "message": "unresolvable_payable_code", + "description": "We could not read this payment code. Check the code and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "QUOTES_NOT_FOUND": { - "summary": "QUOTES_NOT_FOUND", + "PAYABLES_CURRENCY_MUST_BE_BRL": { + "summary": "PAYABLES_CURRENCY_MUST_BE_BRL", "value": { "success": false, - "code": "QUOTES_NOT_FOUND", - "message": "quote_not_found", - "description": "The requested quote was not found.", + "code": "PAYABLES_CURRENCY_MUST_BE_BRL", + "message": "payable_currency_must_be_brl", + "description": "Boleto and PIX payables must use BRL.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "QUOTES_RATE_UNAVAILABLE": { - "summary": "QUOTES_RATE_UNAVAILABLE", + "PAYABLES_DESTINATION_NOT_SUPPORTED": { + "summary": "PAYABLES_DESTINATION_NOT_SUPPORTED", "value": { "success": false, - "code": "QUOTES_RATE_UNAVAILABLE", - "message": "fx_rate_unavailable", - "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "code": "PAYABLES_DESTINATION_NOT_SUPPORTED", + "message": "payable_destination_not_supported", + "description": "Only boleto, arrecadação (utility/tax) and PIX QR code payables can be paid right now. Bank-destination invoice payables are not payable yet.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "PAYABLES_DOCUMENT_INVALID": { + "summary": "PAYABLES_DOCUMENT_INVALID", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "PAYABLES_DOCUMENT_INVALID", + "message": "payable_document_invalid", + "description": "document_file must be a URL returned by POST /upload with bucket `documents`, uploaded by this instance.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_MISSING_REQUIRED_FIELDS": { - "summary": "VALIDATION_MISSING_REQUIRED_FIELDS", + "PAYABLES_DUPLICATE": { + "summary": "PAYABLES_DUPLICATE", "value": { "success": false, - "code": "VALIDATION_MISSING_REQUIRED_FIELDS", - "message": "missing_required_fields", - "description": "Required fields are missing. Provide the missing fields and try again.", + "code": "PAYABLES_DUPLICATE", + "message": "duplicate_payable", + "description": "This payment code already has a payable registered, in progress or completed for this instance.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { - "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "PAYABLES_NETWORK_NOT_SUPPORTED": { + "summary": "PAYABLES_NETWORK_NOT_SUPPORTED", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", - "message": "id_doc_front_file_required", - "description": "Additional documents are required to create this virtual account. Upload the requested documents.", + "code": "PAYABLES_NETWORK_NOT_SUPPORTED", + "message": "payable_network_not_supported", + "description": "Only EVM wallets can fund payables right now.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_NOT_CANCELABLE": { + "summary": "PAYABLES_NOT_CANCELABLE", + "value": { + "success": false, + "code": "PAYABLES_NOT_CANCELABLE", + "message": "payable_not_cancelable", + "description": "Only draft payables can be deleted. Once a payout is executing this payable it can no longer be canceled.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_PIX_AMOUNT_REQUIRED": { + "summary": "PAYABLES_PIX_AMOUNT_REQUIRED", + "value": { + "success": false, + "code": "PAYABLES_PIX_AMOUNT_REQUIRED", + "message": "pix_code_amount_required", + "description": "This PIX code has no fixed amount and no amount was provided. Send the amount as line_items when registering a PIX code that lets the payer choose the value.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_AMOUNT_BELOW_MINIMUM": { + "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "value": { + "success": false, + "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "message": "swift_minimum_is_100_usd", + "description": "The amount is below the minimum for this payment rail.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_DOCUMENTS_NOT_ACCEPTED": { + "summary": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", + "value": { + "success": false, + "code": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", + "message": "document_upload_only_for_swift_payouts", + "description": "A document cannot be submitted for this payout in its current state.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_INSUFFICIENT_BALANCE": { + "summary": "PAYOUTS_INSUFFICIENT_BALANCE", + "value": { + "success": false, + "code": "PAYOUTS_INSUFFICIENT_BALANCE", + "message": "not_enough_balance", + "description": "There is not enough balance to complete this payout. Fund your balance and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VIRTUAL_ACCOUNTS_NOT_FOUND": { - "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "QUOTES_ALREADY_USED": { + "summary": "QUOTES_ALREADY_USED", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", - "message": "virtual_account_not_found", - "description": "The requested virtual account was not found.", + "code": "QUOTES_ALREADY_USED", + "message": "quote_already_used", + "description": "This quote was already used. Request a new quote.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { - "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM": { + "summary": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "message": "virtual_account_provision_failed", - "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "code": "QUOTES_AMOUNT_BELOW_PROVIDER_MINIMUM", + "message": "otc_provider_minimum_not_met", + "description": "The amount is below the minimum the liquidity provider accepts for this pair. Try a larger amount.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED": { - "summary": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", + "QUOTES_EXPIRED": { + "summary": "QUOTES_EXPIRED", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", - "message": "us_state_not_supported", - "description": "Virtual accounts are not available for this country or region.", + "code": "QUOTES_EXPIRED", + "message": "quote_expired", + "description": "This quote has expired. Request a new quote and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "401": { - "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_UNAUTHORIZED": { - "summary": "AUTH_UNAUTHORIZED", + }, + "QUOTES_INVALID_STATE": { + "summary": "QUOTES_INVALID_STATE", "value": { "success": false, - "code": "AUTH_UNAUTHORIZED", - "message": "unauthorized", - "description": "Authentication failed. Check your API key or session and try again.", + "code": "QUOTES_INVALID_STATE", + "message": "quote_invalid_state", + "description": "This quote cannot be authorized in its current state. Request a new quote and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "403": { - "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_FORBIDDEN": { - "summary": "AUTH_FORBIDDEN", + }, + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", "value": { "success": false, - "code": "AUTH_FORBIDDEN", - "message": "user_not_allowed", - "description": "You do not have permission to perform this action.", + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "404": { - "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "WALLETS_NOT_FOUND": { - "summary": "WALLETS_NOT_FOUND", + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", "value": { "success": false, - "code": "WALLETS_NOT_FOUND", - "message": "wallet_not_found", - "description": "The requested wallet was not found.", + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "422": { - "description": "Possible error codes: `CUSTOMERS_INVALID_DATA`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "CUSTOMERS_INVALID_DATA": { - "summary": "CUSTOMERS_INVALID_DATA", + }, + "VALIDATION_INVALID_REQUEST": { + "summary": "VALIDATION_INVALID_REQUEST", "value": { "success": false, - "code": "CUSTOMERS_INVALID_DATA", - "message": "invalid_customer_data", - "description": "The customer data was rejected by the banking provider. Check the highlighted fields and try again.", + "code": "VALIDATION_INVALID_REQUEST", + "message": "invalid_body", + "description": "The request is not valid for this operation. Check the parameters and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", + }, + "VALIDATION_MISSING_REQUIRED_FIELDS": { + "summary": "VALIDATION_MISSING_REQUIRED_FIELDS", "value": { "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", + "code": "VALIDATION_MISSING_REQUIRED_FIELDS", + "message": "missing_required_fields", + "description": "Required fields are missing. Provide the missing fields and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "500": { - "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `QUOTES_RATE_UNAVAILABLE`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", + }, + "VIRTUAL_ACCOUNTS_DISABLED": { + "summary": "VIRTUAL_ACCOUNTS_DISABLED", "value": { "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", + "code": "VIRTUAL_ACCOUNTS_DISABLED", + "message": "virtual_accounts_not_enabled", + "description": "Virtual accounts are not enabled for this account. Contact support to enable them.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { + "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "message": "id_doc_front_file_required", + "description": "An identity document is required for this customer. Upload the front of a valid document and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "QUOTES_RATE_UNAVAILABLE": { - "summary": "QUOTES_RATE_UNAVAILABLE", + "VIRTUAL_ACCOUNTS_NOT_FOUND": { + "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", "value": { "success": false, - "code": "QUOTES_RATE_UNAVAILABLE", - "message": "fx_rate_unavailable", - "description": "An exchange rate is temporarily unavailable. Try again shortly.", + "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "message": "virtual_account_not_found", + "description": "The requested virtual account was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { - "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE": { + "summary": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "message": "virtual_account_provision_failed", - "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", + "code": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "message": "banking_partner_not_eligible_for_customer", + "description": "This banking partner is not available for this customer. Choose a different banking partner.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "502": { - "description": "Possible error codes: `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { + }, "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", "value": { @@ -44818,160 +65484,47 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "503": { - "description": "Possible error codes: `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "QUOTES_RATE_UNAVAILABLE": { - "summary": "QUOTES_RATE_UNAVAILABLE", - "value": { - "success": false, - "code": "QUOTES_RATE_UNAVAILABLE", - "message": "fx_rate_unavailable", - "description": "An exchange rate is temporarily unavailable. Try again shortly.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - } - } - } - }, - "/v1/instances/{instance_id}/customers/{customer_id}/wallets": { - "post": { - "x-sdk": true, - "tags": [ - "Wallets" - ], - "summary": "Create Wallet", - "parameters": [ - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "required": false, - "name": "Idempotency-Key", - "in": "header" - } - ], - "requestBody": { - "description": "Create a new wallet", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateWalletIn" - } - } - } - }, - "responses": { - "200": { - "description": "Wallet created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WalletOut" - } - } - } - }, - "400": { - "description": "Possible error codes: `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_KYC_NOT_APPROVED`, `TRANSFERS_NOT_ENABLED`, `VALIDATION_FAILED`, `VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { - "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", - "value": { - "success": false, - "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", - "message": "network_not_supported_on_dev_instance", - "description": "This network or token combination is not supported for this operation.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } }, - "CUSTOMERS_KYC_NOT_APPROVED": { - "summary": "CUSTOMERS_KYC_NOT_APPROVED", + "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED": { + "summary": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", "value": { "success": false, - "code": "CUSTOMERS_KYC_NOT_APPROVED", - "message": "kyc_not_approved", - "description": "This customer has not completed verification yet. Complete the verification before continuing.", + "code": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", + "message": "us_state_not_supported", + "description": "Virtual accounts are not available for this country or region.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "TRANSFERS_NOT_ENABLED": { - "summary": "TRANSFERS_NOT_ENABLED", + "WALLETS_DEPOSIT_UNDER_REVIEW": { + "summary": "WALLETS_DEPOSIT_UNDER_REVIEW", "value": { "success": false, - "code": "TRANSFERS_NOT_ENABLED", - "message": "wallets_and_transfers_not_enabled", - "description": "Wallets and transfers are not enabled for this account. Contact support to enable them.", + "code": "WALLETS_DEPOSIT_UNDER_REVIEW", + "message": "wallet_deposit_under_review", + "description": "A deposit into this wallet is under compliance review. Transfers out of the wallet are paused until the review is resolved.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "WALLETS_DESTINATION_SANCTIONED": { + "summary": "WALLETS_DESTINATION_SANCTIONED", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "WALLETS_DESTINATION_SANCTIONED", + "message": "wallet_destination_sanctioned", + "description": "The destination wallet address is on a sanctions list. Funds cannot be sent to it.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED": { - "summary": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", + "WALLETS_NOT_OWNED_BY_CUSTOMER": { + "summary": "WALLETS_NOT_OWNED_BY_CUSTOMER", "value": { "success": false, - "code": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", - "message": "us_state_not_supported", - "description": "Virtual accounts are not available for this country or region.", + "code": "WALLETS_NOT_OWNED_BY_CUSTOMER", + "message": "blockchain_wallet_does_not_belong_to_customer", + "description": "The selected wallet belongs to a different customer. Choose one of this customer's wallets.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -45026,171 +65579,98 @@ } } }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `FEES_NOT_FOUND`, `INSTANCES_NOT_FOUND`, `PAYABLES_NOT_FOUND`, `PAYINS_NOT_FOUND`, `PAYOUTS_NOT_FOUND`, `QUOTES_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", "value": { "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + }, + "FEES_NOT_FOUND": { + "summary": "FEES_NOT_FOUND", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "FEES_NOT_FOUND", + "message": "partner_fee_not_found", + "description": "The requested fee configuration was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - } - } - }, - "get": { - "x-sdk": true, - "tags": [ - "Wallets" - ], - "summary": "Retrieve Wallets", - "parameters": [ - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - } - ], - "responses": { - "200": { - "description": "Get wallets", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WalletOut" - } - } - } - } - }, - "400": { - "description": "Possible error codes: `TRANSFERS_NOT_ENABLED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "TRANSFERS_NOT_ENABLED": { - "summary": "TRANSFERS_NOT_ENABLED", + }, + "INSTANCES_NOT_FOUND": { + "summary": "INSTANCES_NOT_FOUND", "value": { "success": false, - "code": "TRANSFERS_NOT_ENABLED", - "message": "wallets_and_transfers_not_enabled", - "description": "Wallets and transfers are not enabled for this account. Contact support to enable them.", + "code": "INSTANCES_NOT_FOUND", + "message": "instance_not_found", + "description": "The requested instance was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "PAYABLES_NOT_FOUND": { + "summary": "PAYABLES_NOT_FOUND", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "PAYABLES_NOT_FOUND", + "message": "payable_not_found", + "description": "This payable was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "401": { - "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_UNAUTHORIZED": { - "summary": "AUTH_UNAUTHORIZED", + }, + "PAYINS_NOT_FOUND": { + "summary": "PAYINS_NOT_FOUND", "value": { "success": false, - "code": "AUTH_UNAUTHORIZED", - "message": "unauthorized", - "description": "Authentication failed. Check your API key or session and try again.", + "code": "PAYINS_NOT_FOUND", + "message": "payin_not_found", + "description": "The requested payin was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "403": { - "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_FORBIDDEN": { - "summary": "AUTH_FORBIDDEN", + }, + "PAYOUTS_NOT_FOUND": { + "summary": "PAYOUTS_NOT_FOUND", "value": { "success": false, - "code": "AUTH_FORBIDDEN", - "message": "user_not_allowed", - "description": "You do not have permission to perform this action.", + "code": "PAYOUTS_NOT_FOUND", + "message": "payout_not_found", + "description": "The requested payout was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_NOT_FOUND": { + "summary": "QUOTES_NOT_FOUND", + "value": { + "success": false, + "code": "QUOTES_NOT_FOUND", + "message": "quote_not_found", + "description": "The requested quote was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", + "value": { + "success": false, + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -45199,21 +65679,21 @@ } } }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "422": { + "description": "Possible error codes: `CUSTOMERS_INVALID_DATA`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", + "CUSTOMERS_INVALID_DATA": { + "summary": "CUSTOMERS_INVALID_DATA", "value": { "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", + "code": "CUSTOMERS_INVALID_DATA", + "message": "invalid_customer_data", + "description": "The customer data was rejected by the banking provider. Check the highlighted fields and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -45222,21 +65702,21 @@ } } }, - "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -45244,136 +65724,55 @@ } } } - } - } - } - }, - "/v1/instances/{instance_id}/customers/{customer_id}/wallets/{id}": { - "get": { - "x-sdk": true, - "tags": [ - "Wallets" - ], - "summary": "Retrieve Wallet", - "parameters": [ - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "bk_000000000000" - }, - "required": true, - "name": "id", - "in": "path" - } - ], - "responses": { - "200": { - "description": "Get wallet", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WalletOut" - } - } - } }, - "400": { - "description": "Possible error codes: `TRANSFERS_NOT_ENABLED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "500": { + "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `QUOTES_RATE_UNAVAILABLE`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "TRANSFERS_NOT_ENABLED": { - "summary": "TRANSFERS_NOT_ENABLED", + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", "value": { "success": false, - "code": "TRANSFERS_NOT_ENABLED", - "message": "wallets_and_transfers_not_enabled", - "description": "Wallets and transfers are not enabled for this account. Contact support to enable them.", + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "401": { - "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_UNAUTHORIZED": { - "summary": "AUTH_UNAUTHORIZED", + }, + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", "value": { "success": false, - "code": "AUTH_UNAUTHORIZED", - "message": "unauthorized", - "description": "Authentication failed. Check your API key or session and try again.", + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "403": { - "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_FORBIDDEN": { - "summary": "AUTH_FORBIDDEN", + }, + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", "value": { "success": false, - "code": "AUTH_FORBIDDEN", - "message": "user_not_allowed", - "description": "You do not have permission to perform this action.", + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -45382,21 +65781,21 @@ } } }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "502": { + "description": "Possible error codes: `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", "value": { "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -45405,21 +65804,21 @@ } } }, - "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "503": { + "description": "Possible error codes: `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -45429,13 +65828,15 @@ } } } - }, - "delete": { + } + }, + "/v1/instances/{instance_id}/payables": { + "post": { "x-sdk": true, "tags": [ - "Wallets" + "Payables" ], - "summary": "Remove Wallet", + "summary": "Create Payable", "parameters": [ { "schema": { @@ -45448,29 +65849,6 @@ "name": "instance_id", "in": "path" }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "bk_000000000000" - }, - "required": true, - "name": "id", - "in": "path" - }, { "schema": { "type": "string", @@ -45483,237 +65861,504 @@ "in": "header" } ], + "requestBody": { + "description": "Register a bill to pay: an invoice, a boleto or a PIX QR code", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreatePayableIn" + } + } + } + }, "responses": { "200": { - "description": "Delete wallet", + "description": "Payable created as a draft. Pay it by creating a payout quote with payable_id.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Success" + "$ref": "#/components/schemas/PayableOut" } } } }, "400": { - "description": "Possible error codes: `TRANSFERS_NOT_ENABLED`, `VALIDATION_FAILED`, `WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `BANK_ACCOUNTS_INVALID_BANK_CODE`, `BANK_ACCOUNTS_INVALID_ROUTING`, `BANK_ACCOUNTS_NOT_APPROVED`, `BANK_ACCOUNTS_NOT_FOUND`, `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED`, `BANK_ACCOUNTS_RTP_NOT_SUPPORTED`, `BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `BLOCKCHAIN_TX_FAILED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `CUSTOMERS_KYC_TYPE_NOT_AVAILABLE`, `CUSTOMERS_NAME_INVALID`, `CUSTOMERS_ONBOARDING_INCOMPLETE`, `FEES_PARTNER_FEE_EXCEEDED`, `FILES_TOO_LARGE`, `FILES_UNREADABLE`, `LIMITS_AMOUNT_OUT_OF_RANGE`, `PAYABLES_ALREADY_PAID_OR_EXPIRED`, `PAYABLES_ALREADY_PAID_OR_IN_FLIGHT`, `PAYABLES_AMOUNT_NEGATIVE`, `PAYABLES_BANK_ACCOUNT_INVALID`, `PAYABLES_CODE_UNRESOLVABLE`, `PAYABLES_CURRENCY_MUST_BE_BRL`, `PAYABLES_DESTINATION_NOT_SUPPORTED`, `PAYABLES_DOCUMENT_INVALID`, `PAYABLES_DUPLICATE`, `PAYABLES_NETWORK_NOT_SUPPORTED`, `PAYABLES_NOT_CANCELABLE`, `PAYABLES_PIX_AMOUNT_REQUIRED`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `PAYOUTS_DOCUMENTS_NOT_ACCEPTED`, `QUOTES_ALREADY_USED`, `QUOTES_EXPIRED`, `QUOTES_INVALID_STATE`, `QUOTES_RATE_UNAVAILABLE`, `VALIDATION_FAILED`, `VALIDATION_INVALID_REQUEST`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_NOT_FOUND`, `VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "TRANSFERS_NOT_ENABLED": { - "summary": "TRANSFERS_NOT_ENABLED", + "BANK_ACCOUNTS_INVALID_BANK_CODE": { + "summary": "BANK_ACCOUNTS_INVALID_BANK_CODE", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INVALID_BANK_CODE", + "message": "bank_accounts_invalid_bank_code", + "description": "The bank code provided is not valid for this payment rail. The message lists where to fetch the valid codes.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_INVALID_ROUTING": { + "summary": "BANK_ACCOUNTS_INVALID_ROUTING", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_INVALID_ROUTING", + "message": "The routing number must be a valid 9-digit ABA routing number.", + "description": "The routing number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_NOT_APPROVED": { + "summary": "BANK_ACCOUNTS_NOT_APPROVED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_APPROVED", + "message": "bank_account_not_approved", + "description": "This bank account is not approved yet.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_NOT_FOUND": { + "summary": "BANK_ACCOUNTS_NOT_FOUND", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_NOT_FOUND", + "message": "bank_account_not_found", + "description": "The requested bank account was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", + "message": "unsupported_banking_partner", + "description": "This banking option is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_RTP_NOT_SUPPORTED": { + "summary": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_RTP_NOT_SUPPORTED", + "message": "The provided routing number does not support RTP transactions.", + "description": "The provided routing number does not support instant payments.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR": { + "summary": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "value": { + "success": false, + "code": "BANK_ACCOUNTS_SEPA_IBAN_NOT_EUR", + "message": "sepa_iban_not_eur", + "description": "SEPA payouts are only available to EUR accounts. This IBAN is from a country that holds another currency, so the payment would fail at settlement. Use an IBAN from a EUR account instead.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { + "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "message": "network_not_supported_on_dev_instance", + "description": "This network or token combination is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "BLOCKCHAIN_TX_FAILED": { + "summary": "BLOCKCHAIN_TX_FAILED", + "value": { + "success": false, + "code": "BLOCKCHAIN_TX_FAILED", + "message": "transaction_failed", + "description": "The blockchain transaction failed. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { + "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "value": { + "success": false, + "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", + "message": "country_not_supported", + "description": "This country is not supported for this operation.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_PHONE": { + "summary": "CUSTOMERS_INVALID_PHONE", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_PHONE", + "message": "invalid_phone_number", + "description": "The phone number provided is not valid. Check the number and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_INVALID_TAX_ID": { + "summary": "CUSTOMERS_INVALID_TAX_ID", + "value": { + "success": false, + "code": "CUSTOMERS_INVALID_TAX_ID", + "message": "invalid_cpf_or_rg_tax_id", + "description": "The tax ID provided is not valid. Check the value and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE": { + "summary": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "value": { + "success": false, + "code": "CUSTOMERS_KYC_TYPE_NOT_AVAILABLE", + "message": "kyc_type_not_supported", + "description": "The requested verification type is not available for this customer. Use a supported verification type and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_NAME_INVALID": { + "summary": "CUSTOMERS_NAME_INVALID", + "value": { + "success": false, + "code": "CUSTOMERS_NAME_INVALID", + "message": "legal_name_required", + "description": "The name registered for this customer is not accepted. Review it and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "CUSTOMERS_ONBOARDING_INCOMPLETE": { + "summary": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "value": { + "success": false, + "code": "CUSTOMERS_ONBOARDING_INCOMPLETE", + "message": "onboarding_incomplete", + "description": "Onboarding is not complete yet. Finish the remaining steps before continuing.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FEES_PARTNER_FEE_EXCEEDED": { + "summary": "FEES_PARTNER_FEE_EXCEEDED", + "value": { + "success": false, + "code": "FEES_PARTNER_FEE_EXCEEDED", + "message": "partner_fee_exceeded", + "description": "The partner fee exceeds the allowed maximum for this transaction.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", + "value": { + "success": false, + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "LIMITS_AMOUNT_OUT_OF_RANGE": { + "summary": "LIMITS_AMOUNT_OUT_OF_RANGE", + "value": { + "success": false, + "code": "LIMITS_AMOUNT_OUT_OF_RANGE", + "message": "limits_amount_out_of_range", + "description": "The amount is outside the allowed range. The message includes the allowed range.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_ALREADY_PAID_OR_EXPIRED": { + "summary": "PAYABLES_ALREADY_PAID_OR_EXPIRED", + "value": { + "success": false, + "code": "PAYABLES_ALREADY_PAID_OR_EXPIRED", + "message": "payable_already_paid_or_expired", + "description": "This payment code was already paid or has expired and can no longer be paid.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT": { + "summary": "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT", + "value": { + "success": false, + "code": "PAYABLES_ALREADY_PAID_OR_IN_FLIGHT", + "message": "payable_already_paid_or_in_flight", + "description": "This payable is already being paid or was already paid. Only draft payables can be quoted; a failed or refunded attempt returns the payable to draft.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_AMOUNT_NEGATIVE": { + "summary": "PAYABLES_AMOUNT_NEGATIVE", + "value": { + "success": false, + "code": "PAYABLES_AMOUNT_NEGATIVE", + "message": "payable_amount_negative", + "description": "The payable total (line items plus taxes minus discount) cannot be negative.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_BANK_ACCOUNT_INVALID": { + "summary": "PAYABLES_BANK_ACCOUNT_INVALID", + "value": { + "success": false, + "code": "PAYABLES_BANK_ACCOUNT_INVALID", + "message": "payable_bank_account_invalid", + "description": "The bank_account details on this invoice payable were rejected. Check the errors list for the field that failed.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_CODE_UNRESOLVABLE": { + "summary": "PAYABLES_CODE_UNRESOLVABLE", + "value": { + "success": false, + "code": "PAYABLES_CODE_UNRESOLVABLE", + "message": "unresolvable_payable_code", + "description": "We could not read this payment code. Check the code and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_CURRENCY_MUST_BE_BRL": { + "summary": "PAYABLES_CURRENCY_MUST_BE_BRL", + "value": { + "success": false, + "code": "PAYABLES_CURRENCY_MUST_BE_BRL", + "message": "payable_currency_must_be_brl", + "description": "Boleto and PIX payables must use BRL.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DESTINATION_NOT_SUPPORTED": { + "summary": "PAYABLES_DESTINATION_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYABLES_DESTINATION_NOT_SUPPORTED", + "message": "payable_destination_not_supported", + "description": "Only boleto, arrecadação (utility/tax) and PIX QR code payables can be paid right now. Bank-destination invoice payables are not payable yet.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DOCUMENT_INVALID": { + "summary": "PAYABLES_DOCUMENT_INVALID", + "value": { + "success": false, + "code": "PAYABLES_DOCUMENT_INVALID", + "message": "payable_document_invalid", + "description": "document_file must be a URL returned by POST /upload with bucket `documents`, uploaded by this instance.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_DUPLICATE": { + "summary": "PAYABLES_DUPLICATE", + "value": { + "success": false, + "code": "PAYABLES_DUPLICATE", + "message": "duplicate_payable", + "description": "This payment code already has a payable registered, in progress or completed for this instance.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_NETWORK_NOT_SUPPORTED": { + "summary": "PAYABLES_NETWORK_NOT_SUPPORTED", + "value": { + "success": false, + "code": "PAYABLES_NETWORK_NOT_SUPPORTED", + "message": "payable_network_not_supported", + "description": "Only EVM wallets can fund payables right now.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_NOT_CANCELABLE": { + "summary": "PAYABLES_NOT_CANCELABLE", + "value": { + "success": false, + "code": "PAYABLES_NOT_CANCELABLE", + "message": "payable_not_cancelable", + "description": "Only draft payables can be deleted. Once a payout is executing this payable it can no longer be canceled.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYABLES_PIX_AMOUNT_REQUIRED": { + "summary": "PAYABLES_PIX_AMOUNT_REQUIRED", + "value": { + "success": false, + "code": "PAYABLES_PIX_AMOUNT_REQUIRED", + "message": "pix_code_amount_required", + "description": "This PIX code has no fixed amount and no amount was provided. Send the amount as line_items when registering a PIX code that lets the payer choose the value.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_AMOUNT_BELOW_MINIMUM": { + "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "value": { + "success": false, + "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", + "message": "swift_minimum_is_100_usd", + "description": "The amount is below the minimum for this payment rail.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "PAYOUTS_DOCUMENTS_NOT_ACCEPTED": { + "summary": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", + "value": { + "success": false, + "code": "PAYOUTS_DOCUMENTS_NOT_ACCEPTED", + "message": "document_upload_only_for_swift_payouts", + "description": "A document cannot be submitted for this payout in its current state.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_ALREADY_USED": { + "summary": "QUOTES_ALREADY_USED", + "value": { + "success": false, + "code": "QUOTES_ALREADY_USED", + "message": "quote_already_used", + "description": "This quote was already used. Request a new quote.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "QUOTES_EXPIRED": { + "summary": "QUOTES_EXPIRED", "value": { "success": false, - "code": "TRANSFERS_NOT_ENABLED", - "message": "wallets_and_transfers_not_enabled", - "description": "Wallets and transfers are not enabled for this account. Contact support to enable them.", + "code": "QUOTES_EXPIRED", + "message": "quote_expired", + "description": "This quote has expired. Request a new quote and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "QUOTES_INVALID_STATE": { + "summary": "QUOTES_INVALID_STATE", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "QUOTES_INVALID_STATE", + "message": "quote_invalid_state", + "description": "This quote cannot be authorized in its current state. Request a new quote and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT": { - "summary": "WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT", + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", "value": { "success": false, - "code": "WALLETS_ATTACHED_TO_VIRTUAL_ACCOUNT", - "message": "wallet_attached_to_virtual_account", - "description": "This wallet is attached to a virtual account and cannot be deleted. Delete the virtual account first.", + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "401": { - "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_UNAUTHORIZED": { - "summary": "AUTH_UNAUTHORIZED", + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", "value": { "success": false, - "code": "AUTH_UNAUTHORIZED", - "message": "unauthorized", - "description": "Authentication failed. Check your API key or session and try again.", + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "403": { - "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_FORBIDDEN": { - "summary": "AUTH_FORBIDDEN", + }, + "VALIDATION_INVALID_REQUEST": { + "summary": "VALIDATION_INVALID_REQUEST", "value": { "success": false, - "code": "AUTH_FORBIDDEN", - "message": "user_not_allowed", - "description": "You do not have permission to perform this action.", + "code": "VALIDATION_INVALID_REQUEST", + "message": "invalid_body", + "description": "The request is not valid for this operation. Check the parameters and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", + }, + "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { + "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", "value": { "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", + "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", + "message": "id_doc_front_file_required", + "description": "An identity document is required for this customer. Upload the front of a valid document and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + }, + "VIRTUAL_ACCOUNTS_NOT_FOUND": { + "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", + "message": "virtual_account_not_found", + "description": "The requested virtual account was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - } - } - } - }, - "/v1/instances/{instance_id}/customers/{customer_id}/wallets/{id}/balance": { - "get": { - "x-sdk": true, - "tags": [ - "Wallets" - ], - "summary": "Retrieve Wallet Balance", - "parameters": [ - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "description": "Customer ID", - "example": "re_000000000000" - }, - "required": true, - "name": "customer_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "bk_000000000000" - }, - "required": true, - "name": "id", - "in": "path" - } - ], - "responses": { - "200": { - "description": "Get wallet balance", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WalletBalanceOut" - } - } - } - }, - "400": { - "description": "Possible error codes: `TRANSFERS_NOT_ENABLED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "TRANSFERS_NOT_ENABLED": { - "summary": "TRANSFERS_NOT_ENABLED", + }, + "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE": { + "summary": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", "value": { "success": false, - "code": "TRANSFERS_NOT_ENABLED", - "message": "wallets_and_transfers_not_enabled", - "description": "Wallets and transfers are not enabled for this account. Contact support to enable them.", + "code": "VIRTUAL_ACCOUNTS_PARTNER_NOT_ELIGIBLE", + "message": "banking_partner_not_eligible_for_customer", + "description": "This banking partner is not available for this customer. Choose a different banking partner.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -45768,190 +66413,54 @@ } } }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", - "value": { - "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, - "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", - "value": { - "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, - "503": { - "description": "Possible error codes: `WALLETS_BALANCE_UNAVAILABLE`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "WALLETS_BALANCE_UNAVAILABLE": { - "summary": "WALLETS_BALANCE_UNAVAILABLE", - "value": { - "success": false, - "code": "WALLETS_BALANCE_UNAVAILABLE", - "message": "balance_temporarily_unavailable", - "description": "The wallet balance is temporarily unavailable. Try again shortly.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - } - } - } - }, - "/v1/instances/{instance_id}/transfer-quotes": { - "post": { - "x-sdk": true, - "tags": [ - "Transfer Quotes" - ], - "summary": "Create Transfer Quote", - "parameters": [ - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" - }, - "required": false, - "name": "Idempotency-Key", - "in": "header" - } - ], - "requestBody": { - "description": "Create a new quote", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateTransferQuoteIn" - } - } - } - }, - "responses": { - "200": { - "description": "Transfer Quote creation details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateTransferQuoteOut" - } - } - } - }, - "400": { - "description": "Possible error codes: `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_KYC_NOT_APPROVED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "404": { + "description": "Possible error codes: `CUSTOMERS_NOT_FOUND`, `PAYABLES_NOT_FOUND`, `PAYOUTS_NOT_FOUND`, `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { - "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", + "CUSTOMERS_NOT_FOUND": { + "summary": "CUSTOMERS_NOT_FOUND", "value": { "success": false, - "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", - "message": "network_not_supported_on_dev_instance", - "description": "This network or token combination is not supported for this operation.", + "code": "CUSTOMERS_NOT_FOUND", + "message": "customer_not_found", + "description": "The requested customer was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "CUSTOMERS_KYC_NOT_APPROVED": { - "summary": "CUSTOMERS_KYC_NOT_APPROVED", + "PAYABLES_NOT_FOUND": { + "summary": "PAYABLES_NOT_FOUND", "value": { "success": false, - "code": "CUSTOMERS_KYC_NOT_APPROVED", - "message": "kyc_not_approved", - "description": "This customer has not completed verification yet. Complete the verification before continuing.", + "code": "PAYABLES_NOT_FOUND", + "message": "payable_not_found", + "description": "This payable was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", + "PAYOUTS_NOT_FOUND": { + "summary": "PAYOUTS_NOT_FOUND", "value": { "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", + "code": "PAYOUTS_NOT_FOUND", + "message": "payout_not_found", + "description": "The requested payout was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - } - } - } - } - }, - "401": { - "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_UNAUTHORIZED": { - "summary": "AUTH_UNAUTHORIZED", + }, + "WALLETS_NOT_FOUND": { + "summary": "WALLETS_NOT_FOUND", "value": { "success": false, - "code": "AUTH_UNAUTHORIZED", - "message": "unauthorized", - "description": "Authentication failed. Check your API key or session and try again.", + "code": "WALLETS_NOT_FOUND", + "message": "wallet_not_found", + "description": "The requested wallet was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -45960,21 +66469,21 @@ } } }, - "403": { - "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "422": { + "description": "Possible error codes: `CUSTOMERS_INVALID_DATA`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "AUTH_FORBIDDEN": { - "summary": "AUTH_FORBIDDEN", + "CUSTOMERS_INVALID_DATA": { + "summary": "CUSTOMERS_INVALID_DATA", "value": { "success": false, - "code": "AUTH_FORBIDDEN", - "message": "user_not_allowed", - "description": "You do not have permission to perform this action.", + "code": "CUSTOMERS_INVALID_DATA", + "message": "invalid_customer_data", + "description": "The customer data was rejected by the banking provider. Check the highlighted fields and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -45996,7 +66505,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -46007,145 +66516,42 @@ } }, "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", - "value": { - "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - } - } - } - }, - "/v1/instances/{instance_id}/transfers/{id}": { - "get": { - "x-sdk": true, - "tags": [ - "Transfers" - ], - "summary": "Retrieve Transfer", - "parameters": [ - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "in_000000000000" - }, - "required": true, - "name": "instance_id", - "in": "path" - }, - { - "schema": { - "type": "string", - "minLength": 15, - "maxLength": 15, - "example": "pa_000000000000" - }, - "required": true, - "name": "id", - "in": "path" - } - ], - "responses": { - "200": { - "description": "List transfers", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TransferOut" - } - } - } - }, - "400": { - "description": "Possible error codes: `TRANSFERS_NOT_ENABLED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "TRANSFERS_NOT_ENABLED": { - "summary": "TRANSFERS_NOT_ENABLED", + "FILES_UNREADABLE": { + "summary": "FILES_UNREADABLE", "value": { "success": false, - "code": "TRANSFERS_NOT_ENABLED", - "message": "wallets_and_transfers_not_enabled", - "description": "Wallets and transfers are not enabled for this account. Contact support to enable them.", + "code": "FILES_UNREADABLE", + "message": "file_download_failed", + "description": "We could not read the uploaded file. Check the file and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } }, - "VALIDATION_FAILED": { - "summary": "VALIDATION_FAILED", - "value": { - "success": false, - "code": "VALIDATION_FAILED", - "message": "validation_failed", - "description": "The request contains invalid fields. Check the errors list for details.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, - "401": { - "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_UNAUTHORIZED": { - "summary": "AUTH_UNAUTHORIZED", + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", "value": { "success": false, - "code": "AUTH_UNAUTHORIZED", - "message": "unauthorized", - "description": "Authentication failed. Check your API key or session and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, - "403": { - "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "AUTH_FORBIDDEN": { - "summary": "AUTH_FORBIDDEN", + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", "value": { "success": false, - "code": "AUTH_FORBIDDEN", - "message": "user_not_allowed", - "description": "You do not have permission to perform this action.", + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -46154,21 +66560,21 @@ } } }, - "429": { - "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "502": { + "description": "Possible error codes: `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "AUTH_RATE_LIMITED": { - "summary": "AUTH_RATE_LIMITED", + "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { + "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", "value": { "success": false, - "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", - "description": "Too many requests. Wait a moment and try again.", + "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", + "message": "virtual_account_provision_failed", + "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -46177,21 +66583,21 @@ } } }, - "500": { - "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "503": { + "description": "Possible error codes: `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "INTERNAL_ERROR": { - "summary": "INTERNAL_ERROR", + "QUOTES_RATE_UNAVAILABLE": { + "summary": "QUOTES_RATE_UNAVAILABLE", "value": { "success": false, - "code": "INTERNAL_ERROR", - "message": "internal_error", - "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "code": "QUOTES_RATE_UNAVAILABLE", + "message": "fx_rate_unavailable", + "description": "An exchange rate is temporarily unavailable. Try again shortly.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -46201,35 +66607,171 @@ } } } - } - }, - "/v1/e/transfers/{id}": { + }, "get": { "x-sdk": true, "tags": [ - "Transfers" + "Payables" ], - "summary": "Retrieve Transfer Track", + "summary": "List Payables", "parameters": [ { "schema": { "type": "string", "minLength": 15, "maxLength": 15, - "example": "pa_000000000000" + "example": "in_000000000000" }, "required": true, - "name": "id", + "name": "instance_id", "in": "path" + }, + { + "schema": { + "type": "string", + "enum": [ + "10", + "50", + "100", + "200", + "500", + "1000" + ], + "description": "Number of items to return", + "example": "50" + }, + "required": false, + "name": "limit", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "0", + "10", + "50", + "100", + "200", + "500", + "1000" + ], + "description": "Number of items to skip", + "example": "0" + }, + "required": false, + "name": "offset", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "A cursor for use in pagination. starting_after is an object ID that defines your place in the list.", + "example": "pi_123" + }, + "required": false, + "name": "starting_after", + "in": "query" + }, + { + "schema": { + "type": "string", + "description": "A cursor for use in pagination. ending_before is an object ID that defines your place in the list.", + "example": "pi_123" + }, + "required": false, + "name": "ending_before", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "draft", + "processing", + "completed", + "canceled" + ] + }, + "required": false, + "name": "status", + "in": "query" + }, + { + "schema": { + "type": "string", + "minLength": 15, + "maxLength": 15, + "example": "re_000000000000" + }, + "required": false, + "name": "customer_id", + "in": "query" + }, + { + "schema": { + "type": "string", + "maxLength": 255 + }, + "required": false, + "name": "customer_name", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "boleto", + "pix_code", + "invoice" + ] + }, + "required": false, + "name": "type", + "in": "query" + }, + { + "schema": { + "type": "string", + "maxLength": 255 + }, + "required": false, + "name": "beneficiary_name", + "in": "query" } ], "responses": { "200": { - "description": "List transfers", + "description": "List payables with pagination", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TransferOut" + "anyOf": [ + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PayableOut" + } + }, + "pagination": { + "$ref": "#/components/schemas/PaginationMetadata" + } + }, + "required": [ + "data", + "pagination" + ] + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/PayableOut" + } + } + ] } } } @@ -46316,7 +66858,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -46352,13 +66894,13 @@ } } }, - "/v1/instances/{instance_id}/transfers": { + "/v1/instances/{instance_id}/payables/{id}": { "get": { "x-sdk": true, "tags": [ - "Transfers" + "Payables" ], - "summary": "Retrieve Transfers", + "summary": "Retrieve Payable", "parameters": [ { "schema": { @@ -46374,106 +66916,34 @@ { "schema": { "type": "string", - "enum": [ - "10", - "50", - "100", - "200", - "500", - "1000" - ], - "description": "Number of items to return", - "example": "50" - }, - "required": false, - "name": "limit", - "in": "query" - }, - { - "schema": { - "type": "string", - "enum": [ - "0", - "10", - "50", - "100", - "200", - "500", - "1000" - ], - "description": "Number of items to skip", - "example": "0" - }, - "required": false, - "name": "offset", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "A cursor for use in pagination. starting_after is an object ID that defines your place in the list.", - "example": "pi_123" - }, - "required": false, - "name": "starting_after", - "in": "query" - }, - { - "schema": { - "type": "string", - "description": "A cursor for use in pagination. ending_before is an object ID that defines your place in the list.", - "example": "pi_123" + "minLength": 15, + "maxLength": 15, + "example": "pb_000000000000" }, - "required": false, - "name": "ending_before", - "in": "query" + "required": true, + "name": "id", + "in": "path" } ], "responses": { "200": { - "description": "List transfers", + "description": "Payable details", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TransferOut" - } - }, - "pagination": { - "$ref": "#/components/schemas/PaginationMetadata" - } - }, - "required": [ - "data", - "pagination" - ] + "$ref": "#/components/schemas/PayableOut" } } } }, "400": { - "description": "Possible error codes: `TRANSFERS_NOT_ENABLED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `VALIDATION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "TRANSFERS_NOT_ENABLED": { - "summary": "TRANSFERS_NOT_ENABLED", - "value": { - "success": false, - "code": "TRANSFERS_NOT_ENABLED", - "message": "wallets_and_transfers_not_enabled", - "description": "Wallets and transfers are not enabled for this account. Contact support to enable them.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "VALIDATION_FAILED": { "summary": "VALIDATION_FAILED", "value": { @@ -46535,6 +67005,29 @@ } } }, + "404": { + "description": "Possible error codes: `PAYABLES_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "PAYABLES_NOT_FOUND": { + "summary": "PAYABLES_NOT_FOUND", + "value": { + "success": false, + "code": "PAYABLES_NOT_FOUND", + "message": "payable_not_found", + "description": "This payable was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -46548,7 +67041,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -46583,12 +67076,12 @@ } } }, - "post": { + "delete": { "x-sdk": true, "tags": [ - "Transfers" + "Payables" ], - "summary": "Create Transfer", + "summary": "Delete Payable", "parameters": [ { "schema": { @@ -46604,172 +67097,41 @@ { "schema": { "type": "string", - "maxLength": 255, - "description": "Optional key to safely retry this request without performing the action twice. Retrying with the same key and an identical body replays the original response; reusing a key with a different body returns an error. Keys are kept for 24 hours.", - "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + "minLength": 15, + "maxLength": 15, + "example": "pb_000000000000" }, - "required": false, - "name": "Idempotency-Key", - "in": "header" + "required": true, + "name": "id", + "in": "path" } ], - "requestBody": { - "description": "Start transfer", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateTransferIn" - } - } - } - }, "responses": { "200": { - "description": "Transfer started with success", + "description": "Payable canceled. Only draft payables (no payout executing them) can be deleted; the same code can be registered again afterwards.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateTransferOut" + "$ref": "#/components/schemas/PayableOut" } } } }, "400": { - "description": "Possible error codes: `BANK_ACCOUNTS_INCOMPLETE`, `BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED`, `BLOCKCHAIN_NETWORK_NOT_SUPPORTED`, `CUSTOMERS_COUNTRY_NOT_SUPPORTED`, `CUSTOMERS_INVALID_PHONE`, `CUSTOMERS_INVALID_TAX_ID`, `FILES_UNREADABLE`, `PAYOUTS_AMOUNT_BELOW_MINIMUM`, `PAYOUTS_INSUFFICIENT_BALANCE`, `QUOTES_EXPIRED`, `QUOTES_RATE_UNAVAILABLE`, `TRANSFERS_NOT_ENABLED`, `VALIDATION_FAILED`, `VALIDATION_MISSING_REQUIRED_FIELDS`, `VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED`, `VIRTUAL_ACCOUNTS_NOT_FOUND`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`, `VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `PAYABLES_NOT_CANCELABLE`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "BANK_ACCOUNTS_INCOMPLETE": { - "summary": "BANK_ACCOUNTS_INCOMPLETE", - "value": { - "success": false, - "code": "BANK_ACCOUNTS_INCOMPLETE", - "message": "sepa_bank_account_incomplete", - "description": "The bank account details are incomplete for this payment method. Provide the missing fields.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED": { - "summary": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", - "value": { - "success": false, - "code": "BANK_ACCOUNTS_PARTNER_NOT_SUPPORTED", - "message": "unsupported_banking_partner", - "description": "This banking option is not supported for this operation.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "BLOCKCHAIN_NETWORK_NOT_SUPPORTED": { - "summary": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", - "value": { - "success": false, - "code": "BLOCKCHAIN_NETWORK_NOT_SUPPORTED", - "message": "network_not_supported_on_dev_instance", - "description": "This network or token combination is not supported for this operation.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_COUNTRY_NOT_SUPPORTED": { - "summary": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", - "value": { - "success": false, - "code": "CUSTOMERS_COUNTRY_NOT_SUPPORTED", - "message": "country_not_supported", - "description": "This country is not supported for this operation.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_INVALID_PHONE": { - "summary": "CUSTOMERS_INVALID_PHONE", - "value": { - "success": false, - "code": "CUSTOMERS_INVALID_PHONE", - "message": "invalid_phone_number", - "description": "The phone number provided is not valid. Check the number and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "CUSTOMERS_INVALID_TAX_ID": { - "summary": "CUSTOMERS_INVALID_TAX_ID", - "value": { - "success": false, - "code": "CUSTOMERS_INVALID_TAX_ID", - "message": "invalid_cpf_or_rg_tax_id", - "description": "The tax ID provided is not valid. Check the value and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", - "value": { - "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "PAYOUTS_AMOUNT_BELOW_MINIMUM": { - "summary": "PAYOUTS_AMOUNT_BELOW_MINIMUM", - "value": { - "success": false, - "code": "PAYOUTS_AMOUNT_BELOW_MINIMUM", - "message": "swift_minimum_is_100_usd", - "description": "The amount is below the minimum for this payment rail.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "PAYOUTS_INSUFFICIENT_BALANCE": { - "summary": "PAYOUTS_INSUFFICIENT_BALANCE", - "value": { - "success": false, - "code": "PAYOUTS_INSUFFICIENT_BALANCE", - "message": "not_enough_balance", - "description": "There is not enough balance to complete this payout. Fund your balance and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "QUOTES_EXPIRED": { - "summary": "QUOTES_EXPIRED", - "value": { - "success": false, - "code": "QUOTES_EXPIRED", - "message": "quote_expired", - "description": "This quote has expired. Request a new quote and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "QUOTES_RATE_UNAVAILABLE": { - "summary": "QUOTES_RATE_UNAVAILABLE", - "value": { - "success": false, - "code": "QUOTES_RATE_UNAVAILABLE", - "message": "fx_rate_unavailable", - "description": "An exchange rate is temporarily unavailable. Try again shortly.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "TRANSFERS_NOT_ENABLED": { - "summary": "TRANSFERS_NOT_ENABLED", + "PAYABLES_NOT_CANCELABLE": { + "summary": "PAYABLES_NOT_CANCELABLE", "value": { "success": false, - "code": "TRANSFERS_NOT_ENABLED", - "message": "wallets_and_transfers_not_enabled", - "description": "Wallets and transfers are not enabled for this account. Contact support to enable them.", + "code": "PAYABLES_NOT_CANCELABLE", + "message": "payable_not_cancelable", + "description": "Only draft payables can be deleted. Once a payout is executing this payable it can no longer be canceled.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -46784,61 +67146,6 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - }, - "VALIDATION_MISSING_REQUIRED_FIELDS": { - "summary": "VALIDATION_MISSING_REQUIRED_FIELDS", - "value": { - "success": false, - "code": "VALIDATION_MISSING_REQUIRED_FIELDS", - "message": "missing_required_fields", - "description": "Required fields are missing. Provide the missing fields and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED": { - "summary": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_DOCUMENTS_REQUIRED", - "message": "id_doc_front_file_required", - "description": "Additional documents are required to create this virtual account. Upload the requested documents.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "VIRTUAL_ACCOUNTS_NOT_FOUND": { - "summary": "VIRTUAL_ACCOUNTS_NOT_FOUND", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_NOT_FOUND", - "message": "virtual_account_not_found", - "description": "The requested virtual account was not found.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { - "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "message": "virtual_account_provision_failed", - "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED": { - "summary": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_REGION_NOT_SUPPORTED", - "message": "us_state_not_supported", - "description": "Virtual accounts are not available for this country or region.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } } } } @@ -46891,43 +67198,20 @@ } }, "404": { - "description": "Possible error codes: `WALLETS_NOT_FOUND`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "WALLETS_NOT_FOUND": { - "summary": "WALLETS_NOT_FOUND", - "value": { - "success": false, - "code": "WALLETS_NOT_FOUND", - "message": "wallet_not_found", - "description": "The requested wallet was not found.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, - "422": { - "description": "Possible error codes: `CUSTOMERS_INVALID_DATA`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `PAYABLES_NOT_FOUND`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "CUSTOMERS_INVALID_DATA": { - "summary": "CUSTOMERS_INVALID_DATA", + "PAYABLES_NOT_FOUND": { + "summary": "PAYABLES_NOT_FOUND", "value": { "success": false, - "code": "CUSTOMERS_INVALID_DATA", - "message": "invalid_customer_data", - "description": "The customer data was rejected by the banking provider. Check the highlighted fields and try again.", + "code": "PAYABLES_NOT_FOUND", + "message": "payable_not_found", + "description": "This payable was not found.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } @@ -46949,7 +67233,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -46960,24 +67244,13 @@ } }, "500": { - "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`, `QUOTES_RATE_UNAVAILABLE`, `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", - "value": { - "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -46988,74 +67261,6 @@ "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" } - }, - "QUOTES_RATE_UNAVAILABLE": { - "summary": "QUOTES_RATE_UNAVAILABLE", - "value": { - "success": false, - "code": "QUOTES_RATE_UNAVAILABLE", - "message": "fx_rate_unavailable", - "description": "An exchange rate is temporarily unavailable. Try again shortly.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, - "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { - "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "message": "virtual_account_provision_failed", - "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, - "502": { - "description": "Possible error codes: `VIRTUAL_ACCOUNTS_PROVISION_FAILED`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "VIRTUAL_ACCOUNTS_PROVISION_FAILED": { - "summary": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "value": { - "success": false, - "code": "VIRTUAL_ACCOUNTS_PROVISION_FAILED", - "message": "virtual_account_provision_failed", - "description": "We could not create the virtual account. Try again, and contact support if the problem persists.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - } - } - } - } - }, - "503": { - "description": "Possible error codes: `QUOTES_RATE_UNAVAILABLE`. See the Error responses section for retry semantics.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - }, - "examples": { - "QUOTES_RATE_UNAVAILABLE": { - "summary": "QUOTES_RATE_UNAVAILABLE", - "value": { - "success": false, - "code": "QUOTES_RATE_UNAVAILABLE", - "message": "fx_rate_unavailable", - "description": "An exchange rate is temporarily unavailable. Try again shortly.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } } } } @@ -47071,6 +67276,7 @@ "Webhook Endpoints" ], "summary": "Register Webhook", + "description": "Registers an HTTPS endpoint that receives the listed events. Event names and payload schemas are in the webhooks section of this API reference (and in the MCP resource blindpay://webhooks/events). Deliveries are signed with Svix; read the signing secret with Retrieve Webhook Secret and verify every delivery.", "parameters": [ { "schema": { @@ -47220,7 +67426,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -47370,7 +67576,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -47541,7 +67747,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -47710,7 +67916,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -47859,7 +68065,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -48023,7 +68229,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -48104,22 +68310,30 @@ "payout_percentage_fee": { "type": "number", "minimum": 0, - "maximum": 1000 + "maximum": 9900, + "description": "Basis points charged on each payout: 100 means 1%. Maximum 9900 (99%).", + "example": 100 }, "payout_flat_fee": { "type": "number", "minimum": 0, - "maximum": 100000 + "maximum": 100000, + "description": "Flat fee charged on each payout, in cents: 200 means 2.00. Maximum 100000 (1,000.00).", + "example": 200 }, "payin_percentage_fee": { "type": "number", "minimum": 0, - "maximum": 1000 + "maximum": 9900, + "description": "Basis points charged on each payin: 100 means 1%. Maximum 9900 (99%).", + "example": 100 }, "payin_flat_fee": { "type": "number", "minimum": 0, - "maximum": 100000 + "maximum": 100000, + "description": "Flat fee charged on each payin, in cents: 200 means 2.00. Maximum 100000 (1,000.00).", + "example": 200 }, "virtual_account_set": { "type": [ @@ -48168,22 +68382,30 @@ "payout_percentage_fee": { "type": "number", "minimum": 0, - "maximum": 1000 + "maximum": 9900, + "description": "Basis points charged on each payout: 100 means 1%. Maximum 9900 (99%).", + "example": 100 }, "payout_flat_fee": { "type": "number", "minimum": 0, - "maximum": 100000 + "maximum": 100000, + "description": "Flat fee charged on each payout, in cents: 200 means 2.00. Maximum 100000 (1,000.00).", + "example": 200 }, "payin_percentage_fee": { "type": "number", "minimum": 0, - "maximum": 1000 + "maximum": 9900, + "description": "Basis points charged on each payin: 100 means 1%. Maximum 9900 (99%).", + "example": 100 }, "payin_flat_fee": { "type": "number", "minimum": 0, - "maximum": 100000 + "maximum": 100000, + "description": "Flat fee charged on each payin, in cents: 200 means 2.00. Maximum 100000 (1,000.00).", + "example": 200 } }, "required": [ @@ -48281,7 +68503,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -48364,22 +68586,30 @@ "payout_percentage_fee": { "type": "number", "minimum": 0, - "maximum": 1000 + "maximum": 9900, + "description": "Basis points charged on each payout: 100 means 1%. Maximum 9900 (99%).", + "example": 100 }, "payout_flat_fee": { "type": "number", "minimum": 0, - "maximum": 100000 + "maximum": 100000, + "description": "Flat fee charged on each payout, in cents: 200 means 2.00. Maximum 100000 (1,000.00).", + "example": 200 }, "payin_percentage_fee": { "type": "number", "minimum": 0, - "maximum": 1000 + "maximum": 9900, + "description": "Basis points charged on each payin: 100 means 1%. Maximum 9900 (99%).", + "example": 100 }, "payin_flat_fee": { "type": "number", "minimum": 0, - "maximum": 100000 + "maximum": 100000, + "description": "Flat fee charged on each payin, in cents: 200 means 2.00. Maximum 100000 (1,000.00).", + "example": 200 } }, "required": [ @@ -48478,7 +68708,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -48572,22 +68802,30 @@ "payout_percentage_fee": { "type": "number", "minimum": 0, - "maximum": 1000 + "maximum": 9900, + "description": "Basis points charged on each payout: 100 means 1%. Maximum 9900 (99%).", + "example": 100 }, "payout_flat_fee": { "type": "number", "minimum": 0, - "maximum": 100000 + "maximum": 100000, + "description": "Flat fee charged on each payout, in cents: 200 means 2.00. Maximum 100000 (1,000.00).", + "example": 200 }, "payin_percentage_fee": { "type": "number", "minimum": 0, - "maximum": 1000 + "maximum": 9900, + "description": "Basis points charged on each payin: 100 means 1%. Maximum 9900 (99%).", + "example": 100 }, "payin_flat_fee": { "type": "number", "minimum": 0, - "maximum": 100000 + "maximum": 100000, + "description": "Flat fee charged on each payin, in cents: 200 means 2.00. Maximum 100000 (1,000.00).", + "example": 200 } }, "required": [ @@ -48672,6 +68910,29 @@ } } }, + "404": { + "description": "Possible error codes: `FEES_NOT_FOUND`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "FEES_NOT_FOUND": { + "summary": "FEES_NOT_FOUND", + "value": { + "success": false, + "code": "FEES_NOT_FOUND", + "message": "partner_fee_not_found", + "description": "The requested fee configuration was not found.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, "429": { "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", "content": { @@ -48685,7 +68946,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -48854,7 +69115,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -48893,6 +69154,7 @@ "/v1/upload": { "post": { "x-sdk": true, + "x-mcp": false, "tags": [ "Upload" ], @@ -49043,7 +69305,221 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, + "/v1/upload/analyze": { + "post": { + "x-sdk": true, + "x-mcp": false, + "tags": [ + "Upload" + ], + "summary": "Analyze Document", + "parameters": [ + { + "schema": { + "type": "string", + "description": "Instance ID. When provided, the request must be authenticated with an API key scoped to this instance. When omitted, a dashboard (Clerk) session is required." + }, + "required": false, + "name": "instance_id", + "in": "query" + } + ], + "requestBody": { + "description": "Document to read and analyze with AI", + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/UploadAnalyzeIn" + } + } + } + }, + "responses": { + "200": { + "description": "Document analyzed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UploadAnalyzeOut" + } + } + } + }, + "400": { + "description": "Possible error codes: `FILES_EMPTY`, `FILES_TOO_LARGE`, `FILES_TYPE_NOT_ALLOWED`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "FILES_EMPTY": { + "summary": "FILES_EMPTY", + "value": { + "success": false, + "code": "FILES_EMPTY", + "message": "file_empty", + "description": "The uploaded file is empty. Upload a valid file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TOO_LARGE": { + "summary": "FILES_TOO_LARGE", + "value": { + "success": false, + "code": "FILES_TOO_LARGE", + "message": "file_size_exceeded", + "description": "The file is too large. Upload a smaller file.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "FILES_TYPE_NOT_ALLOWED": { + "summary": "FILES_TYPE_NOT_ALLOWED", + "value": { + "success": false, + "code": "FILES_TYPE_NOT_ALLOWED", + "message": "file_type_not_allowed", + "description": "This file type is not allowed. Upload a supported file type.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "422": { + "description": "Possible error codes: `FILES_ANALYSIS_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "FILES_ANALYSIS_FAILED": { + "summary": "FILES_ANALYSIS_FAILED", + "value": { + "success": false, + "code": "FILES_ANALYSIS_FAILED", + "message": "analysis_failed", + "description": "The document could not be analyzed. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -49054,24 +69530,13 @@ } }, "500": { - "description": "Possible error codes: `FILES_UNREADABLE`, `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "examples": { - "FILES_UNREADABLE": { - "summary": "FILES_UNREADABLE", - "value": { - "success": false, - "code": "FILES_UNREADABLE", - "message": "file_download_failed", - "description": "We could not read the uploaded file. Check the file and try again.", - "errors": [], - "trace_id": "0af7651916cd43dd8448eb211c80319c" - } - }, "INTERNAL_ERROR": { "summary": "INTERNAL_ERROR", "value": { @@ -49086,17 +69551,42 @@ } } } + }, + "503": { + "description": "Possible error codes: `FILES_ANALYSIS_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "FILES_ANALYSIS_FAILED": { + "summary": "FILES_ANALYSIS_FAILED", + "value": { + "success": false, + "code": "FILES_ANALYSIS_FAILED", + "message": "analysis_failed", + "description": "The document could not be analyzed. Try again, and contact support if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } } } } }, - "/v1/upload/analyze": { + "/v1/upload/extract": { "post": { - "x-sdk": true, + "x-sdk": false, + "x-mcp": false, "tags": [ "Upload" ], - "summary": "Analyze Document", + "summary": "Extract Invoice", + "description": "Reads a supplier invoice and returns the fields needed to register it as an invoice payable: amount, currency, due date, vendor, line items and the payment options printed on it. Every field is nullable and nothing is guessed; numbers that fail format validation come back null. The result prefills a form, it is not a payable. Limited to 60 requests per minute per instance.", "parameters": [ { "schema": { @@ -49109,22 +69599,22 @@ } ], "requestBody": { - "description": "Document to read and analyze with AI", + "description": "Invoice to read with AI", "content": { "multipart/form-data": { "schema": { - "$ref": "#/components/schemas/UploadAnalyzeIn" + "$ref": "#/components/schemas/UploadExtractIn" } } } }, "responses": { "200": { - "description": "Document analyzed successfully", + "description": "Fields read from the invoice", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UploadAnalyzeOut" + "$ref": "#/components/schemas/UploadExtractOut" } } } @@ -49267,7 +69757,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -49326,6 +69816,174 @@ } } }, + "/v1/presign": { + "post": { + "x-sdk": true, + "tags": [ + "Upload" + ], + "summary": "Presign File URL", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "instance_id", + "in": "query" + } + ], + "requestBody": { + "description": "The BlindPay file URL to presign", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PresignIn" + } + } + } + }, + "responses": { + "200": { + "description": "Returns a signed URL for the file, valid for 1 hour", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PresignOut" + } + } + } + }, + "400": { + "description": "Possible error codes: `FILES_URL_INVALID`, `VALIDATION_FAILED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "FILES_URL_INVALID": { + "summary": "FILES_URL_INVALID", + "value": { + "success": false, + "code": "FILES_URL_INVALID", + "message": "file_url_invalid", + "description": "The file_url is not a BlindPay file URL. Pass the file_url returned by POST /upload.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + }, + "VALIDATION_FAILED": { + "summary": "VALIDATION_FAILED", + "value": { + "success": false, + "code": "VALIDATION_FAILED", + "message": "validation_failed", + "description": "The request contains invalid fields. Check the errors list for details.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "401": { + "description": "Possible error codes: `AUTH_UNAUTHORIZED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_UNAUTHORIZED": { + "summary": "AUTH_UNAUTHORIZED", + "value": { + "success": false, + "code": "AUTH_UNAUTHORIZED", + "message": "unauthorized", + "description": "Authentication failed. Check your API key or session and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "403": { + "description": "Possible error codes: `AUTH_FORBIDDEN`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_FORBIDDEN": { + "summary": "AUTH_FORBIDDEN", + "value": { + "success": false, + "code": "AUTH_FORBIDDEN", + "message": "user_not_allowed", + "description": "You do not have permission to perform this action.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "429": { + "description": "Possible error codes: `AUTH_RATE_LIMITED`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "AUTH_RATE_LIMITED": { + "summary": "AUTH_RATE_LIMITED", + "value": { + "success": false, + "code": "AUTH_RATE_LIMITED", + "message": "card_payment_rate_limit_exceeded", + "description": "Too many requests. Wait a moment and try again.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + }, + "500": { + "description": "Possible error codes: `INTERNAL_ERROR`. See the Error responses section for retry semantics.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + }, + "examples": { + "INTERNAL_ERROR": { + "summary": "INTERNAL_ERROR", + "value": { + "success": false, + "code": "INTERNAL_ERROR", + "message": "internal_error", + "description": "Something went wrong on our side. Try again, and contact support with the trace ID if the problem persists.", + "errors": [], + "trace_id": "0af7651916cd43dd8448eb211c80319c" + } + } + } + } + } + } + } + } + }, "/v1/available/bank-details": { "get": { "x-sdk": true, @@ -49333,6 +69991,7 @@ "Available" ], "summary": "Bank Details", + "description": "Returns the fields a bank account needs for a payout rail, so a recipient form can collect and validate them before calling create bank account. Each field has a `label`, the request body `key` to send it under, a validation `regex`, and, where the value comes from a fixed list (banks, countries, account types), the allowed `items`. Get valid `rail` values from `GET /v1/available/rails`. Public: no API key required.", "security": [], "parameters": [ { @@ -49349,7 +70008,8 @@ "ach_cop_bitso", "international_swift", "rtp", - "sepa" + "sepa", + "faster_payments" ] }, "required": true, @@ -49450,7 +70110,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -49493,6 +70153,7 @@ "Available" ], "summary": "Rails", + "description": "Lists every payout rail BlindPay supports (ACH, domestic wire, RTP, PIX, SPEI, SEPA, SWIFT, and more) as `{ label, value, country }`. Pass `value` as the `rail` query parameter of `GET /v1/available/bank-details`, and as the `type` when creating a bank account. `country` is an ISO 3166-1 alpha-2 flag hint for display, not a statement of coverage. Public: no API key required.", "security": [], "responses": { "200": { @@ -49587,7 +70248,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -49724,7 +70385,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -49884,7 +70545,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -50090,7 +70751,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -50355,7 +71016,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -50540,7 +71201,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -50735,7 +71396,7 @@ "value": { "success": false, "code": "AUTH_RATE_LIMITED", - "message": "api_key_rate_limit_exceeded", + "message": "card_payment_rate_limit_exceeded", "description": "Too many requests. Wait a moment and try again.", "errors": [], "trace_id": "0af7651916cd43dd8448eb211c80319c" @@ -50792,6 +71453,25 @@ } } }, + "blockchainWallet.update": { + "post": { + "requestBody": { + "description": "Self-custody answer saved for a blockchain wallet", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BlockchainWalletUpdateWebhookOut" + } + } + } + }, + "responses": { + "200": { + "description": "Blockchain wallet updated" + } + } + } + }, "blockchainWallet.new": { "post": { "requestBody": { @@ -50980,6 +71660,63 @@ } } }, + "payable.complete": { + "post": { + "requestBody": { + "description": "The payout executing the payable completed and the bill is paid", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PayableCompleteWebhookOut" + } + } + } + }, + "responses": { + "200": { + "description": "Payable paid" + } + } + } + }, + "payable.new": { + "post": { + "requestBody": { + "description": "Payable registered as a draft, ready to be paid through a payout quote", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PayableNewWebhookOut" + } + } + } + }, + "responses": { + "200": { + "description": "Payable registered" + } + } + } + }, + "payable.update": { + "post": { + "requestBody": { + "description": "The bill changed: a payout claimed it (processing), the attempt failed or was refunded (back to draft, payable again), or a draft was deleted (canceled). The executing payout emits its own payout.* events for hold, release and failure detail", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PayableUpdateWebhookOut" + } + } + } + }, + "responses": { + "200": { + "description": "Payable updated" + } + } + } + }, "payout.new": { "post": { "requestBody": { @@ -51082,7 +71819,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateTransferOut" + "$ref": "#/components/schemas/TransferNewWebhookOut" } } } @@ -51101,7 +71838,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateTransferOut" + "$ref": "#/components/schemas/TransferCompleteWebhookOut" } } } @@ -51120,7 +71857,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateTransferOut" + "$ref": "#/components/schemas/TransferUpdateWebhookOut" } } } @@ -51139,7 +71876,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VirtualAccountOut" + "$ref": "#/components/schemas/VirtualAccountNewWebhookOut" } } } @@ -51158,7 +71895,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VirtualAccountOut" + "$ref": "#/components/schemas/VirtualAccountCompleteWebhookOut" } } } @@ -51177,7 +71914,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WalletInboundSchemaOut" + "$ref": "#/components/schemas/WalletInboundWebhookOut" } } } @@ -51189,6 +71926,25 @@ } } }, + "wallet.update": { + "post": { + "requestBody": { + "description": "Wallet yield status changed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WalletUpdateWebhookOut" + } + } + } + }, + "responses": { + "200": { + "description": "Wallet updated" + } + } + } + }, "wallet.new": { "post": { "requestBody": { @@ -51196,7 +71952,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WalletOut" + "$ref": "#/components/schemas/WalletNewWebhookOut" } } } diff --git a/.api-sync/unmodeled.json b/.api-sync/unmodeled.json index 766e1d4..898b13f 100644 --- a/.api-sync/unmodeled.json +++ b/.api-sync/unmodeled.json @@ -2,579 +2,73 @@ "properties": [ { "kind": "property", - "schema": "AvailableBankDetails", - "field": "requiredWhen", - "reason": "Conditional-requirement metadata (field/operator/values, describing when a bank-detail-form field becomes required) added to each AvailableBankDetails item; GetBankDetailsResponse does not model it.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "BankAccountOut", - "field": "swift_ifsc_branch_code", - "reason": "See CreateBankAccountIn.swift_ifsc_branch_code: same new field missing on the response side (GetBankAccountResponse/ListBankAccountsResponse/CreateInternationalSwiftResponse).", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreateBankAccountIn", - "field": "checkbook_account_id", - "reason": "Provider-internal account handle (Checkbook integration) present on the bank-account create schema; not settable through any of the 11 rail create input types, consistent with the existing aiprise_validation_key-style internal-field pattern already allow-listed elsewhere.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreateBankAccountIn", - "field": "checkbook_user_key", - "reason": "See CreateBankAccountIn.checkbook_account_id (same Checkbook-provider internal field).", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreateBankAccountIn", - "field": "force_cpf_cnpj", - "reason": "New PIX-key CPF/CNPJ validation override flag; not modeled on CreatePixInput.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreateBankAccountIn", - "field": "onemoney_external_account_id", - "reason": "Provider-internal account handle (OneMoney integration); same pattern as checkbook_account_id.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreateBankAccountIn", - "field": "status", - "reason": "Bank-account status is present on the shared create schema (likely a server-computed/back-office field, not client-settable) but not modeled on any of the 11 rail create input types; needs confirmation of intended write access before modeling.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreateBankAccountIn", - "field": "swift_ifsc_branch_code", - "reason": "IFSC branch code (Indian bank routing) added alongside the existing SWIFT fields; not modeled on CreateInternationalSwiftInput.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreateBankAccountIn", - "field": "type", - "reason": "Discriminator field injected by the factory function body (bank-accounts/index.ts:508-610: `{ type: \"pix\", ...data }` etc.), never carried on any of the 11 rail create input types by design.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreateBlockchainWalletIn", - "field": "is_account_abstraction", - "reason": "Discriminator field injected by the factory function body (blockchain.ts:109-136: createWithAddress sets true, createWithHash sets false), never carried on either input type by design.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreateCustomerIn", - "field": "additional_info", - "reason": "See CustomerOut.additional_info: same new field, not modeled on any of the 3 KYC/KYB input types.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreateCustomerIn", - "field": "kyc_type", - "reason": "Discriminator field injected by the factory function body (customers/index.ts:521-547: `{ kyc_type: \"standard\"|\"enhanced\", ...data }`), never carried on any of the 3 KYC/KYB input types by design.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreateCustomerIn", - "field": "latitude", - "reason": "See CustomerOut.latitude: same new field, not modeled on any of the 3 KYC/KYB input types.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreateCustomerIn", - "field": "longitude", - "reason": "See CreateCustomerIn.latitude.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreateCustomerIn", - "field": "type", - "reason": "Discriminator field injected by the factory function body (customers/index.ts:521-547: `{ type: \"individual\"|\"business\", ...data }`), never carried on any of the 3 KYC/KYB input types by design.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreatePayinIn", - "field": "payin_quote_id", - "reason": "CreateEvmPayinInput (payins/index.ts) is `= string`, a bare scalar alias for the value the factory sends as {payin_quote_id}, not an object literal; there is no key to mechanically add a field to. Verified by reading the factory: createEvm(payin_quote_id) posts exactly {payin_quote_id}, matching this schema's one property.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreatePayinOut", - "field": "billing_fee_amount", - "reason": "billing_fee_amount is not in CreateEvmPayinResponse's Pick list and has no inline fallback; only the legacy billing_fee field is carried.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreatePayinOut", - "field": "partner_fee", - "reason": "Same partner_fee/transaction_fee_amount/billing_fee_amount gaps as PayinOut (CreateEvmPayinResponse Picks its shared fields from Payin, which does not have them either).", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreatePayinOut", - "field": "transaction_fee_amount", - "reason": "See CreatePayinOut.partner_fee.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreatePayinQuoteOut", - "field": "billing_fee_amount", - "reason": "New computed billing-fee-in-cents field added to CreatePayinQuoteOut; CreatePayinQuoteResponse does not model it (mirrors the same gap on CreateQuoteResponse/QuoteOut).", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CustomerOut", - "field": "additional_info", - "reason": "Extra-documents/notes attachment list (label+value+AdditionalInfoItem) added to CustomerOut; not modeled on any of the 3 KYC/KYB response types.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CustomerOut", - "field": "business_type", - "reason": "CreateBusinessWithStandardKYBInput accepts business_type on create, but BusinessWithStandardKYB (the response type) never surfaces it back; a response-side-only gap.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CustomerOut", - "field": "customer_id", - "reason": "CustomerOut carries both `id` and a separate `customer_id` (the wave-2 rename's canonical identifier); none of the 3 KYC/KYB response types expose `customer_id`, only `id`.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CustomerOut", - "field": "latitude", - "reason": "Optional geolocation pair added to CustomerOut (forwarded to the identity/fraud providers); not modeled on any of the 3 KYC/KYB response types.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CustomerOut", - "field": "longitude", - "reason": "See CustomerOut.latitude.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "Error", - "field": "code", - "reason": "This SDK's error envelope (ErrorResponse) only ever surfaces `message`, the legacy machine string. It does not expose the newer stable `code` the spec explicitly recommends building programmatic handling on.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "Error", - "field": "description", - "reason": "See Error.code: human-readable, safe-to-display explanation, not modeled.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "Error", - "field": "errors", - "reason": "See Error.code: structured per-field validation error list, not modeled.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "Error", - "field": "success", - "reason": "See Error.code: the {success: false} discriminator flag on the error envelope, not modeled (this SDK signals an error by BlindpayApiResponse.error being non-null instead).", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "Error", - "field": "trace_id", - "reason": "See Error.code: request trace ID for support correlation, not modeled.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "GetFeesOut", - "field": "sepa", - "reason": "SEPA fee tier added alongside the other rail fee tiers; GetFeesResponse does not model it (consistent with the SDK-wide SEPA gaps: Rail enum and CreateBankAccountIn/BankAccountOut swift_ifsc_branch_code notwithstanding, SEPA itself is only partially wired).", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayinOut", - "field": "approved_risk_sources", - "reason": "See tracking_payment.review_source: same pending PR.", - "owner": "eric@blindpay.com", - "property": "tracking_payment" - }, - { - "kind": "property", - "schema": "PayinOut", - "field": "end_to_end_id", - "reason": "Payin tracking_transaction gained 6 fields (end_to_end_id, provider_name, provider_transaction_id, sender_bank_name, ted_instruction, transaction_hash) that PayinTrackingTransaction does not model; same class of gap as tracking_payment, needs its own reviewed pass.", - "owner": "eric@blindpay.com", - "property": "tracking_transaction" - }, - { - "kind": "property", - "schema": "PayinOut", - "field": "manual_concluded_at", - "reason": "Manual OTC-liquidity execution tracking (manual_execution_status plus its concluded_at/concluded_by pair) added to PayinOut; not modeled on Payin.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayinOut", - "field": "manual_concluded_by", - "reason": "See manual_concluded_at.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayinOut", - "field": "manual_execution_status", - "reason": "See manual_concluded_at.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayinOut", - "field": "partner_fee", - "reason": "New computed partner-fee-in-cents field (distinct from partner_fee_amount) added to PayinOut; not modeled on Payin.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayinOut", - "field": "provider_name", - "reason": "See tracking_transaction.end_to_end_id: same pending gap.", - "owner": "eric@blindpay.com", - "property": "tracking_transaction" - }, - { - "kind": "property", - "schema": "PayinOut", - "field": "provider_transaction_id", - "reason": "See tracking_transaction.end_to_end_id: same pending gap.", - "owner": "eric@blindpay.com", - "property": "tracking_transaction" - }, - { - "kind": "property", - "schema": "PayinOut", - "field": "review_context", - "reason": "See tracking_payment.review_source: same pending PR.", - "owner": "eric@blindpay.com", - "property": "tracking_payment" - }, - { - "kind": "property", - "schema": "PayinOut", - "field": "review_source", - "reason": "Manual-review risk-context fields added to the payin tracking_payment step (review_source, review_context, approved_risk_sources); this SDK's PayinTrackingPayment models only step/provider_name/completed_at. Additive, needs its own reviewed PR alongside the payout tracking_payment expansion above.", - "owner": "eric@blindpay.com", - "property": "tracking_payment" - }, - { - "kind": "property", - "schema": "PayinOut", - "field": "sender_bank_name", - "reason": "See tracking_transaction.end_to_end_id: same pending gap.", - "owner": "eric@blindpay.com", - "property": "tracking_transaction" - }, - { - "kind": "property", - "schema": "PayinOut", - "field": "ted_instruction", - "reason": "See tracking_transaction.end_to_end_id: same pending gap (a Brazilian TED-rail instruction sub-object, mirroring pse_instruction/transfers_instruction which are already modeled).", - "owner": "eric@blindpay.com", - "property": "tracking_transaction" - }, - { - "kind": "property", - "schema": "PayinOut", - "field": "transaction_fee_amount", - "reason": "See PayinOut.partner_fee: added alongside it, not modeled.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayinOut", - "field": "transaction_hash", - "reason": "See tracking_transaction.end_to_end_id: same pending gap.", - "owner": "eric@blindpay.com", - "property": "tracking_transaction" - }, - { - "kind": "property", - "schema": "PayoutOnEvmOut", - "field": "bank_account_id", - "reason": "PayoutOnEvmOut (the shared create-payout response for evm/solana/stellar) carries several fields Payout itself is also missing (see PayoutOut.partner_fee, .tracking_documents, .transaction_fee_amount); bank_account_id and offramp_wallet_id are additionally new here and not modeled on any of CreateStellarPayoutResponse/CreateEvmPayoutResponse/CreateSolanaPayoutResponse.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayoutOnEvmOut", - "field": "billing_fee_amount", - "reason": "See PayoutOut: same field missing on the create-response types too.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayoutOnEvmOut", - "field": "offramp_wallet_id", - "reason": "See PayoutOnEvmOut.bank_account_id.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayoutOnEvmOut", - "field": "partner_fee", - "reason": "See PayoutOut.partner_fee: same field missing on the create-response types too.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayoutOnEvmOut", - "field": "tracking_documents", - "reason": "See PayoutOut.tracking_documents: same new tracking step missing on the create-response types too.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayoutOnEvmOut", - "field": "transaction_fee_amount", - "reason": "See PayoutOut.transaction_fee_amount: same field missing on the create-response types too.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "coelsa_id", - "reason": "SDK's shared tracking-payment type models a 12 of 20 field subset of the payout tracking_payment object (this SDK already models the 6 recipient_* fields plus provider_name/provider_transaction_id/provider_status/estimated_time_of_arrival/completed_at); exposing the remaining 8 payout-only fields (coelsa_id, end_to_end_id, provider_clearing_system, provider_error_reason, provider_imad, provider_integration, provider_reference, provider_uetr) is a deliberate additive change that needs one reviewed PR across all SDKs, not a blind per-field add.", - "owner": "eric@blindpay.com", - "property": "tracking_payment" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "end_to_end_id", - "reason": "See tracking_payment.coelsa_id: same pending cross-SDK PR.", - "owner": "eric@blindpay.com", - "property": "tracking_payment" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "ledger_in_transaction_id", - "reason": "Payout tracking_transaction gained 4 ledger/provider fields (ledger_in_transaction_id, ledger_out_transaction_id, provider_error_reason, provider_transaction_id) that PayoutTrackingTransaction does not model.", - "owner": "eric@blindpay.com", - "property": "tracking_transaction" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "ledger_out_transaction_id", - "reason": "See tracking_transaction.ledger_in_transaction_id: same pending gap.", - "owner": "eric@blindpay.com", - "property": "tracking_transaction" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "partner_fee", - "reason": "New computed partner-fee-in-cents field (distinct from the existing partner_fee_amount) added alongside billing_fee_amount/transaction_fee_amount; none of the three are modeled on Payout.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "pix_safe_bank_code", - "reason": "PIX SAFE rail fields present on the shared PayoutOut/BankAccountOut shape but never copied onto Payout (whose bank-account fields are otherwise a near-complete flattening of BankAccountOut).", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "pix_safe_branch_code", - "reason": "See pix_safe_bank_code.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "pix_safe_cpf_cnpj", - "reason": "See pix_safe_bank_code.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "provider_clearing_system", - "reason": "See tracking_payment.coelsa_id: same pending cross-SDK PR.", - "owner": "eric@blindpay.com", - "property": "tracking_payment" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "provider_error_reason", - "reason": "See tracking_payment.coelsa_id: same pending cross-SDK PR.", - "owner": "eric@blindpay.com", - "property": "tracking_payment" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "provider_error_reason", - "reason": "See tracking_transaction.ledger_in_transaction_id: same pending gap.", - "owner": "eric@blindpay.com", - "property": "tracking_transaction" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "provider_imad", - "reason": "See tracking_payment.coelsa_id: same pending cross-SDK PR.", - "owner": "eric@blindpay.com", - "property": "tracking_payment" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "provider_integration", - "reason": "See tracking_payment.coelsa_id: same pending cross-SDK PR.", - "owner": "eric@blindpay.com", - "property": "tracking_payment" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "provider_reference", - "reason": "See tracking_payment.coelsa_id: same pending cross-SDK PR.", - "owner": "eric@blindpay.com", - "property": "tracking_payment" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "provider_transaction_id", - "reason": "See tracking_transaction.ledger_in_transaction_id: same pending gap.", - "owner": "eric@blindpay.com", - "property": "tracking_transaction" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "provider_transaction_id", - "reason": "Payout tracking_complete gained a refund-tracking pair (provider_transaction_id for the refund transaction, refund_reason) that PayoutTrackingComplete does not model.", - "owner": "eric@blindpay.com", - "property": "tracking_complete" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "provider_uetr", - "reason": "See tracking_payment.coelsa_id: same pending cross-SDK PR.", - "owner": "eric@blindpay.com", - "property": "tracking_payment" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "refund_reason", - "reason": "See tracking_complete.provider_transaction_id: same pending gap.", - "owner": "eric@blindpay.com", - "property": "tracking_complete" - }, - { - "kind": "property", - "schema": "PayoutOut", - "field": "sender_legal_name", - "reason": "New field (legal name of the sending instance, shown on the receipt) not modeled on Payout.", + "schema": "CreateBankAccountIn", + "field": "checkbook_account_id", + "reason": "Provider-internal account handle (Checkbook integration) present on the bank-account create schema; not settable through any of the 11 rail create input types, consistent with the existing aiprise_validation_key-style internal-field pattern already allow-listed elsewhere.", "owner": "eric@blindpay.com" }, { "kind": "property", - "schema": "PayoutOut", - "field": "tracking_documents", - "reason": "Entire new tracking step (step, completed_at, reviewed_by, status) added for international-wire document review; not modeled at all on Payout, or on the create-response types (PayoutOnEvmOut). Needs a new shared PayoutTrackingDocuments type plus wiring into Payout/CreateStellarPayoutResponse/CreateEvmPayoutResponse/CreateSolanaPayoutResponse.", + "schema": "CreateBankAccountIn", + "field": "checkbook_user_key", + "reason": "See CreateBankAccountIn.checkbook_account_id (same Checkbook-provider internal field).", "owner": "eric@blindpay.com" }, { "kind": "property", - "schema": "PayoutOut", - "field": "transaction_fee_amount", - "reason": "See partner_fee: added alongside it, not modeled.", + "schema": "CreateBankAccountIn", + "field": "onemoney_external_account_id", + "reason": "Provider-internal account handle (OneMoney integration); same pattern as checkbook_account_id.", "owner": "eric@blindpay.com" }, { "kind": "property", - "schema": "QuoteOut", - "field": "billing_fee_amount", - "reason": "New computed billing-fee-in-cents field added to QuoteOut; CreateQuoteResponse does not model it.", + "schema": "CreateBankAccountIn", + "field": "status", + "reason": "Bank-account status is present on the shared create schema (likely a server-computed/back-office field, not client-settable) but not modeled on any of the 11 rail create input types; needs confirmation of intended write access before modeling.", "owner": "eric@blindpay.com" }, { "kind": "property", - "schema": "TransferOut", - "field": "external_id", - "reason": "New pass-through external_id field added to TransferOut; Transfer does not model it.", + "schema": "CreateBankAccountIn", + "field": "type", + "reason": "Discriminator field injected by the factory function body (bank-accounts/index.ts:508-610: `{ type: \"pix\", ...data }` etc.), never carried on any of the 11 rail create input types by design.", "owner": "eric@blindpay.com" }, { "kind": "property", - "schema": "UpdateCustomerIn", - "field": "additional_info", - "reason": "See CustomerOut.additional_info: same new field, not modeled on UpdateCustomerInput.", + "schema": "CreateBlockchainWalletIn", + "field": "is_account_abstraction", + "reason": "Discriminator field injected by the factory function body (blockchain.ts:109-136: createWithAddress sets true, createWithHash sets false), never carried on either input type by design.", "owner": "eric@blindpay.com" }, { "kind": "property", - "schema": "UpdateCustomerIn", - "field": "latitude", - "reason": "See CustomerOut.latitude: same new field, not modeled on UpdateCustomerInput.", + "schema": "CreateCustomerIn", + "field": "kyc_type", + "reason": "Discriminator field injected by the factory function body (customers/index.ts:521-547: `{ kyc_type: \"standard\"|\"enhanced\", ...data }`), never carried on any of the 3 KYC/KYB input types by design.", "owner": "eric@blindpay.com" }, { "kind": "property", - "schema": "UpdateCustomerIn", - "field": "longitude", - "reason": "See UpdateCustomerIn.latitude.", + "schema": "CreateCustomerIn", + "field": "type", + "reason": "Discriminator field injected by the factory function body (customers/index.ts:521-547: `{ type: \"individual\"|\"business\", ...data }`), never carried on any of the 3 KYC/KYB input types by design.", "owner": "eric@blindpay.com" }, { "kind": "property", - "schema": "UpdateInstanceIn", - "field": "compliance_emails", - "reason": "New instance-level RFI notification settings (an email allow-list plus a toggle) added to UpdateInstanceIn; UpdateInstanceInput does not model either.", + "schema": "CreatePayinIn", + "field": "payin_quote_id", + "reason": "CreateEvmPayinInput (payins/index.ts) is `= string`, a bare scalar alias for the value the factory sends as {payin_quote_id}, not an object literal; there is no key to mechanically add a field to. Verified by reading the factory: createEvm(payin_quote_id) posts exactly {payin_quote_id}, matching this schema's one property.", "owner": "eric@blindpay.com" }, { "kind": "property", - "schema": "UpdateInstanceIn", - "field": "customer_rfi_emails_enabled", - "reason": "See UpdateInstanceIn.compliance_emails.", - "owner": "eric@blindpay.com" + "schema": "Error", + "field": "success", + "reason": "The error envelope's `success: false` flag is not copied onto ErrorResponse: BlindpayApiResponse already discriminates with `data: null` / `error`, so it would only restate that.", + "owner": "thayto@blindpay.com" }, { "kind": "property", @@ -582,79 +76,9 @@ "field": "user_role", "reason": "instances/index.ts:60-65 renames the SDK's `role` field to the wire body key `user_role` inside the factory function; the input type itself is named `role`, not `user_role`. Sibling quirk to the already allow-listed UpdateInstanceMemberRoleInput.memberId path-param entry.", "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "VirtualAccountOut", - "field": "customer_id", - "reason": "New field added to VirtualAccountOut; VirtualAccount (virtual-accounts/index.ts) does not model it, even though the surrounding customer-scoped resource already threads customer_id through the URL.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "get /v1/instances/{id}/members", - "field": "has_passkey", - "reason": "Per-member passkey-enrollment flag added; GetInstanceMembersResponse (instances/index.ts) does not model it.", - "owner": "eric@blindpay.com" } ], "knownDivergences": [ - { - "kind": "enum", - "schema": "AvailableBankDetails", - "enumProperty": "[].key", - "reason": "Spec's available-bank-details key enum has grown to 73 values; this SDK's BankDetailKey union models 48 and is missing 24 (business_industry, date_of_birth, force_cpf_cnpj, onemoney_external_account_id, phone_number, pix_safe_bank_code, pix_safe_branch_code, pix_safe_cpf_cnpj, recipient_relationship, sepa_beneficiary_address_line_1, sepa_beneficiary_address_line_2, sepa_beneficiary_bic, sepa_beneficiary_city, sepa_beneficiary_country, sepa_beneficiary_legal_name, sepa_beneficiary_postal_code, sepa_beneficiary_state_province_region, sepa_iban, status, swift_ifsc_branch_code, swift_payment_code, tax_id, ted_bank_code, ted_branch_code, ted_cpf_cnpj). This is a purely descriptive/display enum (used to label dynamic bank-detail form fields), so the gap is cosmetic rather than a functional block, but is substantial enough to need one reviewed pass rather than a blind append.", - "owner": "eric@blindpay.com" - }, - { - "kind": "type-mismatch", - "schema": "AvailableRails", - "field": "country", - "reason": "GetRailsResponse declares country as a bare string; the spec constrains it to the full ISO country-code enum (same list as the shared Country type). Read-only informational endpoint (GET /available/rails); a modeling gap, not a functional one.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "BankAccountOut", - "field": "bank_name", - "reason": "Pre-existing SDK-only field on GetBankAccountResponse with no matching property on BankAccountOut in the spec (same family as the already allow-listed account_holder_name/swift_code/is_primary/iban).", - "owner": "eric@blindpay.com" - }, - { - "kind": "type-mismatch", - "schema": "BankAccountOut", - "field": "business_industry", - "reason": "ListBankAccountsResponse's inline array-item literal declares business_industry as a bare `string | null`; every create*Input type in the same file (CreateAchInput, CreateWireInput, CreateInternationalSwiftInput, CreateRtpInput) correctly types the same field as the shared BusinessIndustry union. The list endpoint's response type alone was never brought in line.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "BankAccountOut", - "field": "customer_id", - "reason": "Pre-existing SDK-only field on GetBankAccountResponse with no matching property on BankAccountOut in the spec; same family as bank_name.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "BankAccountOut", - "field": "offramp_wallets.[].circle_wallet_id", - "reason": "ListBankAccountsResponse's inline offramp_wallets literal (bank-accounts/index.ts:88-93) models {address,id,network,external_id} but spec's BankAccountOut.offramp_wallets item also carries circle_wallet_id; a narrower, independently-named SDK symbol would be needed to track this sub-shape mechanically.", - "owner": "eric@blindpay.com" - }, - { - "kind": "type-mismatch", - "schema": "BankAccountOut", - "field": "spei_protocol", - "reason": "ListBankAccountsResponse's inline array-item literal declares spei_protocol as a bare `string`; CreateSpeiResponse in the same file correctly types it as SpeiProtocol. The list endpoint's response type alone was never brought in line.", - "owner": "eric@blindpay.com" - }, - { - "kind": "type-mismatch", - "schema": "BankAccountOut", - "field": "status", - "reason": "ListBankAccountsResponse's inline array-item literal declares status as a bare `string | null`; spec constrains it to a 4-value approval-status enum (verifying, approved, rejected, deprecated). Never modeled as a named SDK type at all.", - "owner": "eric@blindpay.com" - }, { "kind": "type-mismatch", "schema": "BankAccountOut", @@ -662,13 +86,6 @@ "reason": "CreateInternationalSwiftResponse and ListBankAccountsResponse both declare swift_payment_code as a bare `string | null`; spec constrains it to a large country-specific SWIFT purpose-code enum (hundreds of values, e.g. ae_swift_str, jp_swift_101). Given the size, a named SDK union is likely the wrong shape for this field regardless; flagged for a human modeling decision, not a blind enum type.", "owner": "eric@blindpay.com" }, - { - "kind": "property", - "schema": "BankAccountOut", - "field": "updated_at", - "reason": "Pre-existing SDK-only field on GetBankAccountResponse with no matching property on BankAccountOut in the spec; same family as bank_name.", - "owner": "eric@blindpay.com" - }, { "kind": "type-mismatch", "schema": "CreateBankAccountIn", @@ -690,34 +107,6 @@ "reason": "Pre-existing SDK-only field on all 3 create KYC/KYB input types with no matching property on CreateCustomerIn in the spec.", "owner": "eric@blindpay.com" }, - { - "kind": "property", - "schema": "CreatePartnerFeeInput", - "field": "evm_wallet_address", - "reason": "Already tracked in .api-sync/contract-check-allowlist.json; mirrored here so this repo's own reconciliation state does not depend on that file staying in sync.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreatePartnerFeeInput", - "field": "stellar_wallet_address", - "reason": "See CreatePartnerFeeInput.evm_wallet_address.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreatePartnerFeeResponse", - "field": "evm_wallet_address", - "reason": "See CreatePartnerFeeInput.evm_wallet_address.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "CreatePartnerFeeResponse", - "field": "stellar_wallet_address", - "reason": "See CreatePartnerFeeInput.evm_wallet_address.", - "owner": "eric@blindpay.com" - }, { "kind": "property", "schema": "CreatePayinOut", @@ -732,21 +121,6 @@ "reason": "Already tracked in .api-sync/contract-check-allowlist.json as CreateTransferResponse.tracking_partner_fee; mirrored here.", "owner": "eric@blindpay.com" }, - { - "kind": "enum", - "schema": "CustomerLimitIncreaseIn", - "enumProperty": "supporting_document_type", - "reason": "Spec's supporting_document_type enum has grown to 15 values; this SDK's LimitIncreaseRequestSupportingDocumentType models 6 and is missing 9 (business_accounts_receivable, business_contract, business_merchant_processor_statement, business_shareholder_loan, individual_blockchain_wallet_statement, individual_crypto_exchange_statement, individual_employment_letter, individual_investment_statement, individual_pay_stub).", - "owner": "eric@blindpay.com" - }, - { - "kind": "enum", - "schema": "CustomerOut", - "enumProperty": "kyc_status", - "reason": "Spec's kyc_status has 8 values (verifying, approved, rejected, deprecated, pending_review, awaiting_contract, compliance_request, approved_rfi); this SDK's KycStatus models 7, missing approved_rfi. approved_rfi is reached only through the RFI resource, which this SDK does not implement (see ignore.schemas); adding the enum member without the resource would be misleading.", - "owner": "eric@blindpay.com", - "member": "approved_rfi" - }, { "kind": "property", "schema": "CustomerOut", @@ -761,41 +135,6 @@ "reason": "Pre-existing SDK-only field on all 3 KYC/KYB response types with no matching property on CustomerOut in the spec.", "owner": "eric@blindpay.com" }, - { - "kind": "type-mismatch", - "schema": "CustomerOut", - "field": "source_of_funds_doc_type", - "reason": "IndividualWithEnhancedKYC declares source_of_funds_doc_type as a bare `string`; the other 2 KYC/KYB response types (IndividualWithStandardKYC, BusinessWithStandardKYB) correctly type the same field as `SourceOfFundsDocType | null`. Only the enhanced-KYC variant was never brought in line.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "GetPartnerFeeResponse", - "field": "evm_wallet_address", - "reason": "See CreatePartnerFeeInput.evm_wallet_address.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "GetPartnerFeeResponse", - "field": "stellar_wallet_address", - "reason": "See CreatePartnerFeeInput.evm_wallet_address.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "ListPartnerFeesResponse", - "field": "evm_wallet_address", - "reason": "See CreatePartnerFeeInput.evm_wallet_address.", - "owner": "eric@blindpay.com" - }, - { - "kind": "property", - "schema": "ListPartnerFeesResponse", - "field": "stellar_wallet_address", - "reason": "See CreatePartnerFeeInput.evm_wallet_address.", - "owner": "eric@blindpay.com" - }, { "kind": "property", "schema": "PayinOut", @@ -819,10 +158,10 @@ }, { "kind": "type-mismatch", - "schema": "PayoutOut", - "field": "ach_cop_document_type", - "reason": "Payout declares ach_cop_document_type as a bare `string`; BankAccountOut's own create*Input/Response types (CreateColombiaAchInput/Response) correctly type the same field as AchCopDocument. Only the flattened Payout type was never brought in line.", - "owner": "eric@blindpay.com" + "schema": "PayinOut", + "field": "provider_name", + "reason": "Nested at tracking_transaction.provider_name. The same kind of bank/provider display-label list as PayoutOut.tracking_payment.provider_name (\"Stark Bank\", \"JPMorgan Chase\" and \"JP Morgan Chase\" side by side) that grows with every banking partner, so it stays a bare `string | null` like the payout one.", + "owner": "thayto@blindpay.com" }, { "kind": "type-mismatch", @@ -838,14 +177,6 @@ "reason": "Already tracked in .api-sync/contract-check-allowlist.json (no longer exists on any Payout schema in the spec); mirrored here.", "owner": "eric@blindpay.com" }, - { - "kind": "enum", - "schema": "PayoutOut", - "enumProperty": "tracking_payment.estimated_time_of_arrival", - "reason": "Spec's EstimatedTimeOfArrival gained a 7th value, 5_30_min, between 5_min and 30_min; this SDK's EstimatedTimeOfArrival union still has the original 6. Bootstrap note: this enum is declared with single quotes (unlike most others in this codebase), which is exactly why it slipped past this project's own first bootstrap pass; fixed before committing.", - "owner": "eric@blindpay.com", - "member": "5_30_min" - }, { "kind": "property", "schema": "TransferOut", @@ -853,13 +184,6 @@ "reason": "Already tracked in .api-sync/contract-check-allowlist.json (no longer exists on TransferOut in the spec); mirrored here.", "owner": "eric@blindpay.com" }, - { - "kind": "enum", - "schema": "UpdateCustomerIn", - "enumProperty": "business_industry", - "reason": "Spec's business_industry NAICS enum added code 446120 (this SDK is missing it) and does not include this SDK's non-NAICS crypto/web3 business categories (dapp, exchange, gambling, gaming, infra, marketplace, neo_bank, other, saas, social, wallet), which appear to be a deliberate SDK-side addition for wallet/exchange-type instances rather than spec drift.", - "owner": "eric@blindpay.com" - }, { "kind": "property", "schema": "UpdateCustomerIn", @@ -875,7 +199,20 @@ "owner": "eric@blindpay.com" } ], - "enumPropertyOmissions": [], + "enumPropertyOmissions": [ + { + "schema": "BankAccountOut", + "property": "swift_intermediary_bank_routing_number", + "reason": "anyOf of {enum: [\"\"]}, {pattern: ^\\d{9}$}, null: the only enum member is the empty-string sentinel that allows a blank value next to a free-form 9-digit ABA routing number, so there is no closed value set to map to a union (\"\" | string collapses to string). Modeled as `swift_intermediary_bank_routing_number?: string | null` on ListBankAccountsResponse and CreateInternationalSwiftResponse.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "CreateBankAccountIn", + "property": "swift_intermediary_bank_routing_number", + "reason": "anyOf of {enum: [\"\"]}, {pattern: ^\\d{9}$}, null: the only enum member is the empty-string sentinel that allows a blank value next to a free-form 9-digit ABA routing number, so there is no closed value set to map to a union (\"\" | string collapses to string). Modeled as `swift_intermediary_bank_routing_number?: string | null` on CreateInternationalSwiftInput.", + "owner": "thayto@blindpay.com" + } + ], "nestedShapeOmissions": [ { "schema": "BankAccountOut", @@ -886,8 +223,8 @@ { "schema": "CreateCustomerIn", "path": "owners[]", - "reason": "Pre-existing inline nested shape from before the api-sync-hardening pass introduced nested-object coverage checking; recorded intentionally (not modeled) so newly introduced unmapped nested shapes fail loudly instead of silently. Needs a human pass to either model or drop.", - "owner": "eric@blindpay.com" + "reason": "Modeled as CreateCustomerOwnerInput in src/resources/customers/index.ts and mapped via CreateCustomerIn.owners in spec-map.json; recorded here because nested-shape coverage only accepts omission entries, not map entries.", + "owner": "thayto@blindpay.com" }, { "schema": "CreatePayinOut", @@ -1252,62 +589,62 @@ { "schema": "UpdateCustomerIn", "path": "owners[]", - "reason": "Pre-existing inline nested shape from before the api-sync-hardening pass introduced nested-object coverage checking; recorded intentionally (not modeled) so newly introduced unmapped nested shapes fail loudly instead of silently. Needs a human pass to either model or drop.", - "owner": "eric@blindpay.com" + "reason": "Modeled as UpdateCustomerOwnerInput in src/resources/customers/index.ts and mapped via UpdateCustomerIn.owners in spec-map.json; recorded here because nested-shape coverage only accepts omission entries, not map entries.", + "owner": "thayto@blindpay.com" }, { "schema": "VirtualAccountOut", "path": "blockchain_wallet", - "reason": "Pre-existing inline nested shape from before the api-sync-hardening pass introduced nested-object coverage checking; recorded intentionally (not modeled) so newly introduced unmapped nested shapes fail loudly instead of silently. Needs a human pass to either model or drop.", - "owner": "eric@blindpay.com" + "reason": "Typed inline on VirtualAccount from the spec property's own properties (required/nullable per the spec). Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" }, { "schema": "VirtualAccountOut", "path": "us", - "reason": "Pre-existing inline nested shape from before the api-sync-hardening pass introduced nested-object coverage checking; recorded intentionally (not modeled) so newly introduced unmapped nested shapes fail loudly instead of silently. Needs a human pass to either model or drop.", - "owner": "eric@blindpay.com" + "reason": "Typed inline on VirtualAccount from the spec property's own properties (required/nullable per the spec). Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" }, { "schema": "VirtualAccountOut", "path": "us.ach", - "reason": "Pre-existing inline nested shape from before the api-sync-hardening pass introduced nested-object coverage checking; recorded intentionally (not modeled) so newly introduced unmapped nested shapes fail loudly instead of silently. Needs a human pass to either model or drop.", - "owner": "eric@blindpay.com" + "reason": "Typed inline on VirtualAccount from the spec property's own properties (required/nullable per the spec). Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" }, { "schema": "VirtualAccountOut", "path": "us.beneficiary", - "reason": "Pre-existing inline nested shape from before the api-sync-hardening pass introduced nested-object coverage checking; recorded intentionally (not modeled) so newly introduced unmapped nested shapes fail loudly instead of silently. Needs a human pass to either model or drop.", - "owner": "eric@blindpay.com" + "reason": "Typed inline on VirtualAccount from the spec property's own properties (required/nullable per the spec). Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" }, { "schema": "VirtualAccountOut", "path": "us.receiving_bank", - "reason": "Pre-existing inline nested shape from before the api-sync-hardening pass introduced nested-object coverage checking; recorded intentionally (not modeled) so newly introduced unmapped nested shapes fail loudly instead of silently. Needs a human pass to either model or drop.", - "owner": "eric@blindpay.com" + "reason": "Typed inline on VirtualAccount from the spec property's own properties (required/nullable per the spec). Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" }, { "schema": "VirtualAccountOut", "path": "us.rtp", - "reason": "Pre-existing inline nested shape from before the api-sync-hardening pass introduced nested-object coverage checking; recorded intentionally (not modeled) so newly introduced unmapped nested shapes fail loudly instead of silently. Needs a human pass to either model or drop.", - "owner": "eric@blindpay.com" + "reason": "Typed inline on VirtualAccount from the spec property's own properties (required/nullable per the spec). Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" }, { "schema": "VirtualAccountOut", "path": "us.swift_intermediary_bank", - "reason": "Pre-existing inline nested shape from before the api-sync-hardening pass introduced nested-object coverage checking; recorded intentionally (not modeled) so newly introduced unmapped nested shapes fail loudly instead of silently. Needs a human pass to either model or drop.", - "owner": "eric@blindpay.com" + "reason": "Typed inline on VirtualAccount from the spec property's own properties (required/nullable per the spec). Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" }, { "schema": "VirtualAccountOut", "path": "us.swift_receiving_bank", - "reason": "Pre-existing inline nested shape from before the api-sync-hardening pass introduced nested-object coverage checking; recorded intentionally (not modeled) so newly introduced unmapped nested shapes fail loudly instead of silently. Needs a human pass to either model or drop.", - "owner": "eric@blindpay.com" + "reason": "Typed inline on VirtualAccount from the spec property's own properties (required/nullable per the spec). Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" }, { "schema": "VirtualAccountOut", "path": "us.wire", - "reason": "Pre-existing inline nested shape from before the api-sync-hardening pass introduced nested-object coverage checking; recorded intentionally (not modeled) so newly introduced unmapped nested shapes fail loudly instead of silently. Needs a human pass to either model or drop.", - "owner": "eric@blindpay.com" + "reason": "Typed inline on VirtualAccount from the spec property's own properties (required/nullable per the spec). Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" }, { "schema": "PayinOut", @@ -1320,6 +657,150 @@ "path": "tracking_payment.review_contexts", "reason": "Inline nested shape added to the payin tracking_payment step alongside review_source/review_context; the SDK does not model it yet (same pending tracking_payment PR). Recorded so main's test suite goes green again.", "owner": "darlan@blindpay.com" + }, + { + "schema": "Rfi", + "path": "response", + "reason": "Free-form map (additionalProperties: string | uri[]), no fixed properties to map. Modeled as RfiResponse = Record on CustomerRfi.response; recorded because nested-coverage only accepts omissions.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "InstanceRfi", + "path": "response", + "reason": "Free-form map (additionalProperties: string | uri[]), no fixed properties to map. Modeled as RfiResponse = Record on InstanceRfi.response; recorded because nested-coverage only accepts omissions.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "RfiField", + "path": "items[]", + "reason": "Modeled inline on RfiField.items as Array<{ label: string; value: string }>; recorded because nested-coverage has no nested map-entry kind and only accepts omissions.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "CreateVirtualAccountIn", + "path": "bre_b", + "reason": "Typed inline by the api-sync field-insert, compiled from the spec property's own properties. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "VirtualAccountOut", + "path": "co", + "reason": "Typed inline by the api-sync field-insert, compiled from the spec property's own properties. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "VirtualAccountOut", + "path": "co.bre_b", + "reason": "Typed inline by the api-sync field-insert, compiled from the spec property's own properties. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "VirtualAccountOut", + "path": "co.beneficiary", + "reason": "Typed inline by the api-sync field-insert, compiled from the spec property's own properties. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "VirtualAccountOut", + "path": "mx", + "reason": "Typed inline by the api-sync field-insert, compiled from the spec property's own properties. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "VirtualAccountOut", + "path": "mx.spei", + "reason": "Typed inline by the api-sync field-insert, compiled from the spec property's own properties. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "VirtualAccountOut", + "path": "mx.beneficiary", + "reason": "Typed inline by the api-sync field-insert, compiled from the spec property's own properties. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "PayoutOut", + "path": "tracking_payment.review_context", + "reason": "Free-form map in the spec (additionalProperties only, no fixed properties); typed Record | null. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "PayoutOnEvmOut", + "path": "tracking_payment.review_context", + "reason": "Free-form map in the spec (additionalProperties only, no fixed properties); typed Record | null. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "PayinOut", + "path": "tracking_transaction.card_instruction", + "reason": "Typed inline by the api-sync field-insert, compiled from the spec property's own properties. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "PayinOut", + "path": "tracking_transaction.card_evidence", + "reason": "Typed inline by the api-sync field-insert, compiled from the spec property's own properties. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "CreatePayinOut", + "path": "tracking_transaction.card_instruction", + "reason": "Typed inline by the api-sync field-insert, compiled from the spec property's own properties. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "CreatePayinOut", + "path": "tracking_transaction.card_evidence", + "reason": "Typed inline by the api-sync field-insert, compiled from the spec property's own properties. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "TransferOut", + "path": "tracking_partner_fee", + "reason": "Modeled as TransferTrackingStep | null (src/resources/transfers/index.ts), the same five fields. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "CreateTransferOut", + "path": "tracking_partner_fee", + "reason": "Modeled as TransferTrackingStep | null (src/resources/transfers/index.ts), the same five fields. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "CustomerCnaeCondition", + "path": "cnae_at_approval", + "reason": "Modeled as CnaeSet / Cnae in src/resources/customers/index.ts. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "CustomerCnaeCondition", + "path": "cnae_at_approval.primary", + "reason": "Modeled as CnaeSet / Cnae in src/resources/customers/index.ts. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "CustomerCnaeCondition", + "path": "cnae_at_approval.secondary[]", + "reason": "Modeled as CnaeSet / Cnae in src/resources/customers/index.ts. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "CustomerCnaeCondition", + "path": "result_cnae", + "reason": "Modeled as CnaeSet / Cnae in src/resources/customers/index.ts. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "CustomerCnaeCondition", + "path": "result_cnae.primary", + "reason": "Modeled as CnaeSet / Cnae in src/resources/customers/index.ts. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" + }, + { + "schema": "CustomerCnaeCondition", + "path": "result_cnae.secondary[]", + "reason": "Modeled as CnaeSet / Cnae in src/resources/customers/index.ts. Recorded because spec-map.json has no nested entries; the type check covers the parent field.", + "owner": "thayto@blindpay.com" } ] } diff --git a/.changeset/api-sync-06558e9d25e7.md b/.changeset/api-sync-06558e9d25e7.md new file mode 100644 index 0000000..05e815d --- /dev/null +++ b/.changeset/api-sync-06558e9d25e7.md @@ -0,0 +1,608 @@ +--- +"@blindpay/node": minor +--- + +Sync SDK with API changes: + +- add enum member "111120" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "111219" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "111336" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "111421" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "112111" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "112210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "112310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "112410" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "112519" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "112990" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "113110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "113210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "114119" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "114210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "115113" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "115210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "115310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "211130" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "212290" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "212390" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "213113" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "221122" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "221210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "221320" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "236118" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "236210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "237130" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "237210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "237990" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "238191" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "238391" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "238991" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "311119" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "311212" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "311314" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "311422" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "311511" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "311612" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "311710" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "311811" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "311999" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "312111" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "312230" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "313240" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "313310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "314120" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "314999" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "315120" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "315250" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "316110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "316210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "316990" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "321113" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "321211" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "321918" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "322120" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "322299" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "323120" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "324110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "325180" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "325220" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "325320" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "325510" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "325611" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "325998" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "326111" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "326220" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "327120" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "327212" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "327310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "327410" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "327999" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "331110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "331210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "331313" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "331410" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "331511" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "332111" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "332215" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "332311" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "332410" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "332510" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "332613" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "332710" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "332812" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "332999" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "333111" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "333248" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "333310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "333413" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "333517" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "333611" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "333618" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "334310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "334413" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "334511" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "334610" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "335131" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "335220" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "335311" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "335999" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "336211" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "336412" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "336510" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "336611" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "336999" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "337122" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "337214" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "337920" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "339999" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "423120" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "423220" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "423310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "423490" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "423520" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "423620" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "423710" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "423990" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "424110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "424310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "424490" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "424590" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "424720" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "424820" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "425120" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "441110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "441227" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "441330" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "444180" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "444240" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "445132" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "445298" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "449110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "449129" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "454390" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "456120" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "458320" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "459310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "459410" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "459510" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "459999" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "481211" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "482111" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "483112" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "483212" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "484110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "484220" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "485119" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "485310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "485410" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "485510" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "485999" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "486110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "486210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "486990" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "487110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "487210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "487990" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "488190" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "488210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "488390" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "488490" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "488999" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "492110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "492210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "493190" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "512199" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "512290" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "513210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "515210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "517810" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "519290" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "521110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "522130" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "522298" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "522390" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "523210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "524128" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "524298" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "525190" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "525910" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "532289" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "532310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "532490" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "533110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "541199" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "541213" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "541219" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "541310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "541490" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "541690" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "541720" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "551114" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "561110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "561210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "561599" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "561611" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "561790" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "561990" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "562211" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "562998" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "611210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "611420" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "611519" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "611699" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "621498" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "621610" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "621999" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "622210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "622310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "623210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "623311" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "623990" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "624190" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "624230" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "624310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "711190" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "711219" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "711310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "712120" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "713290" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "713990" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "721199" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "721211" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "721310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "722310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "722410" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "811198" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "811310" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "811411" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "812210" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "812320" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "812990" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "813319" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "813410" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "813930" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "814110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "921140" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "922190" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "923130" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "924110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "925120" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "926110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "927110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "928110" to types/index.d.ts:BusinessIndustry (UpdateCustomerIn.business_industry) +- add enum member "ach_pull" to types/index.d.ts:PayinPaymentMethod (CreatePayinQuoteIn.payment_method) +- add enum member "ach_pull" to types/index.d.ts:PaymentMethod (CreatePayinQuoteIn.payment_method) +- add enum member "approved_rfi" to types/index.d.ts:KycStatus (CustomerOut.kyc_status) +- add enum member "arc" to src/resources/wallets/offramp.ts:OfframpWalletNetwork (BankAccountWebhookOut.offramp_wallets.[].network) +- add enum member "arc" to types/index.d.ts:Network (VirtualAccountOut.blockchain_wallet.network) +- add enum member "arc_testnet" to src/resources/wallets/offramp.ts:OfframpWalletNetwork (BankAccountWebhookOut.offramp_wallets.[].network) +- add enum member "arc_testnet" to types/index.d.ts:Network (VirtualAccountOut.blockchain_wallet.network) +- add enum member "bre_b" to src/resources/virtual-accounts/index.ts:BankingPartner (VirtualAccountOut.banking_partner) +- add enum member "bre_b" to types/index.d.ts:BankingPartner (VirtualAccountOut.banking_partner) +- add enum member "card" to types/index.d.ts:PayinPaymentMethod (CreatePayinQuoteIn.payment_method) +- add enum member "card" to types/index.d.ts:PaymentMethod (CreatePayinQuoteIn.payment_method) +- add enum member "documents" to src/resources/upload/index.ts:UploadBucket (UploadIn.bucket) +- add enum member "faster_payments" to types/index.d.ts:Rail (BankAccountWebhookOut.type) +- add enum member "faster_payments_account_number" to src/resources/available/index.ts:BankDetailKey (AvailableBankDetails.[].key) +- add enum member "faster_payments_beneficiary_address_line_1" to src/resources/available/index.ts:BankDetailKey (AvailableBankDetails.[].key) +- add enum member "faster_payments_beneficiary_address_line_2" to src/resources/available/index.ts:BankDetailKey (AvailableBankDetails.[].key) +- add enum member "faster_payments_beneficiary_city" to src/resources/available/index.ts:BankDetailKey (AvailableBankDetails.[].key) +- add enum member "faster_payments_beneficiary_country" to src/resources/available/index.ts:BankDetailKey (AvailableBankDetails.[].key) +- add enum member "faster_payments_beneficiary_legal_name" to src/resources/available/index.ts:BankDetailKey (AvailableBankDetails.[].key) +- add enum member "faster_payments_beneficiary_postal_code" to src/resources/available/index.ts:BankDetailKey (AvailableBankDetails.[].key) +- add enum member "faster_payments_beneficiary_state_province_region" to src/resources/available/index.ts:BankDetailKey (AvailableBankDetails.[].key) +- add enum member "faster_payments_sort_code" to src/resources/available/index.ts:BankDetailKey (AvailableBankDetails.[].key) +- add enum member "payable.complete" to src/resources/webhooks/index.ts:WebhookEvents (WebhookEndpointIn.events) +- add enum member "payable.new" to src/resources/webhooks/index.ts:WebhookEvents (WebhookEndpointIn.events) +- add enum member "payable.update" to src/resources/webhooks/index.ts:WebhookEvents (WebhookEndpointIn.events) +- add enum member "pending_refund_review" to types/index.d.ts:TrackingStatus (PayoutOut.tracking_complete.step) +- add enum member "portage_g" to src/resources/virtual-accounts/index.ts:BankingPartner (VirtualAccountOut.banking_partner) +- add enum member "portage_g" to types/index.d.ts:BankingPartner (VirtualAccountOut.banking_partner) +- add enum member "salary_or_wages" to types/index.d.ts:SourceOfWealth (UpdateCustomerIn.source_of_wealth) +- add enum member "savings" to types/index.d.ts:SourceOfWealth (UpdateCustomerIn.source_of_wealth) +- add enum member "spei" to src/resources/virtual-accounts/index.ts:BankingPartner (VirtualAccountOut.banking_partner) +- add enum member "spei" to types/index.d.ts:BankingPartner (VirtualAccountOut.banking_partner) +- add enum member "swift_intermediary_bank_routing_number" to src/resources/available/index.ts:BankDetailKey (AvailableBankDetails.[].key) +- add enum member "tempo" to src/resources/wallets/offramp.ts:OfframpWalletNetwork (BankAccountWebhookOut.offramp_wallets.[].network) +- add enum member "tempo" to types/index.d.ts:Network (VirtualAccountOut.blockchain_wallet.network) +- add enum member "tempo_testnet" to src/resources/wallets/offramp.ts:OfframpWalletNetwork (BankAccountWebhookOut.offramp_wallets.[].network) +- add enum member "tempo_testnet" to types/index.d.ts:Network (VirtualAccountOut.blockchain_wallet.network) +- add enum member "wallet.update" to src/resources/webhooks/index.ts:WebhookEvents (WebhookEndpointIn.events) +- add field "EURB?: WalletTokenBalance" to src/resources/wallets/custodial.ts:GetCustodialWalletBalanceResponse (WalletBalanceOut) +- add field "EURC?: WalletTokenBalance" to src/resources/wallets/custodial.ts:GetCustodialWalletBalanceResponse (WalletBalanceOut) +- add field "accent_color?: string | null" to src/resources/instances/index.ts:UpdateInstanceInput (UpdateInstanceIn) +- add field "bank_account_id?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "bre_b?: { + gender: "male" | "female"; +} | null" to src/resources/virtual-accounts/index.ts:CreateVirtualAccountInput (CreateVirtualAccountIn) +- add field "card_claim_at?: string | null" to types/index.d.ts:PayinTrackingTransaction (PayinOut.tracking_transaction) +- add field "card_evidence?: { + eci?: string | null; + cavv?: string | null; + avs_response?: string | null; + cvv_response?: string | null; + auth_code?: string | null; + cardholder_name?: string | null; + three_ds_version?: string | null; +} | null" to types/index.d.ts:PayinTrackingTransaction (PayinOut.tracking_transaction) +- add field "card_failed_attempts?: number | null" to types/index.d.ts:PayinTrackingTransaction (PayinOut.tracking_transaction) +- add field "card_gates_failed_at?: string | null" to types/index.d.ts:PayinTrackingTransaction (PayinOut.tracking_transaction) +- add field "card_instruction?: { + provider: string; + tokenization_key: string; +} | null" to types/index.d.ts:PayinTrackingTransaction (PayinOut.tracking_transaction) +- add field "co?: { + bre_b: { + key: string; +}; + beneficiary?: { + name: string; +} | null; +} | null" to src/resources/virtual-accounts/index.ts:VirtualAccount (VirtualAccountOut) +- add field "earning_amount?: number" to src/resources/wallets/custodial.ts:WalletTokenBalance (WalletTokenOut) +- add field "faster_payments?: string" to src/resources/fees/index.ts:GetFeesResponse (GetFeesOut) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateAchInput (CreateBankAccountIn) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateAchResponse (BankAccountOut) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersInput (CreateBankAccountIn) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersResponse (BankAccountOut) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchInput (CreateBankAccountIn) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchResponse (BankAccountOut) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftInput (CreateBankAccountIn) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftResponse (BankAccountOut) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreatePixInput (CreateBankAccountIn) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreatePixResponse (BankAccountOut) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeInput (CreateBankAccountIn) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeResponse (BankAccountOut) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpInput (CreateBankAccountIn) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpResponse (BankAccountOut) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaInput (CreateBankAccountIn) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaResponse (BankAccountOut) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiInput (CreateBankAccountIn) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiResponse (BankAccountOut) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateTedInput (CreateBankAccountIn) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateTedResponse (BankAccountOut) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateWireInput (CreateBankAccountIn) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:CreateWireResponse (BankAccountOut) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:GetBankAccountResponse (BankAccountOut) +- add field "faster_payments_account_number?: string | null" to src/resources/bank-accounts/index.ts:ListBankAccountsResponse (BankAccountOut) +- add field "faster_payments_account_number?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateAchInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateAchResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreatePixInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreatePixResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateTedInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateTedResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateWireInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:CreateWireResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:GetBankAccountResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/bank-accounts/index.ts:ListBankAccountsResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_1?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateAchInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateAchResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreatePixInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreatePixResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateTedInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateTedResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateWireInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:CreateWireResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:GetBankAccountResponse (BankAccountOut) +- add field "faster_payments_beneficiary_address_line_2?: string | null" to src/resources/bank-accounts/index.ts:ListBankAccountsResponse (BankAccountOut) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateAchInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateAchResponse (BankAccountOut) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersResponse (BankAccountOut) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchResponse (BankAccountOut) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftResponse (BankAccountOut) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreatePixInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreatePixResponse (BankAccountOut) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeResponse (BankAccountOut) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpResponse (BankAccountOut) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaResponse (BankAccountOut) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiResponse (BankAccountOut) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateTedInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateTedResponse (BankAccountOut) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateWireInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:CreateWireResponse (BankAccountOut) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:GetBankAccountResponse (BankAccountOut) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/bank-accounts/index.ts:ListBankAccountsResponse (BankAccountOut) +- add field "faster_payments_beneficiary_city?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateAchInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateAchResponse (BankAccountOut) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersResponse (BankAccountOut) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchResponse (BankAccountOut) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftResponse (BankAccountOut) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreatePixInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreatePixResponse (BankAccountOut) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreatePixSafeInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreatePixSafeResponse (BankAccountOut) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateRtpInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateRtpResponse (BankAccountOut) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateSepaInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateSepaResponse (BankAccountOut) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateSpeiInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateSpeiResponse (BankAccountOut) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateTedInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateTedResponse (BankAccountOut) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateWireInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:CreateWireResponse (BankAccountOut) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:GetBankAccountResponse (BankAccountOut) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/bank-accounts/index.ts:ListBankAccountsResponse (BankAccountOut) +- add field "faster_payments_beneficiary_country?: Country | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateAchInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateAchResponse (BankAccountOut) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersResponse (BankAccountOut) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchResponse (BankAccountOut) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftResponse (BankAccountOut) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreatePixInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreatePixResponse (BankAccountOut) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeResponse (BankAccountOut) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpResponse (BankAccountOut) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaResponse (BankAccountOut) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiResponse (BankAccountOut) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateTedInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateTedResponse (BankAccountOut) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateWireInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:CreateWireResponse (BankAccountOut) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:GetBankAccountResponse (BankAccountOut) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/bank-accounts/index.ts:ListBankAccountsResponse (BankAccountOut) +- add field "faster_payments_beneficiary_legal_name?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateAchInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateAchResponse (BankAccountOut) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersResponse (BankAccountOut) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchResponse (BankAccountOut) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftResponse (BankAccountOut) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreatePixInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreatePixResponse (BankAccountOut) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeResponse (BankAccountOut) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpResponse (BankAccountOut) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaResponse (BankAccountOut) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiResponse (BankAccountOut) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateTedInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateTedResponse (BankAccountOut) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateWireInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:CreateWireResponse (BankAccountOut) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:GetBankAccountResponse (BankAccountOut) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/bank-accounts/index.ts:ListBankAccountsResponse (BankAccountOut) +- add field "faster_payments_beneficiary_postal_code?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateAchInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateAchResponse (BankAccountOut) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersResponse (BankAccountOut) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchResponse (BankAccountOut) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftResponse (BankAccountOut) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreatePixInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreatePixResponse (BankAccountOut) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeResponse (BankAccountOut) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpResponse (BankAccountOut) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaResponse (BankAccountOut) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiResponse (BankAccountOut) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateTedInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateTedResponse (BankAccountOut) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateWireInput (CreateBankAccountIn) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:CreateWireResponse (BankAccountOut) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:GetBankAccountResponse (BankAccountOut) +- add field "faster_payments_beneficiary_state_province_region?: string | null" to src/resources/bank-accounts/index.ts:ListBankAccountsResponse (BankAccountOut) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateAchInput (CreateBankAccountIn) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateAchResponse (BankAccountOut) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersInput (CreateBankAccountIn) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersResponse (BankAccountOut) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchInput (CreateBankAccountIn) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchResponse (BankAccountOut) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftInput (CreateBankAccountIn) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftResponse (BankAccountOut) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreatePixInput (CreateBankAccountIn) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreatePixResponse (BankAccountOut) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeInput (CreateBankAccountIn) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeResponse (BankAccountOut) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpInput (CreateBankAccountIn) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpResponse (BankAccountOut) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaInput (CreateBankAccountIn) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaResponse (BankAccountOut) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiInput (CreateBankAccountIn) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiResponse (BankAccountOut) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateTedInput (CreateBankAccountIn) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateTedResponse (BankAccountOut) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateWireInput (CreateBankAccountIn) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:CreateWireResponse (BankAccountOut) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:GetBankAccountResponse (BankAccountOut) +- add field "faster_payments_sort_code?: string | null" to src/resources/bank-accounts/index.ts:ListBankAccountsResponse (BankAccountOut) +- add field "faster_payments_sort_code?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "forced_provider?: "zenus" | "veem" | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "funding_bank_account_id?: string | null" to src/resources/payins/quotes.ts:CreatePayinQuoteInput (CreatePayinQuoteIn) +- add field "is_nested?: boolean | null" to src/resources/customers/index.ts:BusinessWithStandardKYB (CustomerOut) +- add field "is_nested?: boolean | null" to src/resources/customers/index.ts:IndividualWithEnhancedKYC (CustomerOut) +- add field "is_nested?: boolean | null" to src/resources/customers/index.ts:IndividualWithStandardKYC (CustomerOut) +- add field "logo_url?: string | null" to src/resources/instances/index.ts:UpdateInstanceInput (UpdateInstanceIn) +- add field "mx?: { + spei: { + clabe: string; +}; + beneficiary?: { + name: string; +} | null; +} | null" to src/resources/virtual-accounts/index.ts:VirtualAccount (VirtualAccountOut) +- add field "partner_fee_id?: string | null" to src/resources/virtual-accounts/index.ts:CreateVirtualAccountInput (CreateVirtualAccountIn) +- add field "partner_fee_id?: string | null" to src/resources/virtual-accounts/index.ts:UpdateVirtualAccountInput (UpdateVirtualAccountIn) +- add field "partner_fee_id?: string | null" to src/resources/virtual-accounts/index.ts:VirtualAccount (VirtualAccountOut) +- add field "partner_flat_fee?: number" to src/resources/transfers/index.ts:CreateTransferQuoteInput (CreateTransferQuoteIn) +- add field "partner_flat_fee?: number" to src/resources/transfers/index.ts:CreateTransferQuoteResponse (CreateTransferQuoteOut) +- add field "partner_flat_fee?: number" to src/resources/transfers/index.ts:Transfer (TransferOut) +- add field "partner_percentage_fee?: number" to src/resources/transfers/index.ts:CreateTransferQuoteInput (CreateTransferQuoteIn) +- add field "partner_percentage_fee?: number" to src/resources/transfers/index.ts:CreateTransferQuoteResponse (CreateTransferQuoteOut) +- add field "partner_percentage_fee?: number" to src/resources/transfers/index.ts:Transfer (TransferOut) +- add field "partner_tos_link?: string | null" to src/resources/instances/index.ts:UpdateInstanceInput (UpdateInstanceIn) +- add field "partner_tos_screenshot?: string | null" to src/resources/instances/index.ts:UpdateInstanceInput (UpdateInstanceIn) +- add field "partner_tos_terms_accepted?: boolean" to src/resources/instances/index.ts:UpdateInstanceInput (UpdateInstanceIn) +- add field "payable_id?: string | null" to src/resources/payouts/index.ts:CreateEvmPayoutResponse (PayoutOnEvmOut) +- add field "payable_id?: string | null" to src/resources/payouts/index.ts:CreateSolanaPayoutResponse (PayoutOnEvmOut) +- add field "payable_id?: string | null" to src/resources/payouts/index.ts:CreateStellarPayoutResponse (PayoutOnEvmOut) +- add field "payable_id?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "payable_id?: string | null" to src/resources/quotes/index.ts:CreateQuoteInput (QuoteIn) +- add field "plaid_connected_at?: string | null" to src/resources/bank-accounts/index.ts:CreateAchResponse (BankAccountOut) +- add field "plaid_connected_at?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersResponse (BankAccountOut) +- add field "plaid_connected_at?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchResponse (BankAccountOut) +- add field "plaid_connected_at?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftResponse (BankAccountOut) +- add field "plaid_connected_at?: string | null" to src/resources/bank-accounts/index.ts:CreatePixResponse (BankAccountOut) +- add field "plaid_connected_at?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeResponse (BankAccountOut) +- add field "plaid_connected_at?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpResponse (BankAccountOut) +- add field "plaid_connected_at?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaResponse (BankAccountOut) +- add field "plaid_connected_at?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiResponse (BankAccountOut) +- add field "plaid_connected_at?: string | null" to src/resources/bank-accounts/index.ts:CreateTedResponse (BankAccountOut) +- add field "plaid_connected_at?: string | null" to src/resources/bank-accounts/index.ts:CreateWireResponse (BankAccountOut) +- add field "plaid_connected_at?: string | null" to src/resources/bank-accounts/index.ts:GetBankAccountResponse (BankAccountOut) +- add field "plaid_connected_at?: string | null" to src/resources/bank-accounts/index.ts:ListBankAccountsResponse (BankAccountOut) +- add field "refund_review_actioned_at?: string | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "refund_review_detected_at?: string | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "refund_review_reason?: "amount_threshold" | "time_window" | "late_cancellation_no_live_run" | "master_account_return" | "policy_always_review" | "operator_requested" | "partial_return" | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "returned_amount?: number | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "review_context?: Record | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "review_source?: string | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "review_sources?: unknown[] | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "sepa_beneficiary_address_line_1?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "sepa_beneficiary_city?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "sepa_beneficiary_country?: Country | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "sepa_beneficiary_legal_name?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "sepa_beneficiary_postal_code?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "sepa_iban?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "total_amount?: number" to src/resources/wallets/custodial.ts:WalletTokenBalance (WalletTokenOut) +- add field "wallet_id?: string" to src/resources/payouts/index.ts:AuthorizeStellarTokenInput (PayoutOnStellarAuthorizeIn) +- add field "wallet_id?: string" to src/resources/payouts/index.ts:CreateEvmPayoutInput (PayoutOnEvmIn) +- add field "wallet_id?: string" to src/resources/payouts/index.ts:CreateSolanaPayoutInput (PayoutOnSolanaIn) +- add field "wallet_id?: string" to src/resources/payouts/index.ts:CreateStellarPayoutInput (PayoutOnStellarIn) +- add method "createPlaid" to src/resources/bank-accounts/index.ts:createBankAccountsResource (POST /v1/instances/{instance_id}/customers/{customer_id}/bank-accounts/plaid) diff --git a/.changeset/api-sync-7c619c1122ba.md b/.changeset/api-sync-7c619c1122ba.md new file mode 100644 index 0000000..5f3ba7e --- /dev/null +++ b/.changeset/api-sync-7c619c1122ba.md @@ -0,0 +1,172 @@ +--- +"@blindpay/node": minor +--- + +Sync SDK with API changes: + +- add enum member "bre_b" to types/index.d.ts:PayinPaymentMethod (PayinOut.payment_method) +- add enum member "infinitus_portage" to types/index.d.ts:PayoutForcedProvider (PayoutOut.tracking_payment.forced_provider) +- add field "additional_info?: AdditionalInfoItem[] | null" to src/resources/customers/index.ts:BusinessWithStandardKYB (CustomerOut) +- add field "additional_info?: AdditionalInfoItem[] | null" to src/resources/customers/index.ts:CreateBusinessWithStandardKYBInput (CreateCustomerIn) +- add field "additional_info?: AdditionalInfoItem[] | null" to src/resources/customers/index.ts:CreateIndividualWithEnhancedKYCInput (CreateCustomerIn) +- add field "additional_info?: AdditionalInfoItem[] | null" to src/resources/customers/index.ts:CreateIndividualWithStandardKYCInput (CreateCustomerIn) +- add field "additional_info?: AdditionalInfoItem[] | null" to src/resources/customers/index.ts:IndividualWithEnhancedKYC (CustomerOut) +- add field "additional_info?: AdditionalInfoItem[] | null" to src/resources/customers/index.ts:IndividualWithStandardKYC (CustomerOut) +- add field "additional_info?: AdditionalInfoItem[] | null" to src/resources/customers/index.ts:UpdateCustomerInput (UpdateCustomerIn) +- add field "approved_risk_sources?: string[] | null" to types/index.d.ts:PayinTrackingPayment (PayinOut.tracking_payment) +- add field "bank_account_id?: string | null" to src/resources/payouts/index.ts:CreateEvmPayoutResponse (PayoutOnEvmOut) +- add field "bank_account_id?: string | null" to src/resources/payouts/index.ts:CreateSolanaPayoutResponse (PayoutOnEvmOut) +- add field "bank_account_id?: string | null" to src/resources/payouts/index.ts:CreateStellarPayoutResponse (PayoutOnEvmOut) +- add field "billing_fee_amount?: number | null" to src/resources/payins/index.ts:CreateEvmPayinResponse (CreatePayinOut) +- add field "billing_fee_amount?: number | null" to src/resources/payins/quotes.ts:CreatePayinQuoteResponse (CreatePayinQuoteOut) +- add field "billing_fee_amount?: number | null" to src/resources/payouts/index.ts:CreateEvmPayoutResponse (PayoutOnEvmOut) +- add field "billing_fee_amount?: number | null" to src/resources/payouts/index.ts:CreateSolanaPayoutResponse (PayoutOnEvmOut) +- add field "billing_fee_amount?: number | null" to src/resources/payouts/index.ts:CreateStellarPayoutResponse (PayoutOnEvmOut) +- add field "billing_fee_amount?: number | null" to src/resources/quotes/index.ts:CreateQuoteResponse (QuoteOut) +- add field "business_type?: BusinessType | null" to src/resources/customers/index.ts:BusinessWithStandardKYB (CustomerOut) +- add field "business_type?: BusinessType | null" to src/resources/customers/index.ts:IndividualWithEnhancedKYC (CustomerOut) +- add field "business_type?: BusinessType | null" to src/resources/customers/index.ts:IndividualWithStandardKYC (CustomerOut) +- add field "coelsa_id?: string | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "compliance_emails?: string[] | null" to src/resources/instances/index.ts:UpdateInstanceInput (UpdateInstanceIn) +- add field "customer_id?: string | null" to src/resources/virtual-accounts/index.ts:VirtualAccount (VirtualAccountOut) +- add field "customer_id?: string" to src/resources/customers/index.ts:BusinessWithStandardKYB (CustomerOut) +- add field "customer_id?: string" to src/resources/customers/index.ts:IndividualWithEnhancedKYC (CustomerOut) +- add field "customer_id?: string" to src/resources/customers/index.ts:IndividualWithStandardKYC (CustomerOut) +- add field "customer_rfi_emails_enabled?: boolean" to src/resources/instances/index.ts:UpdateInstanceInput (UpdateInstanceIn) +- add field "end_to_end_id?: string | null" to types/index.d.ts:PayinTrackingTransaction (PayinOut.tracking_transaction) +- add field "end_to_end_id?: string | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "external_id?: string | null" to src/resources/transfers/index.ts:Transfer (TransferOut) +- add field "force_cpf_cnpj?: boolean | null" to src/resources/bank-accounts/index.ts:CreateAchInput (CreateBankAccountIn) +- add field "force_cpf_cnpj?: boolean | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersInput (CreateBankAccountIn) +- add field "force_cpf_cnpj?: boolean | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchInput (CreateBankAccountIn) +- add field "force_cpf_cnpj?: boolean | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftInput (CreateBankAccountIn) +- add field "force_cpf_cnpj?: boolean | null" to src/resources/bank-accounts/index.ts:CreatePixInput (CreateBankAccountIn) +- add field "force_cpf_cnpj?: boolean | null" to src/resources/bank-accounts/index.ts:CreatePixSafeInput (CreateBankAccountIn) +- add field "force_cpf_cnpj?: boolean | null" to src/resources/bank-accounts/index.ts:CreateRtpInput (CreateBankAccountIn) +- add field "force_cpf_cnpj?: boolean | null" to src/resources/bank-accounts/index.ts:CreateSepaInput (CreateBankAccountIn) +- add field "force_cpf_cnpj?: boolean | null" to src/resources/bank-accounts/index.ts:CreateSpeiInput (CreateBankAccountIn) +- add field "force_cpf_cnpj?: boolean | null" to src/resources/bank-accounts/index.ts:CreateTedInput (CreateBankAccountIn) +- add field "force_cpf_cnpj?: boolean | null" to src/resources/bank-accounts/index.ts:CreateWireInput (CreateBankAccountIn) +- add field "has_passkey?: boolean | null" to src/resources/instances/index.ts:GetInstanceMembersResponse (get /v1/instances/{id}/members) +- add field "latitude?: number | null" to src/resources/customers/index.ts:BusinessWithStandardKYB (CustomerOut) +- add field "latitude?: number | null" to src/resources/customers/index.ts:CreateBusinessWithStandardKYBInput (CreateCustomerIn) +- add field "latitude?: number | null" to src/resources/customers/index.ts:CreateIndividualWithEnhancedKYCInput (CreateCustomerIn) +- add field "latitude?: number | null" to src/resources/customers/index.ts:CreateIndividualWithStandardKYCInput (CreateCustomerIn) +- add field "latitude?: number | null" to src/resources/customers/index.ts:IndividualWithEnhancedKYC (CustomerOut) +- add field "latitude?: number | null" to src/resources/customers/index.ts:IndividualWithStandardKYC (CustomerOut) +- add field "latitude?: number | null" to src/resources/customers/index.ts:UpdateCustomerInput (UpdateCustomerIn) +- add field "ledger_in_transaction_id?: string | null" to types/index.d.ts:PayoutTrackingTransaction (PayoutOut.tracking_transaction) +- add field "ledger_out_transaction_id?: string | null" to types/index.d.ts:PayoutTrackingTransaction (PayoutOut.tracking_transaction) +- add field "longitude?: number | null" to src/resources/customers/index.ts:BusinessWithStandardKYB (CustomerOut) +- add field "longitude?: number | null" to src/resources/customers/index.ts:CreateBusinessWithStandardKYBInput (CreateCustomerIn) +- add field "longitude?: number | null" to src/resources/customers/index.ts:CreateIndividualWithEnhancedKYCInput (CreateCustomerIn) +- add field "longitude?: number | null" to src/resources/customers/index.ts:CreateIndividualWithStandardKYCInput (CreateCustomerIn) +- add field "longitude?: number | null" to src/resources/customers/index.ts:IndividualWithEnhancedKYC (CustomerOut) +- add field "longitude?: number | null" to src/resources/customers/index.ts:IndividualWithStandardKYC (CustomerOut) +- add field "longitude?: number | null" to src/resources/customers/index.ts:UpdateCustomerInput (UpdateCustomerIn) +- add field "manual_concluded_at?: string" to src/resources/payins/index.ts:Payin (PayinOut) +- add field "manual_concluded_by?: string | null" to src/resources/payins/index.ts:Payin (PayinOut) +- add field "manual_execution_status?: "pending" | "concluded" | "failed" | null" to src/resources/payins/index.ts:Payin (PayinOut) +- add field "offramp_wallet_id?: string | null" to src/resources/payouts/index.ts:CreateEvmPayoutResponse (PayoutOnEvmOut) +- add field "offramp_wallet_id?: string | null" to src/resources/payouts/index.ts:CreateSolanaPayoutResponse (PayoutOnEvmOut) +- add field "offramp_wallet_id?: string | null" to src/resources/payouts/index.ts:CreateStellarPayoutResponse (PayoutOnEvmOut) +- add field "partner_fee?: number" to src/resources/payins/index.ts:CreateEvmPayinResponse (CreatePayinOut) +- add field "partner_fee?: number" to src/resources/payins/index.ts:Payin (PayinOut) +- add field "partner_fee?: number" to src/resources/payouts/index.ts:CreateEvmPayoutResponse (PayoutOnEvmOut) +- add field "partner_fee?: number" to src/resources/payouts/index.ts:CreateSolanaPayoutResponse (PayoutOnEvmOut) +- add field "partner_fee?: number" to src/resources/payouts/index.ts:CreateStellarPayoutResponse (PayoutOnEvmOut) +- add field "partner_fee?: number" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "pix_safe_bank_code?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "pix_safe_branch_code?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "pix_safe_cpf_cnpj?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "provider_clearing_system?: string | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "provider_error_reason?: string | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "provider_error_reason?: string | null" to types/index.d.ts:PayoutTrackingTransaction (PayoutOut.tracking_transaction) +- add field "provider_imad?: string | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "provider_integration?: PayoutProviderIntegration | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "provider_name?: string | null" to types/index.d.ts:PayinTrackingTransaction (PayinOut.tracking_transaction) +- add field "provider_reference?: string | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "provider_transaction_id?: string | null" to types/index.d.ts:PayinTrackingTransaction (PayinOut.tracking_transaction) +- add field "provider_transaction_id?: string | null" to types/index.d.ts:PayoutTrackingComplete (PayoutOut.tracking_complete) +- add field "provider_transaction_id?: string | null" to types/index.d.ts:PayoutTrackingTransaction (PayoutOut.tracking_transaction) +- add field "provider_uetr?: string | null" to types/index.d.ts:PayoutTrackingPayment (PayoutOut.tracking_payment) +- add field "refund_reason?: string | null" to types/index.d.ts:PayoutTrackingComplete (PayoutOut.tracking_complete) +- add field "requiredWhen?: { + field: "type" | "name" | "status" | "recipient_relationship" | "swift_payment_code" | "pix_key" | "force_cpf_cnpj" | "beneficiary_name" | "routing_number" | "account_number" | "account_type" | "account_class" | "address_line_1" | "address_line_2" | "city" | "state_province_region" | "country" | "postal_code" | "checkbook_account_id" | "checkbook_user_key" | "onemoney_external_account_id" | "pix_safe_bank_code" | "pix_safe_branch_code" | "pix_safe_cpf_cnpj" | "ted_bank_code" | "ted_branch_code" | "ted_cpf_cnpj" | "spei_protocol" | "spei_institution_code" | "spei_clabe" | "transfers_type" | "transfers_account" | "ach_cop_beneficiary_first_name" | "ach_cop_beneficiary_last_name" | "ach_cop_document_id" | "ach_cop_document_type" | "ach_cop_email" | "ach_cop_bank_code" | "ach_cop_bank_account" | "swift_code_bic" | "swift_account_holder_name" | "swift_account_number_iban" | "swift_beneficiary_address_line_1" | "swift_beneficiary_address_line_2" | "swift_beneficiary_country" | "swift_beneficiary_city" | "swift_beneficiary_state_province_region" | "swift_beneficiary_postal_code" | "swift_bank_name" | "swift_bank_address_line_1" | "swift_bank_address_line_2" | "swift_bank_country" | "swift_bank_city" | "swift_bank_state_province_region" | "swift_bank_postal_code" | "swift_ifsc_branch_code" | "swift_intermediary_bank_swift_code_bic" | "swift_intermediary_bank_account_number_iban" | "swift_intermediary_bank_name" | "swift_intermediary_bank_country" | "swift_intermediary_bank_routing_number" | "sepa_iban" | "sepa_beneficiary_bic" | "sepa_beneficiary_legal_name" | "sepa_beneficiary_address_line_1" | "sepa_beneficiary_address_line_2" | "sepa_beneficiary_city" | "sepa_beneficiary_state_province_region" | "sepa_beneficiary_postal_code" | "sepa_beneficiary_country" | "faster_payments_sort_code" | "faster_payments_account_number" | "faster_payments_beneficiary_legal_name" | "faster_payments_beneficiary_address_line_1" | "faster_payments_beneficiary_address_line_2" | "faster_payments_beneficiary_city" | "faster_payments_beneficiary_state_province_region" | "faster_payments_beneficiary_postal_code" | "faster_payments_beneficiary_country" | "business_industry" | "phone_number" | "tax_id" | "date_of_birth"; + operator: "in" | "eq" | "notIn" | "notEq"; + values: string[]; +}" to src/resources/available/index.ts:GetBankDetailsResponse (AvailableBankDetails) +- add field "review_context?: Record | null" to types/index.d.ts:PayinTrackingPayment (PayinOut.tracking_payment) +- add field "review_source?: string | null" to types/index.d.ts:PayinTrackingPayment (PayinOut.tracking_payment) +- add field "sender_bank_name?: string | null" to types/index.d.ts:PayinTrackingTransaction (PayinOut.tracking_transaction) +- add field "sender_legal_name?: string | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "sepa?: FeeOptions" to src/resources/fees/index.ts:GetFeesResponse (GetFeesOut) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateAchInput (CreateBankAccountIn) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateAchResponse (BankAccountOut) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersInput (CreateBankAccountIn) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateArgentinaTransfersResponse (BankAccountOut) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchInput (CreateBankAccountIn) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateColombiaAchResponse (BankAccountOut) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftInput (CreateBankAccountIn) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateInternationalSwiftResponse (BankAccountOut) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreatePixInput (CreateBankAccountIn) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreatePixResponse (BankAccountOut) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeInput (CreateBankAccountIn) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreatePixSafeResponse (BankAccountOut) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpInput (CreateBankAccountIn) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateRtpResponse (BankAccountOut) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaInput (CreateBankAccountIn) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateSepaResponse (BankAccountOut) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiInput (CreateBankAccountIn) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateSpeiResponse (BankAccountOut) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateTedInput (CreateBankAccountIn) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateTedResponse (BankAccountOut) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateWireInput (CreateBankAccountIn) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:CreateWireResponse (BankAccountOut) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:GetBankAccountResponse (BankAccountOut) +- add field "swift_ifsc_branch_code?: string | null" to src/resources/bank-accounts/index.ts:ListBankAccountsResponse (BankAccountOut) +- add field "ted_instruction?: { + beneficiary_name: string; + tax_id: string; + bank_code: string; + bank_name: string; + branch_code: string; + account_number: string; + account_type: string; +} | null" to types/index.d.ts:PayinTrackingTransaction (PayinOut.tracking_transaction) +- add field "tracking_documents?: { + step: TrackingStatus; + status?: "waiting_documents" | "compliance_reviewing" | null; + reviewed_by?: string | null; + completed_at?: string | null; +} | null" to src/resources/payouts/index.ts:CreateEvmPayoutResponse (PayoutOnEvmOut) +- add field "tracking_documents?: { + step: TrackingStatus; + status?: "waiting_documents" | "compliance_reviewing" | null; + reviewed_by?: string | null; + completed_at?: string | null; +} | null" to src/resources/payouts/index.ts:CreateSolanaPayoutResponse (PayoutOnEvmOut) +- add field "tracking_documents?: { + step: TrackingStatus; + status?: "waiting_documents" | "compliance_reviewing" | null; + reviewed_by?: string | null; + completed_at?: string | null; +} | null" to src/resources/payouts/index.ts:CreateStellarPayoutResponse (PayoutOnEvmOut) +- add field "tracking_documents?: { + step: TrackingStatus; + status?: "waiting_documents" | "compliance_reviewing" | null; + reviewed_by?: string | null; + completed_at?: string | null; +} | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "transaction_fee_amount?: number | null" to src/resources/payins/index.ts:CreateEvmPayinResponse (CreatePayinOut) +- add field "transaction_fee_amount?: number | null" to src/resources/payins/index.ts:Payin (PayinOut) +- add field "transaction_fee_amount?: number | null" to src/resources/payouts/index.ts:CreateEvmPayoutResponse (PayoutOnEvmOut) +- add field "transaction_fee_amount?: number | null" to src/resources/payouts/index.ts:CreateSolanaPayoutResponse (PayoutOnEvmOut) +- add field "transaction_fee_amount?: number | null" to src/resources/payouts/index.ts:CreateStellarPayoutResponse (PayoutOnEvmOut) +- add field "transaction_fee_amount?: number | null" to src/resources/payouts/index.ts:Payout (PayoutOut) +- add field "transaction_hash?: string | null" to types/index.d.ts:PayinTrackingTransaction (PayinOut.tracking_transaction) +- add field "yield?: { + blindpay_share_bps: number; + partner_share_bps: number; + partner_wallet_address?: string | null; +} | null" to src/resources/fees/index.ts:GetFeesResponse (GetFeesOut) diff --git a/.changeset/brave-rfi-payables.md b/.changeset/brave-rfi-payables.md new file mode 100644 index 0000000..a9848e8 --- /dev/null +++ b/.changeset/brave-rfi-payables.md @@ -0,0 +1,16 @@ +--- +"@blindpay/node": minor +--- + +Cover the current BlindPay public API: + +- `blindpay.payables`: `list`, `create`, `get` and `delete`. +- `blindpay.instances.rfi` and `blindpay.customers.rfi`: `get` the open request for information and `submit` a response. `KycStatus` gains `"approved_rfi"`. +- `blindpay.instances.get()` and `blindpay.instances.onboarding`: `getBusinessDetails`, `getBusinessProfile` and `getOwnershipDocuments`. +- `blindpay.wallets.custodial.getDeposits()`, and `yield_status` on custodial wallets. +- `blindpay.upload.presign()` and `blindpay.upload.analyze()`. +- `blindpay.customers.bankAccounts.createPlaid()`. +- Customer `virtual_account_preapproval` and `cnae_condition`, and multiple `supporting_documents` on limit-increase requests. +- `CreateQuoteInput` now only requires `network` and `token`, so a quote can be created for a `payable_id` instead of a bank account. + +Endpoints the API marks `x-sdk: false` (yield, simulated SPEI/Bre-B deposits, card payments, ToS passthrough and `upload/extract`) stay out of the SDK. diff --git a/.changeset/customers-tos-upload.md b/.changeset/customers-tos-upload.md new file mode 100644 index 0000000..cd9b270 --- /dev/null +++ b/.changeset/customers-tos-upload.md @@ -0,0 +1,26 @@ +--- +"@blindpay/node": major +--- + +Customers, terms of service, upload and instances now match the API. + +**Breaking:** + +- `customers.update` requires `email` and `country`, as the API does. +- `UpdateCustomerInput.owners` is now `UpdateCustomerOwnerInput[]`: each owner needs the `id` of an existing owner, and every other field is optional. Before, the type had no way to send `id`, and the API rejects owners without one. +- `CreateBusinessWithStandardKYBInput.owners` is now `CreateCustomerOwnerInput[]`, which requires the fields the API requires (`tax_id` and `id_doc_front_file` can't be `null`) and makes `title`, `ownership_percentage`, `address_line_2`, `id_doc_back_file` and the proof of address fields optional. +- `GetCustomerResponse` and `ListCustomersResponse` now include `IndividualWithLightKYC` and `BusinessWithLightKYB`, the legacy `light` tier that migrated customers still carry. Code that narrows on `kyc_type` has to handle `"light"`. +- `date_of_birth` on individual customers and `formation_date` on business customers are now optional and can be `null`. +- Removed `aiprise_validation_key` from customer responses and `individual_holding_doc_front_file` from `IndividualWithEnhancedKYC`: the API never returns them. +- `BusinessIndustry` no longer includes `"336111"`, `"517110"`, `"523110"`, `"523920"` or the instance onboarding categories (`"dapp"`, `"exchange"`, `"gambling"`, `"gaming"`, `"infra"`, `"marketplace"`, `"neo_bank"`, `"other"`, `"saas"`, `"social"`, `"wallet"`). The API rejects them for customers and bank accounts. The onboarding categories stay in `InstanceBusinessIndustry`. +- `ListCustomersInput.status` is now `KycStatus` instead of `string`. +- `customers.update`, `customers.delete`, `instances.update`, `instances.delete`, `instances.deleteMember` and `instances.updateMemberRole` now resolve to `SuccessResponse` (`{ success: boolean }`) instead of `void`. + +**Additive:** + +- `upload.upload`, `upload.analyze` and `upload.presign` send the client's instance id when you don't pass `instance_id`. The API needs it for API key requests, and `PresignInput.instance_id` is now optional. +- `instances.tos.initiate` only requires `idempotency_key`; `customer_id` and `redirect_url` are optional. +- The create customer responses include `customer_id`. +- `BusinessWithStandardKYB` has `publicly_traded`. +- New exported types `CreateCustomerOwnerInput`, `UpdateCustomerOwnerInput`, `IndividualWithLightKYC`, `BusinessWithLightKYB` and `Customer` (the union of every customer variant). +- `MigrateInstanceOwnershipResponse` is now an alias of `SuccessResponse`. diff --git a/.changeset/error-envelope.md b/.changeset/error-envelope.md new file mode 100644 index 0000000..022f589 --- /dev/null +++ b/.changeset/error-envelope.md @@ -0,0 +1,5 @@ +--- +"@blindpay/node": minor +--- + +Errors carry the API's full error envelope. Besides `message`, `error` now has `code` (a stable code such as `PAYOUTS_INSUFFICIENT_BALANCE`, preferred for programmatic handling), `description` (safe to show to end users), `errors`, and `trace_id` (include it when contacting support) whenever the API sends them. diff --git a/.changeset/eur-wallet-tokens.md b/.changeset/eur-wallet-tokens.md new file mode 100644 index 0000000..2a43dfb --- /dev/null +++ b/.changeset/eur-wallet-tokens.md @@ -0,0 +1,8 @@ +--- +"@blindpay/node": minor +--- + +Transfers and custodial wallet balances accept and report the EUR stablecoins. + +- New shared type `WalletToken` (`"USDC" | "USDT" | "USDB" | "EURC" | "EURB"`) for tokens a custodial wallet holds or moves; the wallet deposits methods use it too. +- `CreateTransferQuoteInput.sender_token`/`customer_token`, `Transfer.sender_token`/`customer_token` and `WalletTokenBalance.symbol` now use `WalletToken`, so a transfer can convert between USDC and EURC (USDB and EURB on development instances). diff --git a/.changeset/idempotency-keys.md b/.changeset/idempotency-keys.md new file mode 100644 index 0000000..59bc13e --- /dev/null +++ b/.changeset/idempotency-keys.md @@ -0,0 +1,5 @@ +--- +"@blindpay/node": minor +--- + +Every method that creates, updates or deletes something takes an optional last argument, `{ idempotencyKey }`, sent as the `Idempotency-Key` header. Retrying with the same key and the same input replays the original response instead of acting twice (for example, a payout retried after a timeout is not created again). Keys are kept for 24 hours; file uploads and the unauthenticated terms-of-service route ignore them. diff --git a/.changeset/null-through-refs.md b/.changeset/null-through-refs.md new file mode 100644 index 0000000..ed0fa9e --- /dev/null +++ b/.changeset/null-through-refs.md @@ -0,0 +1,13 @@ +--- +"@blindpay/node": major +--- + +More fields the API can return or accept as `null` are typed that way: the spec marks them nullable through a reference or an `anyOf`, which the type sync used to miss. + +**Breaking:** + +- `Payable.bank_account`, and `cnae_condition` and `virtual_account_preapproval` on every customer type, can now be `null`. + +**Additive:** + +- `date_of_birth` on `CreateAchInput`, `CreateWireInput`, `CreateRtpInput` and `CreateInternationalSwiftInput`, and `date_of_birth`/`formation_date` on `UpdateCustomerInput`, accept `null`. diff --git a/.changeset/payins-wallets-fees.md b/.changeset/payins-wallets-fees.md new file mode 100644 index 0000000..d8b7bce --- /dev/null +++ b/.changeset/payins-wallets-fees.md @@ -0,0 +1,28 @@ +--- +"@blindpay/node": major +--- + +Aligned payins, virtual accounts, wallets, transfers, payables, billing fees and partner fees with the API. + +**Breaking:** + +- `VirtualAccount.us` can now be `null` or absent: Bre-B and SPEI virtual accounts return no US bank details. Inside it, only `wire` is always present; `ach`, `rtp`, `beneficiary`, `receiving_bank`, `swift_bic_code` and `account_type` can be `null` or absent, and `receiving_bank.address_line_2` can be `null`. `account_type` is now typed as `"Personal checking" | "Business checking"`. `blockchain_wallet.address` can be `null` or absent. +- `CreatePayinQuoteInput.blockchain_wallet_id`, `cover_fees` and `partner_fee_id` are now optional. +- Removed the unused `CreatePayinInput` type. Use `payins.createEvm(payin_quote_id)` to create a payin. +- `MintUsdbStellarInput.signedXdr` is now optional. +- `PrepareSolanaDelegationTransactionInput.token_address` and `amount` are now optional. +- `MintUsdbSolanaResponse.signature` and `error` are now optional. +- `WalletTokenBalance.earning_amount` and `total_amount` are now always present. +- `GetFeesResponse.faster_payments` is now a `FeeOptions` object instead of a string, and `sepa` is always present. `ted` can now be `null` or absent. +- Removed `evm_wallet_address` and `stellar_wallet_address` from `CreatePartnerFeeInput` and from the partner fee list, create and get responses. The API never accepted or returned them. +- `Payable.from`, `Payable.to`, `CreatePayableInput.from` and `CreatePayableInput.to` can now be `null`. +- `wallets.blockchain.delete`, `virtualAccounts.update`, `partnerFees.delete` and `wallets.blockchain.mintUsdbStellar` now resolve to `{ success: boolean }` (`SuccessResponse`) instead of `void`. +- `wallets.blockchain.mintUsdbSolana` now resolves to `MintUsdbSolanaResponse` instead of `void`. + +**Added:** + +- `payins.list` accepts the `customer_name`, `bank_account_id`, `country`, `payment_method`, `network` and `token` filters. +- `transfers.list` accepts the `customer_id`, `wallet_id`, `status`, `network` and `token` filters. +- `PrepareSolanaDelegationTransactionInput.quote_id`, the recommended way to prepare a delegation. +- `VirtualAccount.us.swift_intermediary_bank`. +- `wallets.custodial.delete` now uses the shared `SuccessResponse` type; its shape is unchanged. diff --git a/.changeset/payouts-bank-accounts.md b/.changeset/payouts-bank-accounts.md new file mode 100644 index 0000000..a43af3a --- /dev/null +++ b/.changeset/payouts-bank-accounts.md @@ -0,0 +1,23 @@ +--- +"@blindpay/node": major +--- + +Bank account and payout types now match the API. + +**Breaking:** + +- `bankAccounts.get` returns the same bank account shape as `bankAccounts.list` (new exported type `BankAccount`). The old `GetBankAccountResponse` fields the API never returned (`customer_id`, `account_holder_name`, `bank_name`, `swift_code`, `iban`, `is_primary`, `updated_at`) are gone. +- `bankAccounts.delete` and `payouts.submitDocuments` now resolve to `{ success: boolean }` (`SuccessResponse`). `SubmitPayoutDocumentsResponse` no longer has an `id`. +- `ListBankAccountsInput.status` only accepts a `BankAccountStatus` (`verifying`, `approved`, `rejected`, `deprecated`) instead of any string. +- `ListBankAccountsResponse[].swift_intermediary_bank_swift_code_bic` can be `null`. +- `ListBankAccountsResponse[].offramp_wallets[]` matches the API: `network` is any `OfframpWalletNetwork` (not only `"tron"`), `external_id` is optional and can be `null`, and `circle_wallet_id` is added. +- `createTed` requires `account_number` and `account_type`, which the API needs to create a TED account. +- On the payout tracking objects (`PayoutTrackingTransaction`, `PayoutTrackingPayment`, `PayoutTrackingLiquidity`, `PayoutTrackingComplete`, `PayoutTrackingPartnerFee`) only `step` is always present; every other key is now optional, since the API can leave it out. + +**Additive:** + +- New `bankAccounts.createFasterPayments` creates a UK Faster Payments bank account. +- `ListBankAccountsResponse` items carry the SEPA fields (`sepa_iban`, `sepa_beneficiary_legal_name`, beneficiary address, city, region, postal code and country). +- `CreateTedResponse` includes `account_number` and `account_type`. +- `payouts.list` accepts the `status`, `customer_name`, `bank_account_id`, `country`, `payment_method`, `network` and `token` filters. +- `payouts.createEvm`, `createStellar`, `createSolana` and `authorizeStellarToken` no longer require `sender_wallet_address`: pass it or a BlindPay-managed `wallet_id`. `createSolana`'s `signed_transaction` is optional. diff --git a/.changeset/plain-array-lists.md b/.changeset/plain-array-lists.md new file mode 100644 index 0000000..1f9321b --- /dev/null +++ b/.changeset/plain-array-lists.md @@ -0,0 +1,5 @@ +--- +"@blindpay/node": major +--- + +`payouts.list`, `customers.list` and `payables.list` responses are typed as either the paginated envelope or a plain array, like `payins.list` already was. The API returns every match as a plain array when no pagination parameter (`limit`, `starting_after`, `ending_before`) is passed, so code that reads `data.data` must first check `Array.isArray(data)`. diff --git a/.changeset/quiet-nulls-land.md b/.changeset/quiet-nulls-land.md new file mode 100644 index 0000000..7271126 --- /dev/null +++ b/.changeset/quiet-nulls-land.md @@ -0,0 +1,17 @@ +--- +"@blindpay/node": major +--- + +Types now match the OpenAPI spec's nullability and enums. + +**Breaking:** + +- Response fields the API can return as `null` are now typed `| null` (e.g. `VirtualAccount.kyc_status`, `Payout.tracking_liquidity`, `CreateQuoteResponse.expires_at`). Code that reads them without a null check stops compiling. This includes the shared `PaginationMetadata.next_page` and `.prev_page`, so every paginated `list` response is affected, and `PayoutTrackingTransaction.status`. +- Response fields that were a bare `string` now use the union the API guarantees: `GetRailsResponse[].country` (`Country`), `ListBankAccountsResponse[].spei_protocol` (`SpeiProtocol`), `.business_industry` (`BusinessIndustry`), `.status` (new `BankAccountStatus`), `IndividualWithEnhancedKYC.source_of_funds_doc_type` (`SourceOfFundsDocType`), and `Payout.ach_cop_document_type` (`AchCopDocument`). +- `BankingPartner` no longer includes `"ssb"`: the API stopped returning it. + +**Additive:** + +- Input fields the API accepts as `null` now allow `| null`. +- New enum members: 25 `BankDetailKey` values (SEPA, PIX Safe, TED and more), 9 `LimitIncreaseRequestSupportingDocumentType` values, `BusinessIndustry` `"446120"`, and `EstimatedTimeOfArrival` `"5_30_min"`. +- New exported type `BankAccountStatus`. diff --git a/.changeset/typed-webhook-events.md b/.changeset/typed-webhook-events.md new file mode 100644 index 0000000..c111191 --- /dev/null +++ b/.changeset/typed-webhook-events.md @@ -0,0 +1,13 @@ +--- +"@blindpay/node": major +--- + +**Breaking:** + +- `ListWebhookEndpointsResponse` items now type `last_event_at` as optional and `string | null`, matching the API: an endpoint that has not received an event yet has no `last_event_at`. +- `instances.webhookEndpoints.delete` now resolves to `SuccessResponse` (`{ success: boolean }`) instead of `void`. + +**Additive:** + +- Added `constructWebhookEvent({ secret, headers, payload })` on the client. It verifies the webhook signature like `verifyWebhookSignature` and returns the payload typed as `WebhookEvent`, or throws a `BlindPayError` when verification fails. Its parameter type is exported as `WebhookVerificationInput`, which `verifyWebhookSignature` now uses too. +- Added the `WebhookEvent` type, a union of every webhook payload discriminated by `webhook_event`, so a `switch` on `event.webhook_event` gives you that event's fields (for example `tos_id` on `tos.accept`). Each payload type is exported too, such as `TosAcceptWebhookEvent`, `CustomerDeleteWebhookEvent`, `WalletInboundWebhookEvent`, `PayinWebhookEvent` and `PayoutWebhookEvent`. diff --git a/.claude-pr/CLAUDE.md b/.claude-pr/CLAUDE.md deleted file mode 100644 index ac61959..0000000 --- a/.claude-pr/CLAUDE.md +++ /dev/null @@ -1,793 +0,0 @@ -# BlindPay Node SDK - Agent Reference - -## Commands - -``` -bun run build # Build with tsup (CJS + ESM + DTS) -bun run test # Run tests with vitest -bun run test:coverage # Run tests with coverage -bun run check-types # TypeScript type-check (no emit) -bun run lint:check # Biome lint + format check -bun run lint:fix # Biome auto-fix -``` - -## Project Structure - -``` -blindpay-node/ - package.json # @blindpay/node, bun package manager - tsconfig.json # Strict TS, ES6 target, ESNext modules - biome.json # Formatter + linter config - vitest.config.mts # Test config (globals, fetch mock setup) - vitest.setup.mts # Enables vitest-fetch-mock globally - .changeset/config.json # Changeset config (public access, main branch) - types/index.d.ts # Shared types (BlindpayApiResponse, enums, pagination) - src/ - index.ts # Re-exports all resources + client - client.ts # BlindPay class (constructor, HTTP methods, resource wiring) - internal/ - api-client.ts # InternalApiClient interface (get/post/put/patch/delete) - blindpay-error.ts # BlindPayError class - helpers/strict-omit.ts # StrictOmit utility type - vitest-fetch-mock.d.ts # Type declaration for fetch mock - resources/ - {resource-name}/ - index.ts # Types + factory function for the resource - {resource-name}.test.ts # Tests (colocated with resource) - wallets/ # Grouped sub-resources (no index.ts) - blockchain.ts # createBlockchainWalletsResource - blockchain.test.ts - custodial.ts # createCustodialWalletsResource - custodial.test.ts - offramp.ts # createOfframpWalletsResource - offramp.test.ts - payins/ - index.ts # createPayinsResource - quotes.ts # createPayinQuotesResource (sub-resource) - payins.test.ts - payins-quotes.test.ts -``` - -## Conventions - -### File naming - -- Resource directories: kebab-case matching the API path segment (`partner-fees`, `api-keys`, `bank-accounts`). -- Single-file resources inside a directory: `index.ts`. -- Grouped resources without their own parent: individual files (`wallets/blockchain.ts`, `wallets/custodial.ts`). -- Sub-resource files: placed inside the parent resource directory (`payins/quotes.ts`). -- Tests: `{resource-name}.test.ts` colocated next to the resource file. - -### Type naming - -All types are defined in the same file as the factory function, above it. Naming pattern: - -| Pattern | Example | -|---|---| -| Entity type | `Payin`, `Payout`, `CustodialWallet` | -| List input | `ListPayinsInput` | -| List response | `ListPayinsResponse` | -| Create input | `CreatePayinInput`, `CreatePartnerFeeInput` | -| Create response | `CreatePartnerFeeResponse` | -| Get input | `GetPayinInput` | -| Get response | `GetPayinResponse` | -| Update input | `UpdateReceiverInput` | -| Delete input | `DeleteReceiverInput` | -| String-only IDs | `export type GetPayinInput = string;` | -| Object inputs | `export type CreatePayoutInput = { ... };` | - -Types use `snake_case` field names matching the API JSON exactly. Never camelCase. - -### Factory function naming - -``` -create{PascalResourceName}Resource -``` - -Examples: `createPayinsResource`, `createPartnerFeesResource`, `createBlockchainWalletsResource`. - -### Method naming - -| HTTP operation | Method name | -|---|---| -| GET list | `list` | -| GET single | `get` | -| POST create | `create` | -| PUT update | `update` | -| DELETE | `delete` | -| Custom action | Descriptive camelCase: `getTrack`, `createEvm`, `submitDocuments`, `getLimits` | - -### Import style - -- Always use `import type` for type-only imports (enforced by biome `useImportType`). -- Shared types come from `../../../types` (the `types/index.d.ts` file). -- Internal API client: `import type { InternalApiClient } from "../../internal/api-client";` -- Path depth depends on file location. Resources at `src/resources/{name}/index.ts` use `../../internal/...` and `../../../types`. - -### Code style - -- Formatter: 4-space indent, double quotes, trailing commas (ES5), semicolons always, LF line endings, 100-char line width. -- Linter: Biome recommended rules. No unused variables (error). `import type` required (error). No explicit `any` (warn). -- TypeScript: `verbatimModuleSyntax: true` (must use `import type` for type-only imports). `strict: true`. - -## How to: Add a New Resource - -### Step 1: Create the resource file - -Create `src/resources/{resource-name}/index.ts`. - -Template for a standard instance-scoped resource: - -```typescript -import type { BlindpayApiResponse, PaginationMetadata, PaginationParams } from "../../../types"; -import type { InternalApiClient } from "../../internal/api-client"; - -// -- Entity type -- -export type Widget = { - id: string; - name: string; - instance_id: string; - created_at: string; - updated_at: string; -}; - -// -- Input/Output types -- -export type ListWidgetsInput = PaginationParams & { - status?: string; -}; - -export type ListWidgetsResponse = { - data: Widget[]; - pagination: PaginationMetadata; -}; - -export type CreateWidgetInput = { - name: string; - description?: string | null; -}; - -export type CreateWidgetResponse = { - id: string; -}; - -export type GetWidgetInput = string; - -export type GetWidgetResponse = Widget; - -export type UpdateWidgetInput = { - widget_id: string; - name?: string; -}; - -export type DeleteWidgetInput = string; - -// -- Factory function -- -export function createWidgetsResource(instanceId: string, client: InternalApiClient) { - return { - list(params?: ListWidgetsInput): Promise> { - const queryParams = params ? `?${new URLSearchParams(params)}` : ""; - return client.get(`/instances/${instanceId}/widgets${queryParams}`); - }, - create({ - ...data - }: CreateWidgetInput): Promise> { - return client.post(`/instances/${instanceId}/widgets`, data); - }, - get(id: GetWidgetInput): Promise> { - return client.get(`/instances/${instanceId}/widgets/${id}`); - }, - update({ widget_id, ...data }: UpdateWidgetInput): Promise> { - return client.put(`/instances/${instanceId}/widgets/${widget_id}`, data); - }, - delete(id: DeleteWidgetInput): Promise> { - return client.delete(`/instances/${instanceId}/widgets/${id}`); - }, - }; -} -``` - -For a resource NOT scoped to an instance (like `available`), omit `instanceId` from the factory signature: - -```typescript -export function createAvailableResource(client: InternalApiClient) { - return { - getRails(): Promise> { - return client.get("/available/rails"); - }, - }; -} -``` - -### Step 2: Register in `src/client.ts` - -1. Add the import at the top: -```typescript -import { createWidgetsResource } from "./resources/widgets"; -``` - -2. Add the property declaration to the `BlindPay` class: -```typescript -readonly widgets: ReturnType; -``` - -3. Initialize in the constructor body: -```typescript -this.widgets = createWidgetsResource(this.instanceId, this.api); -``` - -### Step 3: Re-export from `src/index.ts` - -Add one line: -```typescript -export * from "./resources/widgets"; -``` - -### Step 4: Create a test file - -Create `src/resources/widgets/widgets.test.ts`: - -```typescript -import { afterEach, describe, expect, it } from "vitest"; -import { BlindPay } from "../../client"; -import type { GetWidgetResponse, ListWidgetsResponse } from "."; - -describe("Widgets", () => { - afterEach(() => fetchMock.resetMocks()); - - const blindpay = new BlindPay({ apiKey: "test-key", instanceId: "in_000000000000" }); - - describe("List widgets", () => { - it("should list widgets", async () => { - const mockedWidgets: ListWidgetsResponse = { - data: [ - { - id: "wi_000000000000", - name: "Test Widget", - instance_id: "in_000000000000", - created_at: "2025-01-01T00:00:00Z", - updated_at: "2025-01-01T00:00:00Z", - }, - ], - pagination: { - has_more: false, - next_page: "", - prev_page: "", - }, - }; - - fetchMock.mockResponseOnce(JSON.stringify(mockedWidgets), { - headers: { "Content-Type": "application/json" }, - }); - - const { data, error } = await blindpay.widgets.list(); - - expect(error).toBeNull(); - expect(data).toEqual(mockedWidgets); - }); - }); - - describe("Get widget", () => { - it("should get a widget", async () => { - const mockedWidget: GetWidgetResponse = { - id: "wi_000000000000", - name: "Test Widget", - instance_id: "in_000000000000", - created_at: "2025-01-01T00:00:00Z", - updated_at: "2025-01-01T00:00:00Z", - }; - - fetchMock.mockResponseOnce(JSON.stringify(mockedWidget), { - headers: { "Content-Type": "application/json" }, - }); - - const { data, error } = await blindpay.widgets.get("wi_000000000000"); - - expect(error).toBeNull(); - expect(data).toEqual(mockedWidget); - }); - }); -}); -``` - -### Step 5: Create a changeset - -```bash -bunx changeset -``` - -Select `@blindpay/node`, choose `minor` for new features, and write a summary. - -Alternatively, create a file `.changeset/{random-name}.md` manually: - -```markdown ---- -"@blindpay/node": minor ---- - -Added widgets resource with list, create, get, update, and delete methods. -``` - -## How to: Add a Method to an Existing Resource - -### Step 1: Add types to the resource file - -Add the input and response types above the factory function in the resource's `index.ts`: - -```typescript -export type ActivateWidgetInput = string; - -export type ActivateWidgetResponse = { - id: string; - status: string; -}; -``` - -### Step 2: Add the method inside the factory function's return object - -```typescript -export function createWidgetsResource(instanceId: string, client: InternalApiClient) { - return { - // ... existing methods ... - activate( - id: ActivateWidgetInput - ): Promise> { - return client.post(`/instances/${instanceId}/widgets/${id}/activate`, {}); - }, - }; -} -``` - -### Step 3: Add tests and a changeset - -Follow the same test pattern. Add a `patch` changeset. - -## How to: Modify Types - -### Add a field to an existing type - -Add the field directly to the type definition. Use `snake_case`. Match the API response exactly. - -```typescript -export type Widget = { - id: string; - name: string; - description: string | null; // <-- new field - instance_id: string; - created_at: string; - updated_at: string; -}; -``` - -If the field is optional in the API response, use `?`: -```typescript - metadata?: Record | null; -``` - -### Remove a field - -Delete the field from the type definition. Search the codebase for any usage of that field. - -### Rename a field - -Change the field name in the type definition. This is a breaking change -- use a `major` changeset. - -### Shared types - -Types like `Currency`, `Network`, `StablecoinToken`, `TransactionStatus`, `PaginationParams`, `PaginationMetadata`, `BlindpayApiResponse`, and `Country` live in `types/index.d.ts`. If a new enum value needs to be added to a shared type (e.g., a new network), edit it there. - -## How to: Remove a Resource - -1. Delete the resource directory: `src/resources/{resource-name}/`. -2. Remove the import from `src/client.ts`. -3. Remove the property declaration from the `BlindPay` class. -4. Remove the initialization line from the constructor. -5. Remove the re-export line from `src/index.ts`. -6. Create a `major` changeset (breaking change). - -## How to: Add a Sub-Resource - -A sub-resource is nested under a parent on the client (e.g., `blindpay.payins.quotes`, `blindpay.instances.apiKeys`). - -### Step 1: Create the sub-resource file - -Place it inside the parent resource directory. For a sub-resource of `payins`: - -File: `src/resources/payins/quotes.ts` - -```typescript -import type { BlindpayApiResponse } from "../../../types"; -import type { InternalApiClient } from "../../internal/api-client"; - -export type CreatePayinQuoteInput = { - blockchain_wallet_id: string; - // ... -}; - -export type CreatePayinQuoteResponse = { - id: string; - // ... -}; - -export function createPayinQuotesResource(instanceId: string, client: InternalApiClient) { - return { - create({ - ...data - }: CreatePayinQuoteInput): Promise> { - return client.post(`/instances/${instanceId}/payin-quotes`, data); - }, - }; -} -``` - -### Step 2: Register in `src/client.ts` - -1. Import: -```typescript -import { createPayinQuotesResource } from "./resources/payins/quotes"; -``` - -2. Declare the type with intersection: -```typescript -readonly payins: ReturnType & { - quotes: ReturnType; -}; -``` - -3. Initialize with spread: -```typescript -this.payins = { - ...createPayinsResource(this.instanceId, this.api), - quotes: createPayinQuotesResource(this.instanceId, this.api), -}; -``` - -### Step 3: Re-export from `src/index.ts` - -```typescript -export * from "./resources/payins/quotes"; -``` - -### Grouped resources (no parent entity) - -For groupings like `wallets` where there is no parent `createWalletsResource`, each sub-resource is its own file and the parent is a plain object: - -```typescript -// Declaration -readonly wallets: { - blockchain: ReturnType; - offramp: ReturnType; - custodial: ReturnType; -}; - -// Initialization -this.wallets = { - blockchain: createBlockchainWalletsResource(this.instanceId, this.api), - offramp: createOfframpWalletsResource(this.instanceId, this.api), - custodial: createCustodialWalletsResource(this.instanceId, this.api), -}; -``` - -## Testing - -### Framework - -Vitest with `vitest-fetch-mock`. The `fetchMock` global is available in all test files (configured in `vitest.setup.mts`). Vitest globals (`describe`, `it`, `expect`, `afterEach`) are enabled. - -### Test file location - -Colocated with the resource file: -- `src/resources/payins/payins.test.ts` for `src/resources/payins/index.ts` -- `src/resources/wallets/blockchain.test.ts` for `src/resources/wallets/blockchain.ts` - -### Test pattern - -```typescript -import { afterEach, describe, expect, it } from "vitest"; -import { BlindPay } from "../../client"; -import type { ListWidgetsResponse } from "."; - -describe("Widgets", () => { - afterEach(() => fetchMock.resetMocks()); - - const blindpay = new BlindPay({ apiKey: "test-key", instanceId: "in_000000000000" }); - - describe("List widgets", () => { - it("should list widgets", async () => { - const mockedResponse: ListWidgetsResponse = { /* ... */ }; - - fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { - headers: { "Content-Type": "application/json" }, - }); - - const { data, error } = await blindpay.widgets.list(); - - expect(error).toBeNull(); - expect(data).toEqual(mockedResponse); - }); - }); -}); -``` - -Key rules: -- Always call `fetchMock.resetMocks()` in `afterEach`. -- Instantiate `BlindPay` with `apiKey: "test-key"` and `instanceId: "in_000000000000"`. -- Use `fetchMock.mockResponseOnce` with `JSON.stringify` and content-type header. -- Destructure `{ data, error }` from the result. -- Assert `error` is null and `data` matches the mock. - -### Running - -```bash -bun run test # All tests -bun run test:coverage # With coverage (excludes src/internal/** and src/index.ts) -``` - -## Versioning - -This project uses [Changesets](https://github.com/changesets/changesets). - -### Semantic versioning rules - -- `patch`: Bug fixes, type corrections, adding optional fields to existing types. -- `minor`: New resources, new methods on existing resources, new sub-resources. -- `major`: Removing resources/methods, renaming fields, removing fields, changing required/optional status of input fields. - -### Creating a changeset - -```bash -bunx changeset -``` - -Or manually create `.changeset/{name}.md`: - -```markdown ---- -"@blindpay/node": minor ---- - -Added widgets resource with CRUD methods. -``` - -The changeset file name should be a random short identifier (changesets CLI generates these automatically). - -### Configuration - -- `baseBranch`: `main` -- `access`: `public` (npm) -- `commit`: `false` (changesets do not auto-commit) - -## OpenAPI to SDK Mapping Rules - -This section defines exactly how an OpenAPI specification maps to SDK code. - -### Path to resource mapping - -| API path pattern | Resource location | Factory function | -|---|---|---| -| `/instances/{id}/widgets` | `src/resources/widgets/index.ts` | `createWidgetsResource` | -| `/instances/{id}/widgets/{widgetId}` | Same file as above | Same factory, different method | -| `/instances/{id}/widgets/{widgetId}/actions` | Same file if simple | Method in same factory | -| `/available/something` | `src/resources/available/index.ts` | `createAvailableResource` (no instanceId) | -| `/instances/{id}/parent/{parentId}/children` | `src/resources/children/index.ts` OR `src/resources/parent/children.ts` | `createChildrenResource` | -| `/e/widgets/{id}` | Same widget resource file | Method like `getTrack` (public/external endpoints) | - -### HTTP method to SDK method mapping - -| HTTP method | Path pattern | SDK method name | Notes | -|---|---|---|---| -| `GET` | `/instances/{id}/widgets` | `list` | Returns paginated response | -| `GET` | `/instances/{id}/widgets/{widgetId}` | `get` | Input is a string ID | -| `POST` | `/instances/{id}/widgets` | `create` | Input is an object | -| `PUT` | `/instances/{id}/widgets/{widgetId}` | `update` | Input destructures ID from body | -| `PATCH` | `/instances/{id}/widgets/{widgetId}` | `update` | Same pattern as PUT | -| `DELETE` | `/instances/{id}/widgets/{widgetId}` | `delete` | Input is a string ID | -| `POST` | `/instances/{id}/widgets/{widgetId}/action-name` | `actionName` | camelCase the action | -| `GET` | `/instances/{id}/widgets/{widgetId}/sub-thing` | `getSubThing` | camelCase with get prefix | - -### Request body to input type mapping - -OpenAPI request body schema fields map 1:1 to TypeScript type fields using `snake_case`: - -```yaml -# OpenAPI -requestBody: - content: - application/json: - schema: - type: object - required: [name, currency] - properties: - name: - type: string - currency: - type: string - enum: [USD, BRL, MXN] - description: - type: string - nullable: true -``` - -Maps to: - -```typescript -export type CreateWidgetInput = { - name: string; - currency: "USD" | "BRL" | "MXN"; - description?: string | null; -}; -``` - -Rules: -- Required fields: no `?`, no `| null` (unless the API explicitly allows null). -- Optional fields: use `?` and `| null` if nullable. -- String enums: use union literal types. -- Numbers: use `number`. -- Booleans: use `boolean`. -- Arrays: use `Array` or `T[]`. -- Nested objects: inline or define a separate type. -- Date strings: use `string`. - -### Response schema to output type mapping - -Response schemas map the same way. Every field from the API response becomes a type field: - -```yaml -# OpenAPI -responses: - 200: - content: - application/json: - schema: - type: object - properties: - id: - type: string - status: - type: string - enum: [processing, completed, failed] - created_at: - type: string - format: date-time -``` - -Maps to: - -```typescript -export type GetWidgetResponse = { - id: string; - status: "processing" | "completed" | "failed"; - created_at: string; -}; -``` - -### Query parameters to input type mapping - -Query parameters are merged into the input type using intersection with `PaginationParams`: - -```yaml -# OpenAPI -parameters: - - name: status - in: query - schema: - type: string - - name: limit - in: query - schema: - type: string - - name: offset - in: query - schema: - type: string -``` - -Maps to: - -```typescript -export type ListWidgetsInput = PaginationParams & { - status?: string; -}; -``` - -The method builds query params with `URLSearchParams`: - -```typescript -list(params?: ListWidgetsInput): Promise> { - const queryParams = params ? `?${new URLSearchParams(params)}` : ""; - return client.get(`/instances/${instanceId}/widgets${queryParams}`); -}, -``` - -### Path parameters - -Path parameters that are resource IDs are handled in two ways: - -1. **Single ID (the resource's own ID)**: passed as a plain string argument. -```typescript -get(id: GetWidgetInput): Promise> { - return client.get(`/instances/${instanceId}/widgets/${id}`); -}, -``` - -2. **Multiple IDs or ID + body**: destructured from an object input type. -```typescript -export type UpdateWidgetInput = { - widget_id: string; - name?: string; -}; - -update({ widget_id, ...data }: UpdateWidgetInput): Promise> { - return client.put(`/instances/${instanceId}/widgets/${widget_id}`, data); -}, -``` - -3. **Nested resource IDs**: all IDs come from the input object. -```typescript -export type GetOfframpWalletInput = { - receiver_id: string; - bank_account_id: string; - id: string; -}; - -get({ - receiver_id, - bank_account_id, - id, -}: GetOfframpWalletInput): Promise> { - return client.get( - `/instances/${instanceId}/receivers/${receiver_id}/bank-accounts/${bank_account_id}/offramp-wallets/${id}` - ); -}, -``` - -### Return type - -Every method returns `Promise>` where `T` is the response type. `BlindpayApiResponse` is a discriminated union: - -```typescript -type BlindpayApiResponse = { data: T; error: null } | { data: null; error: { message: string } } -``` - -For methods with no response body, use `Promise>`. - -### Discriminated/variant creation - -When one endpoint creates different variants based on a `type` field, create separate methods that hardcode the discriminator: - -```typescript -createIndividualWithStandardKYC( - data: CreateIndividualWithStandardKYCInput -): Promise> { - return client.post(`/instances/${instanceId}/receivers`, { - kyc_type: "standard", - type: "individual", - ...data, - }); -}, -``` - -### Object body destructuring pattern - -When passing an object body to `client.post`/`client.put`, use rest destructuring even when no fields need extracting: - -```typescript -create({ - ...data -}: CreateWidgetInput): Promise> { - return client.post(`/instances/${instanceId}/widgets`, data); -}, -``` - -This is the consistent pattern used throughout the codebase. - -### Summary: complete checklist for adding an OpenAPI endpoint - -1. Identify the API path and HTTP method. -2. Determine which resource file it belongs to (or create a new one). -3. Define the input type from request body schema + path params. -4. Define the response type from the response schema. -5. Add the method to the factory function's return object. -6. If new resource: register in `client.ts`, re-export from `index.ts`. -7. Add tests. -8. Add a changeset. -9. Run `bun run check-types && bun run lint:check && bun run test`. diff --git a/.github/workflows/api-sync-merged.yml b/.github/workflows/api-sync-merged.yml index 9ec73b6..3cd11f9 100644 --- a/.github/workflows/api-sync-merged.yml +++ b/.github/workflows/api-sync-merged.yml @@ -24,10 +24,11 @@ jobs: # Create a temporary worktree for the api-sync-data branch git checkout -B api-sync-data origin/api-sync-data 2>/dev/null || git checkout --orphan api-sync-data - # Remove the changelog (no longer needed) and update the baseline - # The baseline should be the spec that the SDK is now synced to - # We can't easily fetch blindpay-v2's spec from here, so we - # clear the last-synced-spec.json to signal "fully synced" + # This repo's patcher never reads these files, but blindpay-v2's + # sdk-sync.yml does: it takes .api-sync/last-synced-spec.json from + # this branch as the baseline for the prose changelog that drives + # blindpay-cli's generator. Clearing it here resets that baseline + # once a sync lands, so the next changelog is not cumulative forever. rm -f .api-sync/changelog.md rm -f .api-sync/last-synced-spec.json echo "Baseline cleared — SDK is in sync as of $(date -u +%Y-%m-%dT%H:%M:%SZ)" > .api-sync/SYNCED diff --git a/CLAUDE.md b/CLAUDE.md index f4e53b6..d2f3ccf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -28,12 +28,14 @@ blindpay-node/ internal/ api-client.ts # InternalApiClient interface (get/post/put/patch/delete) blindpay-error.ts # BlindPayError class + error-response.ts # toErrorResponse: API error envelope -> ErrorResponse helpers/strict-omit.ts # StrictOmit utility type vitest-fetch-mock.d.ts # Type declaration for fetch mock resources/ {resource-name}/ index.ts # Types + factory function for the resource {resource-name}.test.ts # Tests (colocated with resource) + request-options.test.ts # Fails on a mutation that doesn't forward RequestOptions wallets/ # Grouped sub-resources (no index.ts) blockchain.ts # createBlockchainWalletsResource blockchain.test.ts @@ -46,6 +48,9 @@ blindpay-node/ quotes.ts # createPayinQuotesResource (sub-resource) payins.test.ts payins-quotes.test.ts + webhooks/ + index.ts # Webhook endpoints and the WebhookEvents name union + events.ts # WebhookEvent: payload union keyed on webhook_event ``` ## Conventions @@ -110,6 +115,30 @@ Examples: `createPayinsResource`, `createPartnerFeesResource`, `createBlockchain - Linter: Biome recommended rules. No unused variables (error). `import type` required (error). No explicit `any` (warn). - TypeScript: `verbatimModuleSyntax: true` (must use `import type` for type-only imports). `strict: true`. +## Generate before you hand-write + +`scripts/api-sync/` is a deterministic patcher (no LLM) that reconciles the SDK against the OpenAPI spec. Anything it can produce must come from it, not from a hand-written (or model-written) edit: + +```bash +bun run sync -- --spec /tmp/openapi.public.json # apply against the current public spec (built below) +bun run sync:check # CI gate against the committed snapshot +bun run audit:types # informational full type audit +``` + +`.api-sync/spec-snapshot.json` is the spec the SDK last synced to, so applying against it only restores methods the SDK lost. To pick up a new endpoint, build the current public spec from blindpay-v2's committed `openapi.json` with blindpay-v2's own public filter (run inside a blindpay-v2 checkout): + +```bash +git fetch origin main +mkdir -p /tmp/v2 && git archive origin/main apps/api/openapi.json apps/api/src/shared/helpers scripts/openapi-public-filter.ts | tar -x -C /tmp/v2 +(cd /tmp/v2 && bun scripts/openapi-public-filter.ts --in apps/api/openapi.json --out /tmp/openapi.public.json) +``` + +Normally the api-sync workflow does this for you: blindpay-v2's `sdk-sync.yml` delivers the spec and dispatches the run. A successful `--apply` also refreshes the snapshot. + +It applies three kinds of change on its own: new enum members, new optional fields, and new methods for standard operations on an existing resource (instance-scoped path, JSON request and response, an existing `create{X}Resource(instanceId, client)` factory). For anything else it prints the exact reason it stopped. Only then use the manual recipes below: a brand-new resource, non-instance paths (`/available/*`, `/e/*`), multipart uploads, non-GET operations with query parameters, and resource files with a non-standard factory. After a manual change, `bun run sync:check` names any `.api-sync/spec-map.json` entry still missing. + +Deliberate differences from the spec are recorded in `.api-sync/unmodeled.json` with an owner and a reason. Never silence a finding by editing that file without the reason being true. + ## How to: Add a New Resource ### Step 1: Create the resource file @@ -119,7 +148,13 @@ Create `src/resources/{resource-name}/index.ts`. Template for a standard instance-scoped resource: ```typescript -import type { BlindpayApiResponse, PaginationMetadata, PaginationParams } from "../../../types"; +import type { + BlindpayApiResponse, + PaginationMetadata, + PaginationParams, + RequestOptions, + SuccessResponse, +} from "../../../types"; import type { InternalApiClient } from "../../internal/api-client"; // -- Entity type -- @@ -168,19 +203,26 @@ export function createWidgetsResource(instanceId: string, client: InternalApiCli const queryParams = params ? `?${new URLSearchParams(params)}` : ""; return client.get(`/instances/${instanceId}/widgets${queryParams}`); }, - create({ - ...data - }: CreateWidgetInput): Promise> { - return client.post(`/instances/${instanceId}/widgets`, data); + create( + { ...data }: CreateWidgetInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/widgets`, data, options); }, get(id: GetWidgetInput): Promise> { return client.get(`/instances/${instanceId}/widgets/${id}`); }, - update({ widget_id, ...data }: UpdateWidgetInput): Promise> { - return client.put(`/instances/${instanceId}/widgets/${widget_id}`, data); + update( + { widget_id, ...data }: UpdateWidgetInput, + options?: RequestOptions + ): Promise> { + return client.put(`/instances/${instanceId}/widgets/${widget_id}`, data, options); }, - delete(id: DeleteWidgetInput): Promise> { - return client.delete(`/instances/${instanceId}/widgets/${id}`); + delete( + id: DeleteWidgetInput, + options?: RequestOptions + ): Promise> { + return client.delete(`/instances/${instanceId}/widgets/${id}`, options); }, }; } @@ -329,9 +371,10 @@ export function createWidgetsResource(instanceId: string, client: InternalApiCli return { // ... existing methods ... activate( - id: ActivateWidgetInput + id: ActivateWidgetInput, + options?: RequestOptions ): Promise> { - return client.post(`/instances/${instanceId}/widgets/${id}/activate`, {}); + return client.post(`/instances/${instanceId}/widgets/${id}/activate`, {}, options); }, }; } @@ -395,7 +438,7 @@ Place it inside the parent resource directory. For a sub-resource of `payins`: File: `src/resources/payins/quotes.ts` ```typescript -import type { BlindpayApiResponse } from "../../../types"; +import type { BlindpayApiResponse, RequestOptions } from "../../../types"; import type { InternalApiClient } from "../../internal/api-client"; export type CreatePayinQuoteInput = { @@ -410,10 +453,11 @@ export type CreatePayinQuoteResponse = { export function createPayinQuotesResource(instanceId: string, client: InternalApiClient) { return { - create({ - ...data - }: CreatePayinQuoteInput): Promise> { - return client.post(`/instances/${instanceId}/payin-quotes`, data); + create( + { ...data }: CreatePayinQuoteInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/payin-quotes`, data, options); }, }; } @@ -530,7 +574,7 @@ This project uses [Changesets](https://github.com/changesets/changesets). - `patch`: Bug fixes, type corrections, adding optional fields to existing types. - `minor`: New resources, new methods on existing resources, new sub-resources. -- `major`: Removing resources/methods, renaming fields, removing fields, changing required/optional status of input fields. +- `major`: Removing resources/methods, renaming fields, removing fields, changing required/optional status of input fields, adding `| null` to a response field, narrowing a response field from `string` to a union, removing an enum member. ### Creating a changeset @@ -631,8 +675,9 @@ export type CreateWidgetInput = { ``` Rules: -- Required fields: no `?`, no `| null` (unless the API explicitly allows null). -- Optional fields: use `?` and `| null` if nullable. +- Required fields: no `?`. +- Optional fields: use `?`. +- Nullable fields (`type: [..., "null"]` in the spec): add `| null`, on inputs and responses alike. `sync:check` fails on a spec-nullable field whose SDK type has no `| null`. - String enums: use union literal types. - Numbers: use `number`. - Booleans: use `boolean`. @@ -729,8 +774,11 @@ export type UpdateWidgetInput = { name?: string; }; -update({ widget_id, ...data }: UpdateWidgetInput): Promise> { - return client.put(`/instances/${instanceId}/widgets/${widget_id}`, data); +update( + { widget_id, ...data }: UpdateWidgetInput, + options?: RequestOptions +): Promise> { + return client.put(`/instances/${instanceId}/widgets/${widget_id}`, data, options); }, ``` @@ -758,10 +806,15 @@ get({ Every method returns `Promise>` where `T` is the response type. `BlindpayApiResponse` is a discriminated union: ```typescript -type BlindpayApiResponse = { data: T; error: null } | { data: null; error: { message: string } } +type BlindpayApiResponse = { data: T; error: null } | { data: null; error: ErrorResponse } +// ErrorResponse: message, plus code, description, errors and trace_id when the API sends them ``` -For methods with no response body, use `Promise>`. +When the spec's 200 response is `$ref Success`, use `Promise>`. For methods with no response body, use `Promise>`. + +### Request options (Idempotency-Key) + +Every method that sends a POST, PUT, PATCH or DELETE takes a trailing `options?: RequestOptions` and passes it to the client as the last argument; `options.idempotencyKey` becomes the `Idempotency-Key` header. GET methods never take it, and neither do unauthenticated `/e/` routes (the API ignores the header there). `src/resources/request-options.test.ts` fails on a mutation that doesn't forward it, and the api-sync generator emits the same signature. ### Discriminated/variant creation @@ -769,13 +822,14 @@ When one endpoint creates different variants based on a `type` field, create sep ```typescript createIndividualWithStandardKYC( - data: CreateIndividualWithStandardKYCInput + data: CreateIndividualWithStandardKYCInput, + options?: RequestOptions ): Promise> { - return client.post(`/instances/${instanceId}/customers`, { - kyc_type: "standard", - type: "individual", - ...data, - }); + return client.post( + `/instances/${instanceId}/customers`, + { kyc_type: "standard", type: "individual", ...data }, + options + ); }, ``` @@ -784,10 +838,11 @@ createIndividualWithStandardKYC( When passing an object body to `client.post`/`client.put`, use rest destructuring even when no fields need extracting: ```typescript -create({ - ...data -}: CreateWidgetInput): Promise> { - return client.post(`/instances/${instanceId}/widgets`, data); +create( + { ...data }: CreateWidgetInput, + options?: RequestOptions +): Promise> { + return client.post(`/instances/${instanceId}/widgets`, data, options); }, ``` @@ -795,6 +850,7 @@ This is the consistent pattern used throughout the codebase. ### Summary: complete checklist for adding an OpenAPI endpoint +0. First run `bun run sync -- --spec /tmp/openapi.public.json` (see "Generate before you hand-write"); if it generated the method, skip to step 7. 1. Identify the API path and HTTP method. 2. Determine which resource file it belongs to (or create a new one). 3. Define the input type from request body schema + path params. @@ -803,9 +859,7 @@ This is the consistent pattern used throughout the codebase. 6. If new resource: register in `client.ts`, re-export from `index.ts`. 7. Add tests. 8. Add a changeset. -9. Run `bun run lint:fix && bun run check-types && bun run lint:check && bun run test`. +9. Run `bun run lint:fix && bun run check-types && bun run lint:check && bun run test && bun run sync:check`. Always run `lint:fix` first so Biome auto-applies formatter changes (trailing newlines, quote style, etc.); then `lint:check` validates - that nothing remains. Running only `lint:check` reports formatter - diffs as errors instead of fixing them — those are exactly the - issues api-sync runs were leaving behind. + that nothing remains. diff --git a/README.md b/README.md index a0d9db5..3895886 100644 --- a/README.md +++ b/README.md @@ -85,14 +85,57 @@ This SDK uses a consistent error handling pattern. Always check for errors: const { data, error } = await blindpay.payins.list(); if (error) { - // Handle error - console.error('API Error:', error.message); + // error.code is a stable code (e.g. PAYOUTS_INSUFFICIENT_BALANCE); error.description is + // safe to show to end users; include error.trace_id when contacting support. + console.error('API Error:', error.code ?? error.message); return; } console.log('Success:', data); // fully typed ``` +## Safe retries (idempotency) + +Every method that creates, updates or deletes something takes an optional last argument. Pass an `idempotencyKey` and a retry with the same key and the same input replays the original response instead of acting twice, for example when a timeout leaves you unsure whether a payout was created. Keys are kept for 24 hours. + +```typescript +import { randomUUID } from 'node:crypto'; + +const idempotencyKey = randomUUID(); // reuse it only to retry this same call + +const { data, error } = await blindpay.payouts.createEvm( + { quote_id: 'qu_000000000000', sender_wallet_address: '0x...' }, + { idempotencyKey } +); +``` + +## Webhooks + +`constructWebhookEvent` verifies the Svix signature and returns the payload typed by its `webhook_event`. It throws a `BlindPayError` when verification fails. Pass the raw request body, not a re-serialized object. + +```typescript +const event = blindpay.constructWebhookEvent({ + secret: process.env.BLINDPAY_WEBHOOK_SECRET as string, + headers: { + id: req.headers['svix-id'] as string, + timestamp: req.headers['svix-timestamp'] as string, + signature: req.headers['svix-signature'] as string, + }, + payload: rawBody, +}); + +switch (event.webhook_event) { + case 'tos.accept': + console.log('ToS accepted:', event.tos_id); + break; + case 'customer.update': + console.log('KYC status:', event.kyc_status); + break; +} +``` + +`verifyWebhookSignature` is still available when you only need a boolean. + For detailed API documentation, visit: - [BlindPay API documentation](https://blindpay.com/docs/getting-started/overview) - [API Reference](https://api.blindpay.com/reference) diff --git a/scripts/api-sync/apply.test.ts b/scripts/api-sync/apply.test.ts index 4ff3dda..6b04bc5 100644 --- a/scripts/api-sync/apply.test.ts +++ b/scripts/api-sync/apply.test.ts @@ -10,6 +10,14 @@ describe("insertEnumMember", () => { ); }); + it("inserts into a single-line union that has no trailing semicolon (valid in a .d.ts)", () => { + const src = 'export type PayinPaymentMethod = "ach" | "wire"\n\nexport type Other = "x";\n'; + const result = insertEnumMember(src, "PayinPaymentMethod", "pix"); + expect(result).toBe( + 'export type PayinPaymentMethod = "ach" | "wire" | "pix"\n\nexport type Other = "x";\n' + ); + }); + it("inserts into a one-member-per-line union, keeping the final `;` on the true last member", () => { const src = [ "export type WebhookEvents =", @@ -79,6 +87,14 @@ describe("insertOptionalField", () => { ); }); + it("indents a multi-line object type under the field it is inserted as", () => { + const src = "export type Account = {\n id: string;\n};\n"; + const result = insertOptionalField(src, "Account", "co", "{\n key: string;\n} | null"); + expect(result).toBe( + "export type Account = {\n id: string;\n co?: {\n key: string;\n } | null;\n};\n" + ); + }); + it("matches deeper sibling indentation, not a hardcoded 4 spaces", () => { const src = [ "export type Foo = {", diff --git a/scripts/api-sync/apply.ts b/scripts/api-sync/apply.ts index 0d5489b..fef3f8b 100644 --- a/scripts/api-sync/apply.ts +++ b/scripts/api-sync/apply.ts @@ -28,6 +28,9 @@ export function insertEnumMember(content: string, symbol: string, member: string const semiIdx = lines[declLineIdx].lastIndexOf(";"); lines[declLineIdx] = `${lines[declLineIdx].slice(0, semiIdx)} | "${member}"${lines[declLineIdx].slice(semiIdx)}`; + } else if (/=\s*"[^"]*"(\s*\|\s*"[^"]*")*\s*$/.test(lines[declLineIdx])) { + // single-line union with no trailing `;` (valid in a .d.ts): `export type X = "a" | "b"` + lines[declLineIdx] = `${lines[declLineIdx].trimEnd()} | "${member}"`; } else { // one-member-per-line union with a leading `|`; find the last such line (it carries the `;`). let lastMemberIdx = -1; @@ -92,7 +95,8 @@ export function insertOptionalField( } } - lines.splice(closingIdx, 0, `${indent}${field}?: ${tsType};`); + const typeText = tsType.split("\n").join(`\n${indent}`); + lines.splice(closingIdx, 0, `${indent}${field}?: ${typeText};`); const patched = lines.join("\n"); return content.slice(0, span.start) + patched + content.slice(span.end); } diff --git a/scripts/api-sync/audit.ts b/scripts/api-sync/audit.ts index 9d897ec..6fe3196 100644 --- a/scripts/api-sync/audit.ts +++ b/scripts/api-sync/audit.ts @@ -48,11 +48,9 @@ function categorize(problem: string): AuditFinding["category"] { /** * Full STATE-based comparison of every mapped property's spec type against its declared - * TypeScript type, including nullability, which the blocking `--check`/`--apply` path - * deliberately does not enforce (see reconcile.ts: this codebase does not mirror JSON - * nullability into `| null` on response fields as a matter of pervasive, pre-existing house - * style, not oversight; enforcing it retroactively is a separate, wholesale, human-reviewed - * pass, not a Phase A concern). Always non-blocking: this function only ever reports, it never + * TypeScript type. Unlike the blocking `--check`/`--apply` path (see reconcile.ts), it ignores + * known divergences, discriminator fields and enum-mapping coverage, so it also lists every + * deliberate narrowing. Always non-blocking: this function only ever reports, it never * throws or exits non-zero, so it is safe to run unconditionally in CI. Its purpose is exactly * the one state-based reconciliation exists for elsewhere in this tool: make sure the SDK's * CURRENT surface disagreeing with the CURRENT spec is never invisible, even when the disagreement @@ -85,7 +83,7 @@ export function auditTypes(spec: Spec, map: SpecMap, repoRoot: string): AuditFin for (const field of specProps) { const info = fields.get(field); if (!info) continue; - const specSig = specTypeSignature(resolveFieldNode(spec, entry.spec, field)); + const specSig = specTypeSignature(resolveFieldNode(spec, entry.spec, field), spec); const sdkSig = classifySdkType(info.typeExpr, repoRoot, site.file); const problems = compareTypeSignatures(specSig, sdkSig, { skipEnumValues: false }); for (const problem of problems) { diff --git a/scripts/api-sync/changeset.test.ts b/scripts/api-sync/changeset.test.ts index 6a92d7c..94c8025 100644 --- a/scripts/api-sync/changeset.test.ts +++ b/scripts/api-sync/changeset.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest"; -import { changesetFileName, classifyBump, renderChangeset } from "./changeset"; +import { changesetFileName, classifyBump, mergeChangeset, renderChangeset } from "./changeset"; describe("classifyBump", () => { it("is minor when any enum member was inserted", () => { @@ -56,3 +56,28 @@ describe("renderChangeset", () => { ); }); }); + +describe("mergeChangeset", () => { + const earlier = renderChangeset("@blindpay/node", "patch", ["add field b", "add field a"]); + + it("renders a fresh changeset when none exists for this spec", () => { + expect(mergeChangeset(null, "@blindpay/node", "minor", ["x"])).toBe( + renderChangeset("@blindpay/node", "minor", ["x"]) + ); + }); + + it("keeps the earlier run's changes when the same spec is applied again", () => { + expect( + mergeChangeset(earlier, "@blindpay/node", "minor", ["add enum c", "add field a"]) + ).toBe( + renderChangeset("@blindpay/node", "minor", ["add enum c", "add field a", "add field b"]) + ); + }); + + it("never lowers the earlier bump", () => { + const minor = renderChangeset("@blindpay/node", "minor", ["add enum c"]); + expect(mergeChangeset(minor, "@blindpay/node", "patch", ["add field a"])).toContain( + '"@blindpay/node": minor' + ); + }); +}); diff --git a/scripts/api-sync/changeset.ts b/scripts/api-sync/changeset.ts index fe8a39d..a0d3062 100644 --- a/scripts/api-sync/changeset.ts +++ b/scripts/api-sync/changeset.ts @@ -46,3 +46,22 @@ export function renderChangeset( "", ].join("\n"); } + +/** + * A second --apply against the same spec (say, after a spec-map fix lets the patcher reach + * more) writes to the same file, so it carries the earlier run's changes and bump forward + * instead of dropping them. + */ +export function mergeChangeset( + existing: string | null, + packageName: string, + bump: Exclude, + applied: string[] +): string { + if (existing === null) return renderChangeset(packageName, bump, applied); + // Both patterns read renderChangeset's own output: the bump line and the "- " bullets. + const mergedBump = /^".+": minor$/m.test(existing) ? "minor" : bump; + const earlierApplied = [...existing.matchAll(/^- (.+)$/gm)].map((match) => match[1]); + const merged = [...new Set([...earlierApplied, ...applied])].sort(); + return renderChangeset(packageName, mergedBump, merged); +} diff --git a/scripts/api-sync/diff.test.ts b/scripts/api-sync/diff.test.ts index 8ad866d..2966262 100644 --- a/scripts/api-sync/diff.test.ts +++ b/scripts/api-sync/diff.test.ts @@ -1,5 +1,9 @@ -import { describe, expect, it } from "vitest"; +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { afterEach, describe, expect, it } from "vitest"; import { detectNewOperations, detectNewSchemas, detectRemovals } from "./diff"; +import { clearSourceCache } from "./sdk-scan"; import type { Spec } from "./spec"; import type { SpecMap } from "./types"; @@ -7,6 +11,65 @@ function emptyMap(overrides: Partial = {}): SpecMap { return { enums: [], types: [], ignore: { schemas: [] }, ...overrides }; } +describe("detectRemovals against the SDK's current state", () => { + let dir: string | null = null; + afterEach(() => { + clearSourceCache(); + if (dir) rmSync(dir, { recursive: true, force: true }); + dir = null; + }); + + const specWith = (members: string[]): Spec => ({ + paths: {}, + components: { + schemas: { + VirtualAccountOut: { + type: "object", + properties: { banking_partner: { type: "string", enum: members } }, + }, + }, + }, + }); + const map: SpecMap = { + enums: [ + { + spec: { schema: "VirtualAccountOut", property: "banking_partner" }, + sdk: [{ file: "types.ts", symbol: "BankingPartner" }], + }, + ], + types: [], + ignore: { schemas: [] }, + }; + const repoDeclaring = (union: string) => { + dir = mkdtempSync(join(tmpdir(), "api-sync-diff-")); + writeFileSync(join(dir, "types.ts"), `export type BankingPartner = ${union};\n`); + return dir; + }; + + it("does not flag a removed member the SDK already dropped deliberately", () => { + const repo = repoDeclaring('"jpmorgan" | "citi"'); + const removed = detectRemovals( + specWith(["jpmorgan", "citi", "ssb"]), + specWith(["jpmorgan", "citi"]), + map, + repo + ); + expect(removed).toEqual([]); + }); + + it("still flags a removed member the SDK keeps declaring, naming only that member", () => { + const repo = repoDeclaring('"jpmorgan" | "ssb"'); + const removed = detectRemovals( + specWith(["jpmorgan", "citi", "ssb"]), + specWith(["jpmorgan"]), + map, + repo + ); + expect(removed).toHaveLength(1); + expect(removed[0]).toContain("lost member(s) [ssb]"); + }); +}); + describe("detectRemovals", () => { it("hard-fails when a mapped enum loses a member between the snapshot and the new spec", () => { const oldSpec: Spec = { diff --git a/scripts/api-sync/diff.ts b/scripts/api-sync/diff.ts index 4efdea4..816a599 100644 --- a/scripts/api-sync/diff.ts +++ b/scripts/api-sync/diff.ts @@ -1,3 +1,4 @@ +import { extractEnumMembers, findDeclarationSpan, readSource } from "./sdk-scan"; import { operationKeys, reachableSchemas, @@ -5,7 +6,7 @@ import { resolveProperties, type Spec, } from "./spec"; -import { isPathLocator, type SpecMap } from "./types"; +import { isPathLocator, type SdkSite, type SpecMap } from "./types"; function locatorLabel(loc: { schema?: string; @@ -17,13 +18,33 @@ function locatorLabel(loc: { return loc.property ? `${loc.schema}.${loc.property}` : (loc.schema as string); } +/** True if any of `sites` is a string-literal union that still lists `member`. An unreadable + * site counts as declaring it, so a removal is never hidden by a missing file. */ +function sdkDeclares(repoRoot: string, sites: SdkSite[], member: string): boolean { + return sites.some((site) => { + try { + const span = findDeclarationSpan(readSource(repoRoot, site.file), site.symbol); + return extractEnumMembers(span.text)?.has(member) ?? true; + } catch { + return true; + } + }); +} + /** * The only place old-vs-new spec diffing is used: catching something the state-based pass * cannot, by definition, ever see, a member/property that existed in the committed snapshot * and is simply gone from the newly delivered spec. Always a hard fail; removals are breaking - * and must be a deliberate major version bump, never automatic. + * and must be a deliberate major version bump, never automatic. With `repoRoot`, an enum member + * no mapped SDK union declares any more counts as already removed by hand, so only members the + * SDK still carries are reported. */ -export function detectRemovals(oldSpec: Spec, newSpec: Spec, map: SpecMap): string[] { +export function detectRemovals( + oldSpec: Spec, + newSpec: Spec, + map: SpecMap, + repoRoot?: string +): string[] { const messages: string[] = []; for (const entry of map.enums) { @@ -39,7 +60,10 @@ export function detectRemovals(oldSpec: Spec, newSpec: Spec, map: SpecMap): stri } catch { continue; // surfaced separately by reconcile() as "no longer resolves" } - const removed = [...oldMembers].filter((m) => !newMembers.has(m)).sort(); + const removed = [...oldMembers] + .filter((m) => !newMembers.has(m)) + .filter((m) => repoRoot === undefined || sdkDeclares(repoRoot, entry.sdk, m)) + .sort(); if (removed.length > 0) { messages.push( `enum "${locatorLabel(entry.spec)}" lost member(s) [${removed.join(", ")}] present in the committed snapshot; a removal needs a deliberate major version bump, not this patcher.` diff --git a/scripts/api-sync/index.ts b/scripts/api-sync/index.ts index 09eb59c..4cc82d8 100644 --- a/scripts/api-sync/index.ts +++ b/scripts/api-sync/index.ts @@ -11,11 +11,11 @@ import { insertTypeDeclarations, } from "./apply"; import { auditTypes } from "./audit"; -import { changesetFileName, classifyBump, renderChangeset } from "./changeset"; +import { changesetFileName, classifyBump, mergeChangeset } from "./changeset"; import { computeCoverageGaps } from "./coverage"; import { detectNewSchemas, detectRemovals } from "./diff"; import { findUnmappedEnumProperties } from "./enum-coverage"; -import { isIgnoredOperation, loadSpecMap, loadUnmodeled } from "./map"; +import { isIgnoredOperation, loadSpecMap, loadUnmodeled, withPendingMapEntries } from "./map"; import { classifyNewOperation, HTTP_METHODS, loadCanonicalEnums } from "./operation-gen"; import { reconcile } from "./reconcile"; import { readSource } from "./sdk-scan"; @@ -126,30 +126,8 @@ function writeReport(reportPath: string | null, report: SyncReport): void { * same schema/path locator so a second --apply against unchanged state stays byte-identical. */ function persistNewMapEntries(specMapPath: string, entries: NewSchemaMapEntry[]): void { if (entries.length === 0) return; - // biome-ignore lint/suspicious/noExplicitAny: raw spec-map.json JSON - const raw: any = JSON.parse(readFileSync(specMapPath, "utf8")); - for (const entry of entries) { - const locator = - entry.kind === "schema" - ? { schema: entry.schema } - : { path: entry.path, method: entry.method, location: entry.location }; - const existing = raw.types.find( - (t: { spec: Record }) => - JSON.stringify(t.spec) === JSON.stringify(locator) - ); - if (existing) { - if (!existing.sdk.some((s: { symbol: string }) => s.symbol === entry.symbol)) { - existing.sdk.push({ file: entry.file, symbol: entry.symbol }); - } - continue; - } - raw.types.push({ - spec: locator, - sdk: [{ file: entry.file, symbol: entry.symbol }], - notes: entry.notes, - }); - } - writeFileSync(specMapPath, `${JSON.stringify(raw, null, 4)}\n`); + const raw: SpecMap = JSON.parse(readFileSync(specMapPath, "utf8")); + writeFileSync(specMapPath, `${JSON.stringify(withPendingMapEntries(raw, entries), null, 4)}\n`); } function main(): void { @@ -180,7 +158,7 @@ function main(): void { } if (args.mode === "audit-types") { - // Full STATE-based comparison, including nullability; always non-blocking (see audit.ts). + // Full STATE-based comparison, deliberate narrowings included; always non-blocking (see audit.ts). const findings = auditTypes(spec, map, REPO_ROOT); console.log( `[api-sync] audit:types: ${findings.length} finding(s) (non-blocking, informational only).` @@ -218,13 +196,19 @@ function main(): void { changeSortKey(a) < changeSortKey(b) ? -1 : 1 ); - const removalMessages = detectRemovals(snapshot, spec, map); - const newSchemaMessages = detectNewSchemas(snapshot, spec, map); + const removalMessages = detectRemovals(snapshot, spec, map, REPO_ROOT); + // Judged against the map as this run will leave it, so schemas the operation-inserts above + // are about to map are not reported as needing a human. + const mapAfterInserts = withPendingMapEntries( + map, + operationGaps.applicable.flatMap((c) => c.newMapEntries) + ); + const newSchemaMessages = detectNewSchemas(snapshot, spec, mapAfterInserts); // Enum-constrained properties invisible to both the enum-insert patcher and the ordinary // field-type audit (chiefly anyOf/oneOf-wrapped enums): the exact bug class this system // exists to kill, so a new one hard-fails --check/--apply immediately instead of shipping // silently. See enum-coverage.ts. - const enumCoverageMessages = findUnmappedEnumProperties(spec, map, unmodeled).map( + const enumCoverageMessages = findUnmappedEnumProperties(spec, mapAfterInserts, unmodeled).map( (g) => `enum-constrained property "${g.schema}.${g.property}" (${g.kind}) is not mapped in spec-map.json's enums[], not covered by the ordinary field-type audit, and has no recorded omission in .api-sync/unmodeled.json's enumPropertyOmissions.` ); @@ -273,6 +257,9 @@ function main(): void { if (change.kind === "enum-insert") { after = insertEnumMember(before, change.site.symbol, change.member); } else if (change.kind === "field-insert") { + // A shared union is declared in types/index.d.ts itself, so that file never imports it. + const imports = file === "types/index.d.ts" ? [] : change.importsNeeded; + before = ensureSharedTypeImports(before, imports); after = insertOptionalField(before, change.site.symbol, change.field, change.tsType); } else { before = ensureSharedTypeImports(before, change.importsNeeded); @@ -306,7 +293,9 @@ function main(): void { const { name } = JSON.parse(readFileSync(packageJsonPath, "utf8")) as { name: string }; const specSha256 = createHash("sha256").update(readFileSync(args.specPath)).digest("hex"); changeset = `.changeset/${changesetFileName(specSha256)}`; - writeFileSync(resolve(REPO_ROOT, changeset), renderChangeset(name, bump, applied)); + const changesetPath = resolve(REPO_ROOT, changeset); + const existing = existsSync(changesetPath) ? readFileSync(changesetPath, "utf8") : null; + writeFileSync(changesetPath, mergeChangeset(existing, name, bump, applied)); } const report: SyncReport = { diff --git a/scripts/api-sync/map.test.ts b/scripts/api-sync/map.test.ts index 1513a53..33f2f90 100644 --- a/scripts/api-sync/map.test.ts +++ b/scripts/api-sync/map.test.ts @@ -1,7 +1,13 @@ import { resolve } from "node:path"; import { describe, expect, it } from "vitest"; import { findUnmappedEnumProperties } from "./enum-coverage"; -import { isKnownEnumDivergence, isUnmodeledProperty, loadSpecMap, loadUnmodeled } from "./map"; +import { + isKnownEnumDivergence, + isUnmodeledProperty, + loadSpecMap, + loadUnmodeled, + withPendingMapEntries, +} from "./map"; import { findUnmappedNestedShapes } from "./nested-coverage"; import { findDeclarationSpan, readSource } from "./sdk-scan"; import { @@ -11,7 +17,7 @@ import { resolveProperties, type Spec, } from "./spec"; -import { isPathLocator } from "./types"; +import { isPathLocator, type SpecMap } from "./types"; const REPO_ROOT = resolve(import.meta.dirname, "../.."); const map = loadSpecMap(resolve(REPO_ROOT, ".api-sync/spec-map.json")); @@ -99,3 +105,60 @@ describe("unmodeled.json validity", () => { } }); }); + +describe("withPendingMapEntries", () => { + const base: SpecMap = { + enums: [], + types: [ + { + spec: { schema: "PayinOut" }, + sdk: [{ file: "src/resources/payins/index.ts", symbol: "Payin" }], + }, + ], + ignore: { schemas: [] }, + }; + + it("adds a schema mapping and an inline-body path mapping the run is about to persist", () => { + const merged = withPendingMapEntries(base, [ + { + kind: "schema", + schema: "PlaidLinkOut", + file: "src/resources/bank-accounts/index.ts", + symbol: "CreatePlaidBankAccountResponse", + notes: null, + }, + { + kind: "path", + path: "/v1/instances/{instance_id}/widgets", + method: "get", + location: "response:200", + file: "src/resources/widgets/index.ts", + symbol: "ListWidgetsResponse", + notes: "inline", + }, + ]); + expect(merged.types.map((t) => t.spec)).toEqual([ + { schema: "PayinOut" }, + { schema: "PlaidLinkOut" }, + { + path: "/v1/instances/{instance_id}/widgets", + method: "get", + location: "response:200", + }, + ]); + }); + + it("adds a new SDK site to an existing locator once, and leaves the input untouched", () => { + const entry = { + kind: "schema" as const, + schema: "PayinOut", + file: "src/resources/payins/index.ts", + symbol: "GetPayinResponse", + notes: null, + }; + const merged = withPendingMapEntries(base, [entry, entry]); + expect(merged.types).toHaveLength(1); + expect(merged.types[0].sdk.map((s) => s.symbol)).toEqual(["Payin", "GetPayinResponse"]); + expect(base.types[0].sdk).toHaveLength(1); + }); +}); diff --git a/scripts/api-sync/map.ts b/scripts/api-sync/map.ts index 4e7e1ba..c280403 100644 --- a/scripts/api-sync/map.ts +++ b/scripts/api-sync/map.ts @@ -1,6 +1,13 @@ import { existsSync, readFileSync } from "node:fs"; import { join } from "node:path"; -import type { KnownDivergenceEntry, SpecMap, UnmodeledFile } from "./types"; +import type { + KnownDivergenceEntry, + NewSchemaMapEntry, + PathLocator, + SpecLocator, + SpecMap, + UnmodeledFile, +} from "./types"; export function loadSpecMap(path: string): SpecMap { const raw = JSON.parse(readFileSync(path, "utf8")); @@ -14,6 +21,36 @@ export function loadSpecMap(path: string): SpecMap { return raw; } +/** + * The map as it will look once this run's operation-inserts persist their new types[] entries. + * `--apply` judges new schemas and enum coverage against it, so a schema the generator is about + * to map is not reported as needing a human. Never mutates `map`. + */ +export function withPendingMapEntries>( + map: M, + entries: NewSchemaMapEntry[] +): M { + const types = map.types.map((t) => ({ ...t, sdk: [...t.sdk] })); + for (const entry of entries) { + const locator: SpecLocator = + entry.kind === "schema" + ? { schema: entry.schema } + : { + path: entry.path, + method: entry.method, + location: entry.location as PathLocator["location"], + }; + const site = { file: entry.file, symbol: entry.symbol }; + const existing = types.find((t) => JSON.stringify(t.spec) === JSON.stringify(locator)); + if (!existing) { + types.push({ spec: locator, sdk: [site], notes: entry.notes }); + } else if (!existing.sdk.some((t) => t.symbol === entry.symbol)) { + existing.sdk.push(site); + } + } + return { ...map, types }; +} + export function loadUnmodeled(path: string): UnmodeledFile { const raw = JSON.parse(readFileSync(path, "utf8")); if ( diff --git a/scripts/api-sync/operation-gen.golden.test.ts b/scripts/api-sync/operation-gen.golden.test.ts index 17c169e..8970213 100644 --- a/scripts/api-sync/operation-gen.golden.test.ts +++ b/scripts/api-sync/operation-gen.golden.test.ts @@ -62,7 +62,7 @@ function deleteTwoOperations(dir: string): void { quotes = deleteSpan(quotes, "export type CreateQuoteInput", "export type GetFxRateInput"); quotes = deleteSpan( quotes, - " create({ ...data }: CreateQuoteInput)", + " create(\n { ...data }: CreateQuoteInput,", " getFxRate(" ); writeFileSync(quotesPath, quotes); @@ -102,13 +102,15 @@ describe("operation-insert golden self-test", () => { ); const quotes = readFileSync(join(dir, "src/resources/quotes/index.ts"), "utf8"); - expect(quotes).toContain("bank_account_id: string;"); - expect(quotes).toContain("currency_type:"); - expect(quotes).toContain("request_amount: number;"); + expect(quotes).toContain("bank_account_id?: string | null;"); + expect(quotes).toContain("currency_type?:"); + expect(quotes).toContain("request_amount?: number | null;"); expect(quotes).toContain( - "create({ ...data }: CreateQuoteInput): Promise> {" + "create({ ...data }: CreateQuoteInput, options?: RequestOptions): Promise> {" + ); + expect(quotes).toContain( + "return client.post(`/instances/${instanceId}/quotes`, data, options);" ); - expect(quotes).toContain("return client.post(`/instances/${instanceId}/quotes`, data);"); execFileSync("bun", ["run", "check-types"], { cwd: dir, stdio: "pipe" }); execFileSync("bun", ["run", "test"], { cwd: dir, stdio: "pipe" }); diff --git a/scripts/api-sync/operation-gen.test.ts b/scripts/api-sync/operation-gen.test.ts index 0a8f4e7..f64a69b 100644 --- a/scripts/api-sync/operation-gen.test.ts +++ b/scripts/api-sync/operation-gen.test.ts @@ -99,6 +99,191 @@ describe("operation-insert classifier", () => { ); }); + it("passes a parent resource ID that precedes the resource segment (e.g. customer_id)", () => { + const repoRoot = makeRepo(baseFiles()); + const json = (schema: unknown) => ({ content: { "application/json": { schema } } }); + const object = { type: "object", properties: { url: { type: "string" } } }; + const path = "/v1/instances/{instance_id}/customers/{customer_id}/widgets/plaid"; + const spec: Spec = { + paths: { + [path]: { + post: { + parameters: [{ name: "customer_id", in: "path", required: true }], + requestBody: json(object), + responses: { "200": json(object) }, + }, + }, + }, + components: { schemas: {} }, + }; + const result = classifyNewOperation( + spec, + "post", + path, + emptyMap(), + repoRoot, + loadCanonicalEnums(repoRoot) + ); + expect(result.standard).toBe(true); + if (!result.standard) throw new Error("unreachable"); + expect(result.change.typeDecls).toContain("customer_id: string;"); + expect(result.change.methodSource).toContain("customer_id,"); + expect(result.change.methodSource).toContain( + "`/instances/${instanceId}/customers/${customer_id}/widgets/plaid`" + ); + }); + + describe("RequestOptions (the Idempotency-Key header)", () => { + const json = (schema: unknown) => ({ content: { "application/json": { schema } } }); + const object = { type: "object", properties: { url: { type: "string" } } }; + const classify = (method: string, path: string, op: Record) => { + const spec: Spec = { paths: { [path]: { [method]: op } }, components: { schemas: {} } }; + const repoRoot = makeRepo(baseFiles()); + const result = classifyNewOperation( + spec, + method, + path, + emptyMap(), + repoRoot, + loadCanonicalEnums(repoRoot) + ); + if (!result.standard) throw new Error(result.reason); + return result.change; + }; + + it("is the last parameter of a mutating method, forwarded to the client and imported", () => { + const change = classify("post", "/v1/instances/{instance_id}/widgets", { + requestBody: json(object), + responses: { "200": json(object) }, + }); + expect(change.methodSource).toContain( + "create({ ...data }: CreateWidgetInput, options?: RequestOptions)" + ); + expect(change.methodSource).toContain( + "return client.post(`/instances/${instanceId}/widgets`, data, options);" + ); + expect(change.importsNeeded).toContain("RequestOptions"); + }); + + it("is the only argument a DELETE by scalar id passes after its path", () => { + const change = classify("delete", "/v1/instances/{instance_id}/widgets/{id}", { + parameters: [{ name: "id", in: "path", required: true }], + responses: { "200": json(object) }, + }); + expect(change.methodSource).toContain(", options?: RequestOptions)"); + expect(change.methodSource).toContain( + "client.delete(`/instances/${instanceId}/widgets/${widgetId}`, options);" + ); + }); + + it("leaves a DELETE with a body to a human: the client's delete sends none", () => { + const spec: Spec = { + paths: { + "/v1/instances/{instance_id}/widgets/{id}": { + delete: { + parameters: [{ name: "id", in: "path", required: true }], + requestBody: json(object), + responses: { "200": json(object) }, + }, + }, + }, + components: { schemas: {} }, + }; + const repoRoot = makeRepo(baseFiles()); + const result = classifyNewOperation( + spec, + "delete", + "/v1/instances/{instance_id}/widgets/{id}", + emptyMap(), + repoRoot, + loadCanonicalEnums(repoRoot) + ); + expect(result.standard).toBe(false); + }); + + it("is never added to a GET", () => { + const change = classify("get", "/v1/instances/{instance_id}/widgets/{id}", { + parameters: [{ name: "id", in: "path", required: true }], + responses: { "200": json(object) }, + }); + expect(change.methodSource).not.toContain("RequestOptions"); + expect(change.importsNeeded).not.toContain("RequestOptions"); + }); + }); + + it("names a lone parent-ID scalar after its own parameter, not after the resource", () => { + const repoRoot = makeRepo(baseFiles()); + const path = "/v1/instances/{instance_id}/customers/{customer_id}/widgets"; + const spec: Spec = { + paths: { + [path]: { + get: { + parameters: [{ name: "customer_id", in: "path", required: true }], + responses: { + "200": { + content: { + "application/json": { schema: { type: "array", items: {} } }, + }, + }, + }, + }, + }, + }, + components: { schemas: {} }, + }; + const result = classifyNewOperation( + spec, + "get", + path, + emptyMap(), + repoRoot, + loadCanonicalEnums(repoRoot) + ); + expect(result.standard).toBe(true); + if (!result.standard) throw new Error("unreachable"); + expect(result.change.methodSource).toContain("(customerId: "); + expect(result.change.methodSource).toContain("/customers/${customerId}/widgets"); + }); + + it("keeps an acronym path segment like `tos` whole when naming the generated types", () => { + const repoRoot = makeRepo({ + ...baseFiles(), + "src/resources/terms-of-service/index.ts": `import type { BlindpayApiResponse } from "../../../types"; +import type { InternalApiClient } from "../../internal/api-client"; + +export function createTermsOfServiceResource(instanceId: string, client: InternalApiClient) { + return { + initiate(): Promise> { + return client.post(\`/e/instances/\${instanceId}/tos\`, {}); + }, + }; +} +`, + }); + const json = (schema: unknown) => ({ content: { "application/json": { schema } } }); + const object = { type: "object", properties: { tos_id: { type: "string" } } }; + const spec: Spec = { + paths: { + "/v1/instances/{instance_id}/tos/passthrough": { + post: { requestBody: json(object), responses: { "200": json(object) } }, + }, + }, + components: { schemas: {} }, + }; + const result = classifyNewOperation( + spec, + "post", + "/v1/instances/{instance_id}/tos/passthrough", + emptyMap(), + repoRoot, + loadCanonicalEnums(repoRoot) + ); + expect(result.standard).toBe(true); + if (!result.standard) throw new Error("unreachable"); + expect(result.change.typeDecls).toContain("export type CreatePassthroughTosInput"); + expect(result.change.typeDecls).toContain("export type CreatePassthroughTosResponse"); + }); + it("classifies a multipart/form-data request body as NON-STANDARD, never generated", () => { const repoRoot = makeRepo(baseFiles()); const spec: Spec = { diff --git a/scripts/api-sync/operation-gen.ts b/scripts/api-sync/operation-gen.ts index f91f291..6df6a62 100644 --- a/scripts/api-sync/operation-gen.ts +++ b/scripts/api-sync/operation-gen.ts @@ -36,7 +36,11 @@ function camelCase(segment: string): string { return p ? p[0].toLowerCase() + p.slice(1) : p; } +/** Path segments that end in "s" without being plurals (`tos` is terms of service). */ +const UNCOUNTABLE_SEGMENTS = new Set(["tos"]); + function singularize(segment: string): string { + if (UNCOUNTABLE_SEGMENTS.has(segment)) return segment; if (segment.endsWith("ies")) return `${segment.slice(0, -3)}y`; if (segment.endsWith("ss")) return segment; if (segment.endsWith("s")) return segment.slice(0, -1); @@ -196,6 +200,13 @@ export function classifyNewOperation( }; } + if (method === "delete" && op.requestBody) { + return { + standard: false, + reason: `"${method} ${path}" has a request body; the client's delete never sends one.`, + }; + } + const requestBodyKind = jsonContentOnly(op.requestBody?.content); if (requestBodyKind === "other") { return { @@ -220,9 +231,9 @@ export function classifyNewOperation( } const parameters: JsonValue[] = op.parameters ?? []; - // An *optional* header (e.g. every mutation's "Idempotency-Key") is never modeled by this - // SDK at all, on any existing hand-written method; only a REQUIRED header/cookie param is - // out of the generator's scope, since the template has nowhere to plumb it from. + // Optional headers aren't parameters of the generated method: every mutation's + // "Idempotency-Key" travels in its trailing RequestOptions. Only a REQUIRED header/cookie + // param is out of the generator's scope, since the template has nowhere to plumb it from. if (parameters.some((p) => (p.in === "header" || p.in === "cookie") && p.required)) { return { standard: false, @@ -271,10 +282,8 @@ export function classifyNewOperation( const segs = pathSegments(path); const rest = segs.slice(2); // drop "instances", "{instance_id}" const resourceIdx = rest.lastIndexOf(resourceSegment); - const pathParamNames = rest - .slice(resourceIdx + 1) - .filter((s) => s.startsWith("{")) - .map((s) => s.slice(1, -1)); + // Every path ID after the instance, parent resources' included (customers/{customer_id}/...). + const pathParamNames = rest.filter((s) => s.startsWith("{")).map((s) => s.slice(1, -1)); const extraLiteralSegments = rest.slice(resourceIdx + 1).filter((s) => !s.startsWith("{")); const isCollection = !rest[rest.length - 1]?.startsWith("{"); @@ -322,7 +331,7 @@ export function classifyNewOperation( })); const queryFields: Field[] = queryParams.map((p) => ({ name: p.name as string, - tsType: synthesizeType(ctx, p.schema, !!p.required), + tsType: synthesizeType(ctx, p.schema), required: !!p.required, })); @@ -337,7 +346,10 @@ export function classifyNewOperation( } else if (pathFields.length === 1 && !hasBody && queryFields.length === 0) { inputKind = "scalar"; inputSymbol = `${typePrefix}Input`; - scalarArgName = `${camelCase(singularize(resourceSegment))}Id`; + scalarArgName = + pathFields[0].name === "id" + ? `${camelCase(singularize(resourceSegment))}Id` + : camelCase(pathFields[0].name); } else { inputKind = "object"; inputSymbol = `${typePrefix}Input`; @@ -416,7 +428,10 @@ export function classifyNewOperation( methodName, typeDecls: typeDecls.trimEnd(), methodSource, - importsNeeded: [...ctx.importsNeeded].sort(), + importsNeeded: [ + ...ctx.importsNeeded, + ...(method === "get" ? [] : ["RequestOptions"]), + ].sort(), newMapEntries, }, }; @@ -466,15 +481,23 @@ function buildMethodSource(args: { pathTemplate, } = args; const returnType = `Promise>`; + // Every mutation takes RequestOptions last (its Idempotency-Key header); a GET never does. + const params = (input: string) => + method === "get" ? input : [input, "options?: RequestOptions"].filter(Boolean).join(", "); + const call = (body: "data" | "{}") => { + if (method === "get") return `client.get(\`${pathTemplate}\`)`; + if (method === "delete") return `client.delete(\`${pathTemplate}\`, options)`; + return `client.${method}(\`${pathTemplate}\`, ${body}, options)`; + }; if (inputKind === "none") { - return `${methodName}(): ${returnType} {\n return client.${method}(\`${pathTemplate}\`);\n },`; + return `${methodName}(${params("")}): ${returnType} {\n return ${call("{}")};\n },`; } if (inputKind === "scalar") { return ( - `${methodName}(${scalarArgName}: ${inputSymbol}): ${returnType} {\n` + - ` return client.${method}(\`${pathTemplate}\`);\n` + + `${methodName}(${params(`${scalarArgName}: ${inputSymbol}`)}): ${returnType} {\n` + + ` return ${call("{}")};\n` + ` },` ); } @@ -500,22 +523,22 @@ function buildMethodSource(args: { } if (pathFieldNames.length > 0 && hasBody) { return ( - `${methodName}({ ${pathFieldNames.join(", ")}, ...data }: ${inputSymbol}): ${returnType} {\n` + - ` return client.${method}(\`${pathTemplate}\`, data);\n` + + `${methodName}(${params(`{ ${pathFieldNames.join(", ")}, ...data }: ${inputSymbol}`)}): ${returnType} {\n` + + ` return ${call("data")};\n` + ` },` ); } if (pathFieldNames.length > 0 && !hasBody) { return ( - `${methodName}({ ${pathFieldNames.join(", ")} }: ${inputSymbol}): ${returnType} {\n` + - ` return client.${method}(\`${pathTemplate}\`);\n` + + `${methodName}(${params(`{ ${pathFieldNames.join(", ")} }: ${inputSymbol}`)}): ${returnType} {\n` + + ` return ${call("{}")};\n` + ` },` ); } // pathFieldNames.length === 0 && hasBody return ( - `${methodName}({ ...data }: ${inputSymbol}): ${returnType} {\n` + - ` return client.${method}(\`${pathTemplate}\`, data);\n` + + `${methodName}(${params(`{ ...data }: ${inputSymbol}`)}): ${returnType} {\n` + + ` return ${call("data")};\n` + ` },` ); } diff --git a/scripts/api-sync/reconcile.test.ts b/scripts/api-sync/reconcile.test.ts index 17a0734..a590c64 100644 --- a/scripts/api-sync/reconcile.test.ts +++ b/scripts/api-sync/reconcile.test.ts @@ -1,4 +1,4 @@ -import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { afterEach, describe, expect, it } from "vitest"; @@ -12,6 +12,7 @@ let dir: string | null = null; function makeRepo(files: Record): string { dir = mkdtempSync(join(tmpdir(), "api-sync-reconcile-")); for (const [rel, content] of Object.entries(files)) { + mkdirSync(join(dir, rel, ".."), { recursive: true }); writeFileSync(join(dir, rel), content); } return dir; @@ -163,6 +164,7 @@ describe("field-insertion (property reconciliation)", () => { property: undefined, field: "refund_wallet_address", tsType: "string | null", + importsNeeded: [], site: { file: "quotes.ts", symbol: "CreateQuoteInput" }, }, ]); @@ -302,6 +304,246 @@ describe("field-insertion (property reconciliation)", () => { }); }); +describe("field-insert of an enum-constrained property", () => { + const specWithField = (node: Record): Spec => ({ + paths: {}, + components: { + schemas: { BankAccountOut: { type: "object", properties: { country: node } } }, + }, + }); + const map: SpecMap = { + enums: [], + types: [ + { + spec: { schema: "BankAccountOut" }, + sdk: [{ file: "bank.ts", symbol: "BankAccount" }], + }, + ], + ignore: { schemas: [] }, + }; + const files = () => ({ + "bank.ts": "export type BankAccount = {\n id: string;\n};\n", + "types/index.d.ts": 'export type Country = "BR" | "US";\n', + }); + + it("reuses the shared union whose members match exactly, and asks for its import", () => { + const repo = makeRepo(files()); + const { applicable } = reconcile( + specWithField({ type: ["string", "null"], enum: ["US", "BR"] }), + map, + emptyUnmodeled(), + repo + ); + expect(applicable).toEqual([ + expect.objectContaining({ + kind: "field-insert", + field: "country", + tsType: "Country | null", + importsNeeded: ["Country"], + }), + ]); + }); + + it("compiles an object property's own properties instead of Record", () => { + const repo = makeRepo(files()); + const { applicable } = reconcile( + specWithField({ + type: ["object", "null"], + properties: { + key: { type: "string" }, + code: { type: "string", enum: ["BR", "US"] }, + }, + required: ["key"], + }), + map, + emptyUnmodeled(), + repo + ); + expect(applicable).toEqual([ + expect.objectContaining({ + tsType: "{\n key: string;\n code?: Country;\n} | null", + importsNeeded: ["Country"], + }), + ]); + }); + + it("keeps a free-form object (additionalProperties only) as Record", () => { + const repo = makeRepo(files()); + const { applicable } = reconcile( + specWithField({ type: ["object", "null"], additionalProperties: {} }), + map, + emptyUnmodeled(), + repo + ); + expect(applicable).toEqual([ + expect.objectContaining({ + tsType: "Record | null", + importsNeeded: [], + }), + ]); + }); + + describe("a property that references a component schema", () => { + const refSpec = (country: Record): Spec => ({ + paths: {}, + components: { + schemas: { + BankAccountOut: { type: "object", properties: { country } }, + TokenOut: { + type: "object", + properties: { amount: { type: "number" } }, + required: ["amount"], + }, + }, + }, + }); + const ref = { $ref: "#/components/schemas/TokenOut" }; + const token = "export type Token = {\n amount: number;\n};\n"; + const repoFiles = () => ({ + ...files(), + "bank.ts": `${files()["bank.ts"]}\n${token}`, + "other.ts": token, + }); + const mapWithToken = (file: string): SpecMap => ({ + ...map, + types: [ + ...map.types, + { spec: { schema: "TokenOut" }, sdk: [{ file, symbol: "Token" }] }, + ], + }); + + it("reuses the SDK symbol the schema is mapped to in the same file", () => { + const repo = makeRepo(repoFiles()); + const { applicable } = reconcile( + refSpec(ref), + mapWithToken("bank.ts"), + emptyUnmodeled(), + repo + ); + expect(applicable).toEqual([ + expect.objectContaining({ tsType: "Token", importsNeeded: [] }), + ]); + }); + + it("sees through an allOf that only wraps the reference with a description", () => { + const repo = makeRepo(repoFiles()); + const { applicable } = reconcile( + refSpec({ allOf: [ref, { description: "Only on some networks" }] }), + mapWithToken("bank.ts"), + emptyUnmodeled(), + repo + ); + expect(applicable).toEqual([expect.objectContaining({ tsType: "Token" })]); + }); + + it("compiles the referenced schema when it is not mapped in the target file", () => { + const repo = makeRepo(repoFiles()); + const { applicable } = reconcile( + refSpec(ref), + mapWithToken("other.ts"), + emptyUnmodeled(), + repo + ); + expect(applicable).toEqual([ + expect.objectContaining({ tsType: "{\n amount: number;\n}", importsNeeded: [] }), + ]); + }); + }); + + describe("an array property", () => { + it("compiles its items instead of unknown[]", () => { + const repo = makeRepo(files()); + const { applicable } = reconcile( + specWithField({ type: ["array", "null"], items: { type: "string" } }), + map, + emptyUnmodeled(), + repo + ); + expect(applicable).toEqual([ + expect.objectContaining({ tsType: "string[] | null", importsNeeded: [] }), + ]); + }); + + it("reuses the shared union for enum items, and asks for its import", () => { + const repo = makeRepo(files()); + const { applicable } = reconcile( + specWithField({ type: "array", items: { type: "string", enum: ["US", "BR"] } }), + map, + emptyUnmodeled(), + repo + ); + expect(applicable).toEqual([ + expect.objectContaining({ tsType: "Country[]", importsNeeded: ["Country"] }), + ]); + }); + + it("reuses the SDK symbol its item schema is mapped to in the same file", () => { + const repo = makeRepo({ + ...files(), + "bank.ts": `${files()["bank.ts"]}\nexport type Token = {\n amount: number;\n};\n`, + }); + const spec: Spec = { + paths: {}, + components: { + schemas: { + BankAccountOut: { + type: "object", + properties: { + country: { + type: ["array", "null"], + items: { $ref: "#/components/schemas/TokenOut" }, + }, + }, + }, + TokenOut: { + type: "object", + properties: { amount: { type: "number" } }, + required: ["amount"], + }, + }, + }, + }; + const withToken: SpecMap = { + ...map, + types: [ + ...map.types, + { spec: { schema: "TokenOut" }, sdk: [{ file: "bank.ts", symbol: "Token" }] }, + ], + }; + const { applicable } = reconcile(spec, withToken, emptyUnmodeled(), repo); + expect(applicable).toEqual([ + expect.objectContaining({ tsType: "Token[] | null", importsNeeded: [] }), + ]); + }); + }); + + it("keeps a boolean enum (e.g. `enum: [true]`) as boolean, matching the type check", () => { + const repo = makeRepo(files()); + const { applicable } = reconcile( + specWithField({ type: "boolean", enum: [true] }), + map, + emptyUnmodeled(), + repo + ); + expect(applicable).toEqual([ + expect.objectContaining({ tsType: "boolean", importsNeeded: [] }), + ]); + }); + + it("falls back to a literal union, never a bare string, when no shared union matches", () => { + const repo = makeRepo(files()); + const { applicable } = reconcile( + specWithField({ type: "string", enum: ["a", "b"] }), + map, + emptyUnmodeled(), + repo + ); + expect(applicable).toEqual([ + expect.objectContaining({ tsType: '"a" | "b"', importsNeeded: [] }), + ]); + }); +}); + describe("needs-human classifications", () => { it("a mapped schema locator that no longer resolves in the delivered spec", () => { const repo = makeRepo({ "x.ts": "export type X = { a: string };\n" }); @@ -371,6 +613,43 @@ describe("needs-human classifications", () => { expect(needsHuman[0]).toContain('spec is "number", SDK declares "string"'); }); + it("a spec-nullable field whose SDK type has no | null, on a required response field", () => { + const repo = makeRepo({ + "quotes.ts": [ + "export type CreateQuoteResponse = {", + " expires_at: number;", + "};", + "", + ].join("\n"), + }); + const spec: Spec = { + paths: {}, + components: { + schemas: { + QuoteOut: { + type: "object", + properties: { expires_at: { type: ["number", "null"] } }, + }, + }, + }, + }; + const map: SpecMap = { + enums: [], + types: [ + { + spec: { schema: "QuoteOut" }, + sdk: [{ file: "quotes.ts", symbol: "CreateQuoteResponse" }], + }, + ], + ignore: { schemas: [] }, + }; + const { applicable, needsHuman } = reconcile(spec, map, emptyUnmodeled(), repo); + expect(applicable).toEqual([]); + expect(needsHuman.length).toBe(1); + expect(needsHuman[0]).toContain("expires_at"); + expect(needsHuman[0]).toContain('spec allows null but the SDK type has no "| null"'); + }); + it("records a type-mismatch known divergence instead of failing", () => { const repo = makeRepo({ "payins.ts": [ diff --git a/scripts/api-sync/reconcile.ts b/scripts/api-sync/reconcile.ts index b76d606..9a25005 100644 --- a/scripts/api-sync/reconcile.ts +++ b/scripts/api-sync/reconcile.ts @@ -1,3 +1,5 @@ +import { existsSync } from "node:fs"; +import { join } from "node:path"; import { isKnownEnumDivergence, isKnownTypeMismatchDivergence, isUnmodeledProperty } from "./map"; import { extractEnumMembers, @@ -10,6 +12,14 @@ import { } from "./sdk-scan"; import { resolveEnumMembers, resolveLocator, resolveProperties, type Spec } from "./spec"; import { classifySdkType, compareTypeSignatures, specTypeSignature } from "./type-check"; +import { + loadCanonicalEnums, + loadWholeSchemaSymbols, + soleRefName, + synthesizeObjectLiteral, + type TypegenContext, + wrapArrayItem, +} from "./typegen"; import { type ApplicableChange, isPathLocator, @@ -48,18 +58,79 @@ function resolveFieldNode(spec: Spec, loc: SpecLocator, field: string): unknown return node?.properties?.[field]; } -function inferTsType(node: unknown): string { +/** + * TypeScript type for a field-insert at `siteFile`. A property referencing a component reuses the + * SDK symbol that component is mapped to in the same file; otherwise the component is compiled. + * An array applies the same rule to its items. + */ +function fieldInsertType( + node: unknown, + siteFile: string, + spec: Spec, + canonicalEnums: Map, + wholeSchemas: Map +): { tsType: string; importsNeeded: string[] } { + // biome-ignore lint/suspicious/noExplicitAny: raw OpenAPI schema node + const n = node as any; + const types: string[] = Array.isArray(n?.type) ? n.type : [n?.type]; + if (types.includes("array") && n.items) { + const item = fieldInsertType(n.items, siteFile, spec, canonicalEnums, wholeSchemas); + const list = wrapArrayItem(item.tsType); + return { ...item, tsType: types.includes("null") ? `${list} | null` : list }; + } + const ref = soleRefName(node); + if (!ref) return inferTsType(node, canonicalEnums, spec); + const whole = wholeSchemas.get(ref); + if (whole?.file === siteFile) return { tsType: whole.symbol, importsNeeded: [] }; + return inferTsType(spec.components.schemas[ref], canonicalEnums, spec); +} + +/** + * TypeScript type for a field-insert. A string enum becomes the shared types/index.d.ts union + * with exactly the same members (as the method generator does), else a literal union: never a + * bare `string`, which the type check would immediately reject as a dropped enum. + */ +function inferTsType( + node: unknown, + canonicalEnums: Map, + spec: Spec +): { tsType: string; importsNeeded: string[] } { // biome-ignore lint/suspicious/noExplicitAny: raw OpenAPI schema node const n = node as any; const rawType = n?.type; const types: string[] = Array.isArray(rawType) ? rawType : rawType ? [rawType] : []; const nullable = types.includes("null"); + const withNull = (base: string) => (nullable ? `${base} | null` : base); + // String enums only: the type check models enums as string unions (a boolean `enum: [true]` + // stays `boolean`). + const members: unknown[] = Array.isArray(n?.enum) + ? n.enum.filter((v: unknown) => typeof v === "string") + : []; + if (members.length > 0) { + const canonical = canonicalEnums.get(members.map(String).sort().join(",")); + if (canonical) return { tsType: withNull(canonical), importsNeeded: [canonical] }; + return { + tsType: withNull(members.map((v) => JSON.stringify(v)).join(" | ")), + importsNeeded: [], + }; + } + if (types.includes("object") && Object.keys(n?.properties ?? {}).length > 0) { + // Same compiler the method generator uses; nested refs are inlined, never imported. + const ctx: TypegenContext = { + spec, + canonicalEnums, + wholeSchemas: new Map(), + importsNeeded: new Set(), + }; + const literal = synthesizeObjectLiteral(ctx, n); + return { tsType: withNull(literal), importsNeeded: [...ctx.importsNeeded].sort() }; + } let base = "string"; if (types.includes("integer") || types.includes("number")) base = "number"; else if (types.includes("boolean")) base = "boolean"; else if (types.includes("object")) base = "Record"; else if (types.includes("array")) base = "unknown[]"; - return nullable ? `${base} | null` : base; + return { tsType: withNull(base), importsNeeded: [] }; } /** @@ -90,6 +161,10 @@ export function reconcile( const applicable: ApplicableChange[] = []; const needsHuman: string[] = []; const divergencesHit: string[] = []; + const canonicalEnums = existsSync(join(repoRoot, "types/index.d.ts")) + ? loadCanonicalEnums(repoRoot) + : new Map(); + const wholeSchemas = loadWholeSchemaSymbols(map); // (schema, property) pairs already covered by a dedicated enums[] mapping, so the type-check // pass below never double-reports an enum-member gap the enum-reconciliation pass already owns. @@ -228,14 +303,22 @@ export function reconcile( // to every declared union site above. Always optional (`field?: T`), matching spec: an // added property is never required on an already-shipped type, and emitting it as // non-optional would force every existing caller to start passing it. - const tsType = inferTsType(resolveFieldNode(spec, entry.spec, field)); + const node = resolveFieldNode(spec, entry.spec, field); for (const target of nonOpaqueSites) { + const { tsType, importsNeeded } = fieldInsertType( + node, + target.file, + spec, + canonicalEnums, + wholeSchemas + ); applicable.push({ kind: "field-insert", schema: schemaName, property: propertyName, field, tsType, + importsNeeded, site: target, }); } @@ -246,17 +329,14 @@ export function reconcile( // TypeScript type. A mismatch is never auto-applicable: silently rewriting a // consumer-facing type is exactly the kind of change that needs a human's eyes, so every // finding here is either a needs-human failure or (if pre-recorded) a known divergence. + // That includes nullability: a spec-nullable field must carry `| null` on every mapped + // site, inputs and responses alike, because making a response field nullable breaks + // consumers. // - // Scoped narrower than the full comparison `auditTypes` runs (see audit.ts): - // - nullability is not enforced here. This codebase does not mirror JSON nullability - // into `| null` on response fields as a matter of pervasive, pre-existing house - // style (hundreds of fields), not oversight; retrofitting that is a separate, - // wholesale, human-reviewed pass, not a Phase A concern. `bun run audit:types` - // reports it in full, non-blocking, for exactly that follow-up. - // - discriminator fields (DISCRIMINATOR_FIELDS) are skipped entirely; see its comment. + // Discriminator fields (DISCRIMINATOR_FIELDS) are skipped entirely; see its comment. for (const field of specProps) { if (missingSet.has(field) || DISCRIMINATOR_FIELDS.has(field)) continue; - const specSig = specTypeSignature(resolveFieldNode(spec, entry.spec, field)); + const specSig = specTypeSignature(resolveFieldNode(spec, entry.spec, field), spec); for (const [siteKey, fields] of fieldsBySite) { const info = fields.get(field); if (!info) continue; // this particular site doesn't carry the field (a fan-out variant) @@ -265,10 +345,7 @@ export function reconcile( const skipEnumValues = enumCovered.has(`${schemaName} ${field}`) || (!!sdkSig.namedAs && enumSymbolsCovered.has(sdkSig.namedAs)); - const problems = compareTypeSignatures(specSig, sdkSig, { - skipEnumValues, - skipNullability: true, - }); + const problems = compareTypeSignatures(specSig, sdkSig, { skipEnumValues }); for (const problem of problems) { if (isKnownTypeMismatchDivergence(unmodeled, schemaName, field)) { divergencesHit.push( diff --git a/scripts/api-sync/spec.test.ts b/scripts/api-sync/spec.test.ts new file mode 100644 index 0000000..abc8cf8 --- /dev/null +++ b/scripts/api-sync/spec.test.ts @@ -0,0 +1,120 @@ +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { afterEach, describe, expect, it } from "vitest"; +import { + loadSpec, + operationKeys, + reachableSchemas, + resolveProperties, + type Spec, + sdkSurface, +} from "./spec"; + +let dir: string | null = null; + +afterEach(() => { + if (dir) rmSync(dir, { recursive: true, force: true }); + dir = null; +}); + +const ref = (name: string) => ({ $ref: `#/components/schemas/${name}` }); +const json = (name: string) => ({ content: { "application/json": { schema: ref(name) } } }); + +function fixture(): Spec { + return { + paths: { + "/v1/instances/{instance_id}/wallets/{id}/deposits": { + get: { "x-sdk": true, responses: { "200": json("DepositsOut") } }, + }, + "/v1/instances/{instance_id}/wallets/{id}/yield": { + get: { "x-sdk": false, responses: { "200": json("YieldOut") } }, + }, + "/v1/instances/{instance_id}/wallets": { + get: { responses: { "200": json("WalletOut") } }, + post: { "x-sdk": false, requestBody: json("SimulateIn") }, + }, + }, + components: { + schemas: { + DepositsOut: { type: "object" }, + YieldOut: { type: "object", properties: { fee: ref("YieldFee") } }, + YieldFee: { type: "object" }, + WalletOut: { type: "object" }, + SimulateIn: { type: "object" }, + }, + }, + }; +} + +describe("sdkSurface", () => { + it("drops operations blindpay-v2 marks `x-sdk: false`, keeping flagged-true and unflagged ones", () => { + expect([...operationKeys(sdkSurface(fixture()))].sort()).toEqual([ + "get /v1/instances/{instance_id}/wallets", + "get /v1/instances/{instance_id}/wallets/{id}/deposits", + ]); + }); + + it("leaves schemas reachable only through excluded operations unreachable", () => { + expect([...reachableSchemas(sdkSurface(fixture()))].sort()).toEqual([ + "DepositsOut", + "WalletOut", + ]); + }); + + it("is what loadSpec returns, and never mutates its input", () => { + const input = fixture(); + sdkSurface(input); + expect(operationKeys(input).size).toBe(4); + + dir = mkdtempSync(join(tmpdir(), "api-sync-spec-")); + const path = join(dir, "spec.json"); + writeFileSync(path, JSON.stringify(input)); + expect(operationKeys(loadSpec(path)).size).toBe(2); + }); +}); + +describe("resolveProperties", () => { + it("reads the object branches of a list body that is either a page envelope or a bare array", () => { + const spec: Spec = { + paths: { + "/v1/instances/{instance_id}/payables": { + get: { + responses: { + "200": { + content: { + "application/json": { + schema: { + anyOf: [ + { + type: "object", + properties: { + data: { + type: "array", + items: ref("PayableOut"), + }, + pagination: { type: "object" }, + }, + }, + { type: "array", items: ref("PayableOut") }, + ], + }, + }, + }, + }, + }, + }, + }, + }, + components: { + schemas: { PayableOut: { type: "object", properties: { id: { type: "string" } } } }, + }, + }; + const loc = { + path: "/v1/instances/{instance_id}/payables", + method: "get", + location: "response:200", + }; + expect([...resolveProperties(spec, loc)].sort()).toEqual(["data", "pagination"]); + }); +}); diff --git a/scripts/api-sync/spec.ts b/scripts/api-sync/spec.ts index 1b72efd..bd57cdd 100644 --- a/scripts/api-sync/spec.ts +++ b/scripts/api-sync/spec.ts @@ -11,7 +11,27 @@ export type Spec = { }; export function loadSpec(path: string): Spec { - return JSON.parse(readFileSync(path, "utf8")); + return sdkSurface(JSON.parse(readFileSync(path, "utf8"))); +} + +/** + * The spec minus operations blindpay-v2 marks `x-sdk: false`. Every route there declares the + * flag (enforced by its check-sdk-tags.yml), and `false` means "exclude from the SDKs", so + * those operations, and schemas reachable only through them, are never gaps or new schemas. + */ +export function sdkSurface(spec: Spec): Spec { + const paths: Spec["paths"] = {}; + for (const [path, item] of Object.entries(spec.paths)) { + const kept = Object.fromEntries(Object.entries(item).filter(([, op]) => !isExcluded(op))); + if (Object.keys(kept).some((key) => HTTP_METHOD_KEYS.has(key))) paths[path] = kept; + } + return { ...spec, paths }; +} + +const HTTP_METHOD_KEYS = new Set(["get", "post", "put", "patch", "delete"]); + +function isExcluded(op: JsonValue): boolean { + return typeof op === "object" && op !== null && op["x-sdk"] === false; } function collectRefs(node: JsonValue, out: Set): void { @@ -108,6 +128,12 @@ function propsOf(spec: Spec, node: JsonValue): Set { const item = resolveRef(spec, node.items); return new Set(Object.keys(item?.properties ?? {})); } + const branches = node?.anyOf ?? node?.oneOf; + if (!node?.properties && Array.isArray(branches)) { + // A list body is a page envelope or a bare array; the envelope is the shape to compare. + const objects = branches.map((b) => resolveRef(spec, b)).filter((b) => !isArrayType(b)); + return new Set(objects.flatMap((b) => Object.keys(b?.properties ?? {}))); + } return new Set(Object.keys(node?.properties ?? {})); } diff --git a/scripts/api-sync/type-check.test.ts b/scripts/api-sync/type-check.test.ts index c1145d1..21bbf7c 100644 --- a/scripts/api-sync/type-check.test.ts +++ b/scripts/api-sync/type-check.test.ts @@ -33,24 +33,67 @@ describe("string to integer (base-kind mismatch)", () => { }); describe("nullable to non-nullable / non-nullable to nullable", () => { - it("flags when spec allows null but the SDK type has no | null (nullability checked)", () => { + it("flags when spec allows null but the SDK type has no | null", () => { const spec = specTypeSignature({ type: ["string", "null"] }); const sdk = classifySdkType("string", "/unused", "unused.ts"); - const problems = compareTypeSignatures(spec, sdk, { - skipEnumValues: false, - skipNullability: false, - }); + const problems = compareTypeSignatures(spec, sdk, { skipEnumValues: false }); expect(problems).toEqual(['spec allows null but the SDK type has no "| null"']); }); - it("does not flag nullability when the blocking pass explicitly skips it (this repo's own house style)", () => { + it("accepts a nullable spec field whose SDK type carries | null", () => { const spec = specTypeSignature({ type: ["string", "null"] }); - const sdk = classifySdkType("string", "/unused", "unused.ts"); - const problems = compareTypeSignatures(spec, sdk, { + const sdk = classifySdkType("string | null", "/unused", "unused.ts"); + const problems = compareTypeSignatures(spec, sdk, { skipEnumValues: false }); + expect(problems).toEqual([]); + }); +}); + +describe("nullability expressed through a reference or a composition", () => { + const spec = { + paths: {}, + components: { + schemas: { + PayableParty: { type: ["object", "null"], properties: {} }, + FeeOptions: { type: "object", properties: {} }, + }, + }, + }; + const ref = (name: string) => ({ $ref: `#/components/schemas/${name}` }); + + it("reads it from the referenced schema", () => { + expect(specTypeSignature(ref("PayableParty"), spec).nullable).toBe(true); + expect(specTypeSignature(ref("FeeOptions"), spec).nullable).toBe(false); + }); + + it("reads it from an anyOf/oneOf null branch", () => { + const node = { anyOf: [{ type: "string", format: "date-time" }, { type: "null" }] }; + expect(specTypeSignature(node, spec).nullable).toBe(true); + expect( + specTypeSignature({ oneOf: [ref("FeeOptions"), { type: "null" }] }, spec).nullable + ).toBe(true); + }); + + it("stops at a reference cycle instead of recursing forever", () => { + const cyclic = { + paths: {}, + components: { + schemas: { A: { anyOf: [{ $ref: "#/components/schemas/A" }, { type: "null" }] } }, + }, + }; + expect(specTypeSignature(ref("A"), cyclic).nullable).toBe(true); + }); + + it("reads it from an allOf that wraps a reference in a nullable object", () => { + const node = { allOf: [ref("FeeOptions"), { type: ["object", "null"] }] }; + expect(specTypeSignature(node, spec).nullable).toBe(true); + }); + + it("flags the SDK type that drops it", () => { + const sdk = classifySdkType("PayableParty", "/unused", "unused.ts"); + const problems = compareTypeSignatures(specTypeSignature(ref("PayableParty"), spec), sdk, { skipEnumValues: false, - skipNullability: true, }); - expect(problems).toEqual([]); + expect(problems).toContain('spec allows null but the SDK type has no "| null"'); }); }); diff --git a/scripts/api-sync/type-check.ts b/scripts/api-sync/type-check.ts index f415bff..990d988 100644 --- a/scripts/api-sync/type-check.ts +++ b/scripts/api-sync/type-check.ts @@ -7,6 +7,7 @@ import { QUOTED_UNION_LIST_SOURCE, readSource, } from "./sdk-scan"; +import type { JsonValue, Spec } from "./spec"; export { extractTopLevelFields, type FieldInfo } from "./sdk-scan"; @@ -19,12 +20,12 @@ export type TypeSignature = { namedAs?: string; }; -export function specTypeSignature(node: unknown): TypeSignature { +export function specTypeSignature(node: unknown, spec?: Spec): TypeSignature { // biome-ignore lint/suspicious/noExplicitAny: raw OpenAPI schema node const n = node as any; const raw = n?.type; const types: string[] = Array.isArray(raw) ? raw : raw ? [raw] : []; - const nullable = types.includes("null"); + const nullable = types.includes("null") || alternatives(n, spec).some(allowsNull); const nonNull = types.filter((t) => t !== "null"); let baseKind: TypeSignature["baseKind"] = "unknown"; if (nonNull.includes("string")) baseKind = "string"; @@ -36,6 +37,28 @@ export function specTypeSignature(node: unknown): TypeSignature { return { baseKind, nullable, enumValues }; } +/** + * The schemas a property node stands for, through a $ref and across anyOf/oneOf/allOf branches. + * blindpay-v2 writes a nullable reference as `allOf: [ref, { type: ["object", "null"] }]` or an + * anyOf with a `{ type: "null" }` branch, so null can sit on any of them. + */ +function alternatives(node: JsonValue, spec?: Spec, seen = new Set()): JsonValue[] { + if (typeof node?.$ref === "string" && spec) { + const name = node.$ref.split("/").pop(); + if (seen.has(name)) return []; + seen.add(name); + return alternatives(spec.components.schemas[name], spec, seen); + } + const branches = node?.anyOf ?? node?.oneOf ?? node?.allOf; + if (Array.isArray(branches)) return branches.flatMap((b) => alternatives(b, spec, seen)); + return [node]; +} + +function allowsNull(node: JsonValue): boolean { + const type = node?.type; + return type === "null" || (Array.isArray(type) && type.includes("null")); +} + /** Resolves `name` as a string-literal union: same file first, then types/index.d.ts, then any resource file. */ export function resolveNamedUnion( repoRoot: string, @@ -159,7 +182,7 @@ export function classifySdkType( export function compareTypeSignatures( spec: TypeSignature, sdk: TypeSignature, - opts: { skipEnumValues: boolean; skipNullability?: boolean } = { skipEnumValues: false } + opts: { skipEnumValues: boolean } = { skipEnumValues: false } ): string[] { const problems: string[] = []; @@ -174,7 +197,7 @@ export function compareTypeSignatures( return problems; // a base-kind mismatch makes enum/nullability comparisons meaningless } - if (!opts.skipNullability && spec.nullable && !sdk.nullable) { + if (spec.nullable && !sdk.nullable) { problems.push('spec allows null but the SDK type has no "| null"'); } diff --git a/scripts/api-sync/typegen.ts b/scripts/api-sync/typegen.ts index 0a74a99..10395c7 100644 --- a/scripts/api-sync/typegen.ts +++ b/scripts/api-sync/typegen.ts @@ -12,6 +12,17 @@ function resolveRef(spec: Spec, node: JsonValue): JsonValue { return node; } +/** The component a property points at: a bare $ref, or an allOf that only annotates one. */ +export function soleRefName(node: JsonValue): string | null { + const direct = refName(node); + if (direct || !Array.isArray(node?.allOf)) return direct; + const refs = node.allOf.map(refName).filter((r: string | null) => r !== null); + const structural = node.allOf.filter( + (m: JsonValue) => !refName(m) && (m?.type || m?.properties || m?.allOf || m?.anyOf) + ); + return refs.length === 1 && structural.length === 0 ? refs[0] : null; +} + function refName(node: JsonValue): string | null { if (node && typeof node === "object" && typeof node.$ref === "string") { return node.$ref.split("/").pop() as string; @@ -69,21 +80,19 @@ function quoteUnion(values: unknown[]): string { return values.map((v) => JSON.stringify(v)).join(" | "); } -function wrapArrayItem(itemType: string): string { +export function wrapArrayItem(itemType: string): string { return itemType.includes("|") ? `(${itemType})[]` : `${itemType}[]`; } /** - * Recursively compiles a raw OpenAPI schema node into a TypeScript type expression, matching - * this codebase's existing hand-written house style: - * - required object properties are non-optional and drop the spec's nullability (matching - * e.g. CreateQuoteResponse's required `expires_at: number`, spec type `["number","null"]`). - * - optional properties keep `?` and, if the spec node itself is nullable, append `| null`. + * Recursively compiles a raw OpenAPI schema node into a TypeScript type expression: + * - required object properties are non-optional; optional ones keep `?`. + * - a nullable spec node appends `| null`, required or not (reconcile.ts enforces this). * - string enums become a literal union, or the canonical shared symbol if one already * declares the exact same value set (e.g. spec inlines Network's values -> `Network`). * - a $ref to a schema already mapped whole in spec-map.json reuses that SDK symbol. */ -export function synthesizeType(ctx: TypegenContext, node: JsonValue, required: boolean): string { +export function synthesizeType(ctx: TypegenContext, node: JsonValue): string { const named = refName(node); if (named) { const whole = ctx.wholeSchemas.get(named); @@ -93,10 +102,10 @@ export function synthesizeType(ctx: TypegenContext, node: JsonValue, required: b } } const resolved = resolveRef(ctx.spec, node); - return synthesizeResolvedType(ctx, resolved, required); + return synthesizeResolvedType(ctx, resolved); } -function synthesizeResolvedType(ctx: TypegenContext, node: JsonValue, required: boolean): string { +function synthesizeResolvedType(ctx: TypegenContext, node: JsonValue): string { if (node === undefined || node === null) return "unknown"; if (Array.isArray(node.enum) && node.enum.length > 0) { @@ -104,38 +113,34 @@ function synthesizeResolvedType(ctx: TypegenContext, node: JsonValue, required: const canonical = ctx.canonicalEnums.get(sig); const base = canonical ?? quoteUnion(node.enum); if (canonical) ctx.importsNeeded.add(canonical); - return nullableSuffix(node, base, required); + return nullableSuffix(node, base); } const rawTypes: string[] = Array.isArray(node.type) ? node.type : node.type ? [node.type] : []; const nonNull = rawTypes.filter((t) => t !== "null"); if (nonNull.includes("array")) { - const itemType = node.items ? synthesizeType(ctx, node.items, true) : "unknown"; - return nullableSuffix(node, wrapArrayItem(itemType), required); + const itemType = node.items ? synthesizeType(ctx, node.items) : "unknown"; + return nullableSuffix(node, wrapArrayItem(itemType)); } if (nonNull.includes("object") || node.properties) { - return nullableSuffix(node, synthesizeObjectLiteral(ctx, node), required); + return nullableSuffix(node, synthesizeObjectLiteral(ctx, node)); } if (nonNull.includes("integer") || nonNull.includes("number")) { - return nullableSuffix(node, "number", required); + return nullableSuffix(node, "number"); } if (nonNull.includes("boolean")) { - return nullableSuffix(node, "boolean", required); + return nullableSuffix(node, "boolean"); } if (nonNull.includes("string")) { - return nullableSuffix(node, "string", required); + return nullableSuffix(node, "string"); } return "unknown"; } -function nullableSuffix(node: JsonValue, base: string, required: boolean): string { +function nullableSuffix(node: JsonValue, base: string): string { const rawTypes: string[] = Array.isArray(node.type) ? node.type : node.type ? [node.type] : []; - const nullable = rawTypes.includes("null"); - // House style (see reconcile.ts DISCRIMINATOR_FIELDS comment block): a *required* field drops - // spec nullability entirely; only an *optional* field's `?` carries `| null` alongside it. - if (nullable && !required) return `${base} | null`; - return base; + return rawTypes.includes("null") ? `${base} | null` : base; } /** Compiles an object schema's properties into `{ a: T; b?: U; }`, one property per line. */ @@ -145,7 +150,7 @@ export function synthesizeObjectLiteral(ctx: TypegenContext, node: JsonValue): s const lines: string[] = []; for (const [name, propNode] of Object.entries(props)) { const isRequired = requiredSet.has(name); - const tsType = synthesizeType(ctx, propNode, isRequired); + const tsType = synthesizeType(ctx, propNode); lines.push(` ${name}${isRequired ? "" : "?"}: ${tsType};`); } if (lines.length === 0) return "Record"; @@ -162,6 +167,6 @@ export function synthesizeObjectFields( const requiredSet = new Set(node?.required ?? []); return Object.entries(props).map(([name, propNode]) => { const isRequired = requiredSet.has(name); - return { name, tsType: synthesizeType(ctx, propNode, isRequired), required: isRequired }; + return { name, tsType: synthesizeType(ctx, propNode), required: isRequired }; }); } diff --git a/scripts/api-sync/types.ts b/scripts/api-sync/types.ts index 4d373f3..f579a32 100644 --- a/scripts/api-sync/types.ts +++ b/scripts/api-sync/types.ts @@ -163,6 +163,8 @@ export type ApplicableChange = property?: string; field: string; tsType: string; + /** Shared types/index.d.ts unions tsType reuses; the target file must import them. */ + importsNeeded: string[]; site: SdkSite; } | OperationInsertChange; diff --git a/src/client.test.ts b/src/client.test.ts index ab5acf5..2c4ca53 100644 --- a/src/client.test.ts +++ b/src/client.test.ts @@ -15,6 +15,50 @@ describe("BlindPay client", () => { expect(error).toBeNull(); expect(data).toBeNull(); }); + + it("surfaces the API error envelope's code, description, errors and trace_id", async () => { + fetchMock.mockResponseOnce( + JSON.stringify({ + success: false, + code: "PAYOUTS_INSUFFICIENT_BALANCE", + message: "not_enough_balance", + description: "There is not enough balance to complete this payout.", + errors: ["Bad Request"], + trace_id: "0af7651916cd43dd8448eb211c80319c", + }), + { status: 400 } + ); + + const { data, error } = await blindpay.payouts.get("pa_000000000000"); + + expect(data).toBeNull(); + expect(error).toStrictEqual({ + code: "PAYOUTS_INSUFFICIENT_BALANCE", + message: "not_enough_balance", + description: "There is not enough balance to complete this payout.", + errors: ["Bad Request"], + trace_id: "0af7651916cd43dd8448eb211c80319c", + }); + }); + + it("keeps only the envelope's documented fields, and only when they're well typed", async () => { + fetchMock.mockResponseOnce( + JSON.stringify({ message: 42, code: "X", errors: ["a", 1], debug: { sql: "..." } }), + { status: 500 } + ); + + const { error } = await blindpay.payouts.get("pa_000000000000"); + + expect(error).toStrictEqual({ message: "Unknown error", code: "X" }); + }); + + it("keeps only a message when the error body is not an object", async () => { + fetchMock.mockResponseOnce(JSON.stringify("Bad Gateway"), { status: 502 }); + + const { error } = await blindpay.payouts.get("pa_000000000000"); + + expect(error).toStrictEqual({ message: "Unknown error" }); + }); }); describe("verifyWebhookSignature", () => { @@ -76,3 +120,45 @@ describe("verifyWebhookSignature", () => { ).toBe(false); }); }); + +describe("Idempotency-Key", () => { + afterEach(() => fetchMock.resetMocks()); + + const blindpay = new BlindPay({ apiKey: "test-key", instanceId: "in_000000000000" }); + const sentKey = () => new Headers(fetchMock.mock.calls[0][1]?.headers).get("Idempotency-Key"); + const payout = { quote_id: "qu_000000000000", sender_wallet_address: "0x000000000000" }; + + it("is sent as a header when a mutation is given one", async () => { + fetchMock.mockResponseOnce(JSON.stringify({ id: "pa_000000000000" })); + + await blindpay.payouts.createEvm(payout, { + idempotencyKey: "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + }); + + expect(sentKey()).toBe("a1b2c3d4-e5f6-7890-abcd-ef1234567890"); + }); + + it("is sent on a DELETE too", async () => { + fetchMock.mockResponseOnce(JSON.stringify({ success: true })); + + await blindpay.customers.delete("cu_000000000000", { idempotencyKey: "retry-1" }); + + expect(sentKey()).toBe("retry-1"); + }); + + it("is sent even when empty, so the API rejects it instead of the SDK dropping it", async () => { + fetchMock.mockResponseOnce(JSON.stringify({ id: "pa_000000000000" })); + + await blindpay.payouts.createEvm(payout, { idempotencyKey: "" }); + + expect(sentKey()).toBe(""); + }); + + it("is not sent when the call has none", async () => { + fetchMock.mockResponseOnce(JSON.stringify({ id: "pa_000000000000" })); + + await blindpay.payouts.createEvm(payout); + + expect(sentKey()).toBeNull(); + }); +}); diff --git a/src/client.ts b/src/client.ts index fcc0132..8bc4548 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,18 +1,22 @@ import { Webhook } from "svix"; import { version } from "../package.json"; -import type { BlindpayApiResponse } from "../types"; +import type { BlindpayApiResponse, RequestOptions } from "../types"; import type { InternalApiClient } from "./internal/api-client"; import { BlindPayError } from "./internal/blindpay-error"; +import { toErrorResponse } from "./internal/error-response"; import { createAvailableResource } from "./resources/available"; import { createBankAccountsResource } from "./resources/bank-accounts"; import { createCustomersResource } from "./resources/customers"; import { createFeesResource } from "./resources/fees"; import { createInstancesResource } from "./resources/instances"; +import { createInstanceOnboardingResource } from "./resources/instances/onboarding"; import { createPartnerFeesResource } from "./resources/partner-fees"; +import { createPayablesResource } from "./resources/payables"; import { createPayinsResource } from "./resources/payins"; import { createPayinQuotesResource } from "./resources/payins/quotes"; import { createPayoutsResource } from "./resources/payouts"; import { createQuotesResource } from "./resources/quotes"; +import { createCustomerRfiResource, createInstanceRfiResource } from "./resources/rfi"; import { createTermsOfServiceResource } from "./resources/terms-of-service"; import { createTransfersResource } from "./resources/transfers"; import { createUploadResource } from "./resources/upload"; @@ -21,6 +25,19 @@ import { createBlockchainWalletsResource } from "./resources/wallets/blockchain" import { createCustodialWalletsResource } from "./resources/wallets/custodial"; import { createOfframpWalletsResource } from "./resources/wallets/offramp"; import { createWebhookEndpointsResource } from "./resources/webhooks"; +import type { WebhookEvent } from "./resources/webhooks/events"; + +/** What `verifyWebhookSignature` and `constructWebhookEvent` check: the svix-* headers. */ +export type WebhookVerificationInput = { + secret: string; + headers: { + id: string; + timestamp: string; + signature: string; + }; + /** The raw request body: re-serialized JSON changes the bytes and fails verification. */ + payload: string; +}; export class BlindPay { // Options @@ -33,6 +50,7 @@ export class BlindPay { // Resources readonly available: ReturnType; readonly partnerFees: ReturnType; + readonly payables: ReturnType; readonly payins: ReturnType & { quotes: ReturnType; }; @@ -44,10 +62,13 @@ export class BlindPay { readonly virtualAccounts: ReturnType; readonly customers: ReturnType & { bankAccounts: ReturnType; + rfi: ReturnType; }; readonly instances: ReturnType & { webhookEndpoints: ReturnType; tos: ReturnType; + onboarding: ReturnType; + rfi: ReturnType; }; readonly wallets: { blockchain: ReturnType; @@ -97,10 +118,14 @@ export class BlindPay { ...createInstancesResource(this.instanceId, this.api), webhookEndpoints: createWebhookEndpointsResource(this.instanceId, this.api), tos: createTermsOfServiceResource(this.instanceId, this.api), + onboarding: createInstanceOnboardingResource(this.instanceId, this.api), + rfi: createInstanceRfiResource(this.instanceId, this.api), }; this.partnerFees = createPartnerFeesResource(this.instanceId, this.api); + this.payables = createPayablesResource(this.instanceId, this.api); + this.payins = { ...createPayinsResource(this.instanceId, this.api), quotes: createPayinQuotesResource(this.instanceId, this.api), @@ -114,11 +139,12 @@ export class BlindPay { this.fees = createFeesResource(this.instanceId, this.api); - this.upload = createUploadResource(this.baseUrl, this.headers); + this.upload = createUploadResource(this.instanceId, this.baseUrl, this.headers, this.api); this.customers = { ...createCustomersResource(this.instanceId, this.api), bankAccounts: createBankAccountsResource(this.instanceId, this.api), + rfi: createCustomerRfiResource(this.instanceId, this.api), }; this.virtualAccounts = createVirtualAccountsResource(this.instanceId, this.api); @@ -133,22 +159,24 @@ export class BlindPay { private async request( method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH", path: string, - body?: Record + body?: Record, + options?: RequestOptions ): Promise> { try { + const idempotencyKey = options?.idempotencyKey; const response = await fetch(`${this.baseUrl}${path}`, { method, - headers: this.headers, + headers: + idempotencyKey === undefined + ? this.headers + : { ...this.headers, "Idempotency-Key": idempotencyKey }, body: body ? JSON.stringify(body) : undefined, }); if (!response.ok) { - const error = await this.parseJsonResponse<{ message?: string }>(response); return { data: null, - error: { - message: error?.message ?? "Unknown error", - }, + error: toErrorResponse(await this.parseJsonResponse(response)), }; } @@ -196,30 +224,33 @@ export class BlindPay { private async post( path: string, - body: Record + body: Record, + options?: RequestOptions ): Promise> { - return this.request("POST", path, body); + return this.request("POST", path, body, options); } private async put( path: string, - body: Record + body: Record, + options?: RequestOptions ): Promise> { - return this.request("PUT", path, body); + return this.request("PUT", path, body, options); } private async patch( path: string, - body: Record + body: Record, + options?: RequestOptions ): Promise> { - return this.request("PATCH", path, body); + return this.request("PATCH", path, body, options); } private async delete( path: string, - body?: Record + options?: RequestOptions ): Promise> { - return this.request("DELETE", path, body); + return this.request("DELETE", path, undefined, options); } /** @@ -230,31 +261,37 @@ export class BlindPay { * @param params.payload The raw request body as a string * @returns {boolean} True if the signature is valid, false otherwise */ - verifyWebhookSignature({ - secret, - headers, - payload, - }: { - secret: string; - headers: { - id: string; - timestamp: string; - signature: string; - }; - payload: string; - }): boolean { + verifyWebhookSignature(params: WebhookVerificationInput): boolean { try { - const webhook = new Webhook(secret); - - webhook.verify(payload, { - "svix-id": headers.id, - "svix-timestamp": headers.timestamp, - "svix-signature": headers.signature, - }); - + verifyWithSvix(params); return true; } catch { return false; } } + + /** + * Verifies a BlindPay webhook with Svix and returns its payload, typed by `webhook_event`. + * + * @returns The verified payload; narrow it with a `switch` on `event.webhook_event` + * @throws {BlindPayError} When the signature or timestamp does not verify + */ + constructWebhookEvent(params: WebhookVerificationInput): WebhookEvent { + try { + return verifyWithSvix(params) as WebhookEvent; + } catch (error) { + throw new BlindPayError( + `Webhook verification failed: ${error instanceof Error ? error.message : String(error)}` + ); + } + } +} + +/** Returns the parsed payload when the Svix signature and timestamp verify, else throws. */ +function verifyWithSvix({ secret, headers, payload }: WebhookVerificationInput): unknown { + return new Webhook(secret).verify(payload, { + "svix-id": headers.id, + "svix-timestamp": headers.timestamp, + "svix-signature": headers.signature, + }); } diff --git a/src/index.ts b/src/index.ts index 58461ba..26dc856 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,11 +4,14 @@ export * from "./resources/bank-accounts"; export * from "./resources/customers"; export * from "./resources/fees"; export * from "./resources/instances"; +export * from "./resources/instances/onboarding"; export * from "./resources/partner-fees"; +export * from "./resources/payables"; export * from "./resources/payins"; export * from "./resources/payins/quotes"; export * from "./resources/payouts"; export * from "./resources/quotes"; +export * from "./resources/rfi"; export * from "./resources/transfers"; export * from "./resources/upload"; export * from "./resources/virtual-accounts"; @@ -16,3 +19,4 @@ export * from "./resources/wallets/blockchain"; export * from "./resources/wallets/custodial"; export * from "./resources/wallets/offramp"; export * from "./resources/webhooks"; +export * from "./resources/webhooks/events"; diff --git a/src/internal/api-client.ts b/src/internal/api-client.ts index 32dc6c5..68533b5 100644 --- a/src/internal/api-client.ts +++ b/src/internal/api-client.ts @@ -1,4 +1,4 @@ -import type { BlindpayApiResponse } from "../../types"; +import type { BlindpayApiResponse, RequestOptions } from "../../types"; /** * @@ -7,8 +7,20 @@ import type { BlindpayApiResponse } from "../../types"; */ export interface InternalApiClient { get: (path: string) => Promise>; - post: (path: string, body: Record) => Promise>; - put: (path: string, body: Record) => Promise>; - patch: (path: string, body: Record) => Promise>; - delete: (path: string, body?: Record) => Promise>; + post: ( + path: string, + body: Record, + options?: RequestOptions + ) => Promise>; + put: ( + path: string, + body: Record, + options?: RequestOptions + ) => Promise>; + patch: ( + path: string, + body: Record, + options?: RequestOptions + ) => Promise>; + delete: (path: string, options?: RequestOptions) => Promise>; } diff --git a/src/internal/error-response.ts b/src/internal/error-response.ts new file mode 100644 index 0000000..75d386b --- /dev/null +++ b/src/internal/error-response.ts @@ -0,0 +1,25 @@ +import type { ErrorResponse } from "../../types"; + +const OPTIONAL_STRING_FIELDS = ["code", "description", "trace_id"] as const; + +/** + * Maps a non-2xx JSON body (the API's `Error` envelope) onto the SDK's `error` object, keeping + * only the documented fields and only when they have the documented type. + */ +export function toErrorResponse(body: unknown): ErrorResponse { + if (!body || typeof body !== "object" || Array.isArray(body)) { + return { message: "Unknown error" }; + } + const fields = body as Record; + const error: ErrorResponse = { + message: typeof fields.message === "string" ? fields.message : "Unknown error", + }; + for (const key of OPTIONAL_STRING_FIELDS) { + const value = fields[key]; + if (typeof value === "string") error[key] = value; + } + if (Array.isArray(fields.errors) && fields.errors.every((e) => typeof e === "string")) { + error.errors = fields.errors; + } + return error; +} diff --git a/src/resources/available/index.ts b/src/resources/available/index.ts index 3f2159a..df7c3f2 100644 --- a/src/resources/available/index.ts +++ b/src/resources/available/index.ts @@ -1,4 +1,4 @@ -import type { BlindpayApiResponse, Rail } from "../../../types"; +import type { BlindpayApiResponse, Country, Rail } from "../../../types"; import type { InternalApiClient } from "../../internal/api-client"; export type BankDetailKey = @@ -49,6 +49,41 @@ export type BankDetailKey = | "swift_intermediary_bank_swift_code_bic" | "swift_intermediary_bank_account_number_iban" | "swift_intermediary_bank_name" + | "business_industry" + | "date_of_birth" + | "force_cpf_cnpj" + | "onemoney_external_account_id" + | "phone_number" + | "pix_safe_bank_code" + | "pix_safe_branch_code" + | "pix_safe_cpf_cnpj" + | "recipient_relationship" + | "sepa_beneficiary_address_line_1" + | "sepa_beneficiary_address_line_2" + | "sepa_beneficiary_bic" + | "sepa_beneficiary_city" + | "sepa_beneficiary_country" + | "sepa_beneficiary_legal_name" + | "sepa_beneficiary_postal_code" + | "sepa_beneficiary_state_province_region" + | "sepa_iban" + | "status" + | "swift_ifsc_branch_code" + | "swift_payment_code" + | "tax_id" + | "ted_bank_code" + | "ted_branch_code" + | "ted_cpf_cnpj" + | "faster_payments_account_number" + | "faster_payments_beneficiary_address_line_1" + | "faster_payments_beneficiary_address_line_2" + | "faster_payments_beneficiary_city" + | "faster_payments_beneficiary_country" + | "faster_payments_beneficiary_legal_name" + | "faster_payments_beneficiary_postal_code" + | "faster_payments_beneficiary_state_province_region" + | "faster_payments_sort_code" + | "swift_intermediary_bank_routing_number" | "swift_intermediary_bank_country"; export type GetBankDetailsResponse = Array<{ @@ -60,13 +95,101 @@ export type GetBankDetailsResponse = Array<{ value: string; is_active?: boolean; }>; - required: boolean; + required: boolean | null; + requiredWhen?: { + field: + | "type" + | "name" + | "status" + | "recipient_relationship" + | "swift_payment_code" + | "pix_key" + | "force_cpf_cnpj" + | "beneficiary_name" + | "routing_number" + | "account_number" + | "account_type" + | "account_class" + | "address_line_1" + | "address_line_2" + | "city" + | "state_province_region" + | "country" + | "postal_code" + | "checkbook_account_id" + | "checkbook_user_key" + | "onemoney_external_account_id" + | "pix_safe_bank_code" + | "pix_safe_branch_code" + | "pix_safe_cpf_cnpj" + | "ted_bank_code" + | "ted_branch_code" + | "ted_cpf_cnpj" + | "spei_protocol" + | "spei_institution_code" + | "spei_clabe" + | "transfers_type" + | "transfers_account" + | "ach_cop_beneficiary_first_name" + | "ach_cop_beneficiary_last_name" + | "ach_cop_document_id" + | "ach_cop_document_type" + | "ach_cop_email" + | "ach_cop_bank_code" + | "ach_cop_bank_account" + | "swift_code_bic" + | "swift_account_holder_name" + | "swift_account_number_iban" + | "swift_beneficiary_address_line_1" + | "swift_beneficiary_address_line_2" + | "swift_beneficiary_country" + | "swift_beneficiary_city" + | "swift_beneficiary_state_province_region" + | "swift_beneficiary_postal_code" + | "swift_bank_name" + | "swift_bank_address_line_1" + | "swift_bank_address_line_2" + | "swift_bank_country" + | "swift_bank_city" + | "swift_bank_state_province_region" + | "swift_bank_postal_code" + | "swift_ifsc_branch_code" + | "swift_intermediary_bank_swift_code_bic" + | "swift_intermediary_bank_account_number_iban" + | "swift_intermediary_bank_name" + | "swift_intermediary_bank_country" + | "swift_intermediary_bank_routing_number" + | "sepa_iban" + | "sepa_beneficiary_bic" + | "sepa_beneficiary_legal_name" + | "sepa_beneficiary_address_line_1" + | "sepa_beneficiary_address_line_2" + | "sepa_beneficiary_city" + | "sepa_beneficiary_state_province_region" + | "sepa_beneficiary_postal_code" + | "sepa_beneficiary_country" + | "faster_payments_sort_code" + | "faster_payments_account_number" + | "faster_payments_beneficiary_legal_name" + | "faster_payments_beneficiary_address_line_1" + | "faster_payments_beneficiary_address_line_2" + | "faster_payments_beneficiary_city" + | "faster_payments_beneficiary_state_province_region" + | "faster_payments_beneficiary_postal_code" + | "faster_payments_beneficiary_country" + | "business_industry" + | "phone_number" + | "tax_id" + | "date_of_birth"; + operator: "in" | "eq" | "notIn" | "notEq"; + values: string[]; + }; }>; export type GetRailsResponse = Array<{ label: string; value: Rail; - country: string; + country: Country; }>; export type GetNaicsCodesResponse = Array<{ diff --git a/src/resources/bank-accounts/bank-accounts.test.ts b/src/resources/bank-accounts/bank-accounts.test.ts index 46efcb1..0bc6bc2 100644 --- a/src/resources/bank-accounts/bank-accounts.test.ts +++ b/src/resources/bank-accounts/bank-accounts.test.ts @@ -1,15 +1,19 @@ import { afterEach, describe, expect, it } from "vitest"; +import type { SuccessResponse } from "../../../types"; import { BlindPay } from "../../client"; import type { CreateAchResponse, CreateArgentinaTransfersResponse, CreateColombiaAchResponse, + CreateFasterPaymentsResponse, CreateInternationalSwiftResponse, CreatePixResponse, CreatePixSafeResponse, + CreatePlaidBankAccountResponse, CreateRtpResponse, CreateSepaResponse, CreateSpeiResponse, + CreateTedResponse, CreateWireResponse, GetBankAccountResponse, ListBankAccountsResponse, @@ -279,6 +283,7 @@ describe("Bank accounts", () => { swift_intermediary_bank_account_number_iban: null, swift_intermediary_bank_name: null, swift_intermediary_bank_country: null, + swift_intermediary_bank_routing_number: "021000089", swift_payment_code: null, created_at: "2021-01-01T00:00:00Z", }; @@ -312,10 +317,20 @@ describe("Bank accounts", () => { swift_intermediary_bank_country: null, swift_intermediary_bank_name: null, swift_intermediary_bank_swift_code_bic: null, + swift_intermediary_bank_routing_number: "021000089", }); expect(error).toBeNull(); expect(data).toEqual(mockedInternationalSwiftAccount); + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/customers/re_000000000000/bank-accounts" + ); + expect(init?.method).toBe("POST"); + expect(JSON.parse(init?.body as string)).toMatchObject({ + type: "international_swift", + swift_intermediary_bank_routing_number: "021000089", + }); }); }); @@ -367,17 +382,21 @@ describe("Bank accounts", () => { it("should get a bank account", async () => { const mockedBankAccount: GetBankAccountResponse = { id: "ba_000000000000", - customer_id: "rcv_123", - account_holder_name: "Individual full name or business name", - account_number: "1001001234", - routing_number: "012345678", - account_type: "checking", - bank_name: "Bank Name", - swift_code: "123456789", - iban: null, - is_primary: false, + type: "sepa", + name: "SEPA Account", + account_class: "individual", + sepa_iban: "BE68539007547034", + sepa_beneficiary_bic: "GKCCBEBB", + sepa_beneficiary_legal_name: "John Doe", + sepa_beneficiary_address_line_1: "123 Main Street", + sepa_beneficiary_address_line_2: null, + sepa_beneficiary_city: "Brussels", + sepa_beneficiary_state_province_region: null, + sepa_beneficiary_postal_code: "1000", + sepa_beneficiary_country: "BE", + swift_intermediary_bank_swift_code_bic: null, + status: "approved", created_at: "2021-01-01T00:00:00Z", - updated_at: "2021-01-01T00:00:00Z", }; fetchMock.mockResponseOnce(JSON.stringify(mockedBankAccount), { @@ -552,9 +571,134 @@ describe("Bank accounts", () => { }); }); + describe("Create TED bank account", () => { + it("should create a TED bank account with account number and type", async () => { + const mockedTedAccount: CreateTedResponse = { + id: "ba_000000000000", + type: "ted", + name: "TED Account", + beneficiary_name: "Jane Doe", + ted_bank_code: "001", + ted_branch_code: "0001", + ted_cpf_cnpj: "12345678900", + account_number: "123456-7", + account_type: "checking", + created_at: "2021-01-01T00:00:00Z", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedTedAccount), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.customers.bankAccounts.createTed({ + customer_id: "re_000000000000", + name: "TED Account", + beneficiary_name: "Jane Doe", + ted_bank_code: "001", + ted_branch_code: "0001", + ted_cpf_cnpj: "12345678900", + account_number: "123456-7", + account_type: "checking", + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedTedAccount); + const [, init] = fetchMock.mock.calls[0]; + expect(JSON.parse(init?.body as string)).toEqual({ + type: "ted", + name: "TED Account", + beneficiary_name: "Jane Doe", + ted_bank_code: "001", + ted_branch_code: "0001", + ted_cpf_cnpj: "12345678900", + account_number: "123456-7", + account_type: "checking", + }); + }); + }); + + describe("Create faster payments bank account", () => { + it("should create a faster payments bank account", async () => { + const mockedFasterPaymentsAccount: CreateFasterPaymentsResponse = { + id: "ba_000000000000", + type: "faster_payments", + name: "Faster Payments Account", + account_class: "individual", + faster_payments_sort_code: "040004", + faster_payments_account_number: "12345678", + faster_payments_beneficiary_legal_name: "John Doe", + faster_payments_beneficiary_address_line_1: "1 High Street", + faster_payments_beneficiary_address_line_2: null, + faster_payments_beneficiary_city: "London", + faster_payments_beneficiary_state_province_region: null, + faster_payments_beneficiary_postal_code: "EC1A 1BB", + faster_payments_beneficiary_country: "GB", + created_at: "2021-01-01T00:00:00Z", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedFasterPaymentsAccount), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.customers.bankAccounts.createFasterPayments({ + customer_id: "re_000000000000", + name: "Faster Payments Account", + account_class: "individual", + faster_payments_sort_code: "040004", + faster_payments_account_number: "12345678", + faster_payments_beneficiary_legal_name: "John Doe", + faster_payments_beneficiary_address_line_1: "1 High Street", + faster_payments_beneficiary_city: "London", + faster_payments_beneficiary_postal_code: "EC1A 1BB", + faster_payments_beneficiary_country: "GB", + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedFasterPaymentsAccount); + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/customers/re_000000000000/bank-accounts" + ); + expect(init?.method).toBe("POST"); + expect(JSON.parse(init?.body as string)).toEqual({ + type: "faster_payments", + name: "Faster Payments Account", + account_class: "individual", + faster_payments_sort_code: "040004", + faster_payments_account_number: "12345678", + faster_payments_beneficiary_legal_name: "John Doe", + faster_payments_beneficiary_address_line_1: "1 High Street", + faster_payments_beneficiary_city: "London", + faster_payments_beneficiary_postal_code: "EC1A 1BB", + faster_payments_beneficiary_country: "GB", + }); + }); + }); + + describe("List bank accounts with filters", () => { + it("should send the status filter as a query param", async () => { + fetchMock.mockResponseOnce(JSON.stringify([]), { + headers: { "Content-Type": "application/json" }, + }); + + const { error } = await blindpay.customers.bankAccounts.list({ + customer_id: "re_000000000000", + status: "approved", + type: "faster_payments", + }); + + expect(error).toBeNull(); + expect(fetchMock.mock.calls[0][0]).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/customers/re_000000000000/bank-accounts?status=approved&type=faster_payments" + ); + }); + }); + describe("Delete bank account", () => { it("should delete a bank account", async () => { - fetchMock.mockResponseOnce(JSON.stringify({ data: null }), { + const mockedResponse: SuccessResponse = { success: true }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { headers: { "Content-Type": "application/json" }, }); @@ -564,7 +708,34 @@ describe("Bank accounts", () => { }); expect(error).toBeNull(); - expect(data).toEqual({ data: null }); + expect(data).toEqual(mockedResponse); + }); + }); + describe("Create Plaid bank account link", () => { + it("should create a Plaid link for the customer", async () => { + const mockedLink: CreatePlaidBankAccountResponse = { + url: "https://link.plaid.com/xyz", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedLink), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.customers.bankAccounts.createPlaid({ + customer_id: "re_000000000000", + redirect_url: "https://example.com/done", + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedLink); + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/customers/re_000000000000/bank-accounts/plaid" + ); + expect(init?.method).toBe("POST"); + expect(JSON.parse(init?.body as string)).toEqual({ + redirect_url: "https://example.com/done", + }); }); }); }); diff --git a/src/resources/bank-accounts/index.ts b/src/resources/bank-accounts/index.ts index 0c2c04d..eb3a699 100644 --- a/src/resources/bank-accounts/index.ts +++ b/src/resources/bank-accounts/index.ts @@ -7,9 +7,12 @@ import type { BusinessIndustry, Country, Rail, + RequestOptions, + SuccessResponse, } from "../../../types"; import type { InternalApiClient } from "../../internal/api-client"; import type { SpeiProtocol } from "../payouts"; +import type { OfframpWalletNetwork } from "../wallets/offramp"; export type RecipientRelationship = | "first_party" @@ -23,9 +26,11 @@ export type RecipientRelationship = | "family" | "other"; +export type BankAccountStatus = "verifying" | "approved" | "rejected" | "deprecated"; + export type ListBankAccountsInput = { customer_id: string; - status?: string; + status?: BankAccountStatus; type?: Rail; name?: string; bank_account_id?: string; @@ -36,72 +41,93 @@ export type ListBankAccountsResponse = Array<{ id: string; type: Rail; name: string; - pix_key?: string; - beneficiary_name?: string; - routing_number?: string; - account_number?: string; - account_type?: BankAccountType; - account_class?: AccountClass; - address_line_1?: string; - address_line_2?: string; - city?: string; - state_province_region?: string; - country?: Country; - postal_code?: string; - spei_protocol?: string; - spei_institution_code?: string; - spei_clabe?: string; - transfers_type?: "CVU" | "CBU" | "ALIAS"; - transfers_account?: string; - ach_cop_beneficiary_first_name?: string; - ach_cop_beneficiary_last_name?: string; - ach_cop_document_id?: string; - ach_cop_document_type?: AchCopDocument; - ach_cop_email?: string; - ach_cop_bank_code?: string; - ach_cop_bank_account?: string; - swift_code_bic?: string; - swift_account_holder_name?: string; - swift_account_number_iban?: string; - swift_beneficiary_address_line_1?: string; - swift_beneficiary_address_line_2?: string; - swift_beneficiary_country?: Country; - swift_beneficiary_city?: string; - swift_beneficiary_state_province_region?: string; - swift_beneficiary_postal_code?: string; - swift_bank_name?: string; - swift_bank_address_line_1?: string; - swift_bank_address_line_2?: string; - swift_bank_country?: Country; - swift_bank_city?: string; - swift_bank_state_province_region?: string; - swift_bank_postal_code?: string; - swift_intermediary_bank_swift_code_bic?: string; - swift_intermediary_bank_account_number_iban?: string; - swift_intermediary_bank_name?: string; - swift_intermediary_bank_country?: Country; - pix_safe_bank_code?: string; - pix_safe_branch_code?: string; - pix_safe_cpf_cnpj?: string; - tron_wallet_hash?: string; + pix_key?: string | null; + beneficiary_name?: string | null; + routing_number?: string | null; + account_number?: string | null; + account_type?: BankAccountType | null; + account_class?: AccountClass | null; + address_line_1?: string | null; + address_line_2?: string | null; + city?: string | null; + state_province_region?: string | null; + country?: Country | null; + postal_code?: string | null; + spei_protocol?: SpeiProtocol | null; + spei_institution_code?: string | null; + spei_clabe?: string | null; + transfers_type?: "CVU" | "CBU" | "ALIAS" | null; + transfers_account?: string | null; + ach_cop_beneficiary_first_name?: string | null; + ach_cop_beneficiary_last_name?: string | null; + ach_cop_document_id?: string | null; + ach_cop_document_type?: AchCopDocument | null; + ach_cop_email?: string | null; + ach_cop_bank_code?: string | null; + ach_cop_bank_account?: string | null; + swift_code_bic?: string | null; + swift_account_holder_name?: string | null; + swift_account_number_iban?: string | null; + swift_beneficiary_address_line_1?: string | null; + swift_beneficiary_address_line_2?: string | null; + swift_beneficiary_country?: Country | null; + swift_beneficiary_city?: string | null; + swift_beneficiary_state_province_region?: string | null; + swift_beneficiary_postal_code?: string | null; + swift_bank_name?: string | null; + swift_bank_address_line_1?: string | null; + swift_bank_address_line_2?: string | null; + swift_bank_country?: Country | null; + swift_bank_city?: string | null; + swift_bank_state_province_region?: string | null; + swift_bank_postal_code?: string | null; + swift_intermediary_bank_swift_code_bic?: string | null; + swift_intermediary_bank_account_number_iban?: string | null; + swift_intermediary_bank_name?: string | null; + swift_intermediary_bank_country?: Country | null; + swift_intermediary_bank_routing_number?: string | null; + pix_safe_bank_code?: string | null; + pix_safe_branch_code?: string | null; + pix_safe_cpf_cnpj?: string | null; + tron_wallet_hash?: string | null; + sepa_iban?: string | null; sepa_beneficiary_bic?: string | null; + sepa_beneficiary_legal_name?: string | null; + sepa_beneficiary_address_line_1?: string | null; + sepa_beneficiary_address_line_2?: string | null; + sepa_beneficiary_city?: string | null; + sepa_beneficiary_state_province_region?: string | null; + sepa_beneficiary_postal_code?: string | null; + sepa_beneficiary_country?: Country | null; offramp_wallets?: Array<{ address: string; id: string; - network: "tron"; - external_id: string; - }>; - business_industry?: string | null; + network: OfframpWalletNetwork; + external_id?: string | null; + circle_wallet_id?: string | null; + }> | null; + business_industry?: BusinessIndustry | null; phone_number?: string | null; tax_id?: string | null; date_of_birth?: string | null; - status?: string | null; + status?: BankAccountStatus | null; recipient_relationship?: RecipientRelationship | null; swift_payment_code?: string | null; ted_bank_code?: string | null; ted_branch_code?: string | null; ted_cpf_cnpj?: string | null; - created_at: string; + created_at: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + plaid_connected_at?: string | null; + swift_ifsc_branch_code?: string | null; }>; export type GetBankAccountInput = { @@ -109,21 +135,9 @@ export type GetBankAccountInput = { id: string; }; -export type GetBankAccountResponse = { - id: string; - customer_id: string; - account_holder_name: string; - account_number: string; - routing_number: string; - account_type: BankAccountType; - bank_name: string; - swift_code?: string | null; - iban?: string | null; - sepa_beneficiary_bic?: string | null; - is_primary: boolean; - created_at: string; - updated_at: string; -}; +export type BankAccount = ListBankAccountsResponse[number]; + +export type GetBankAccountResponse = BankAccount; export type DeleteBankAccountInput = { customer_id: string; @@ -133,138 +147,259 @@ export type DeleteBankAccountInput = { export type CreatePixInput = { customer_id: string; name: string; - pix_key: string; + pix_key: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + force_cpf_cnpj?: boolean | null; + swift_ifsc_branch_code?: string | null; }; export type CreatePixResponse = { id: string; type: "pix"; name: string; - pix_key: string; - created_at: string; + pix_key: string | null; + created_at: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + plaid_connected_at?: string | null; + swift_ifsc_branch_code?: string | null; }; export type CreatePixSafeInput = { customer_id: string; name: string; - beneficiary_name: string; - account_number: string; - account_type: BankAccountType; - pix_safe_bank_code: string; - pix_safe_branch_code: string; - pix_safe_cpf_cnpj: string; + beneficiary_name: string | null; + account_number: string | null; + account_type: BankAccountType | null; + pix_safe_bank_code: string | null; + pix_safe_branch_code: string | null; + pix_safe_cpf_cnpj: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + force_cpf_cnpj?: boolean | null; + swift_ifsc_branch_code?: string | null; }; export type CreatePixSafeResponse = { id: string; type: "pix_safe"; name: string; - beneficiary_name: string; - account_number: string; - account_type: BankAccountType; - pix_safe_bank_code: string; - pix_safe_branch_code: string; - pix_safe_cpf_cnpj: string; - created_at: string; + beneficiary_name: string | null; + account_number: string | null; + account_type: BankAccountType | null; + pix_safe_bank_code: string | null; + pix_safe_branch_code: string | null; + pix_safe_cpf_cnpj: string | null; + created_at: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + plaid_connected_at?: string | null; + swift_ifsc_branch_code?: string | null; }; export type CreateArgentinaTransfersInput = { customer_id: string; name: string; - beneficiary_name: string; - transfers_account: string; - transfers_type: ArgentinaTransfers; + beneficiary_name: string | null; + transfers_account: string | null; + transfers_type: ArgentinaTransfers | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + force_cpf_cnpj?: boolean | null; + swift_ifsc_branch_code?: string | null; }; export type CreateArgentinaTransfersResponse = { id: string; type: "transfers_bitso"; name: string; - beneficiary_name: string; - transfers_type: ArgentinaTransfers; - transfers_account: string; - created_at: string; + beneficiary_name: string | null; + transfers_type: ArgentinaTransfers | null; + transfers_account: string | null; + created_at: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + plaid_connected_at?: string | null; + swift_ifsc_branch_code?: string | null; }; export type CreateSpeiInput = { customer_id: string; - beneficiary_name: string; + beneficiary_name: string | null; name: string; - spei_clabe: string; - spei_institution_code: string; - spei_protocol: SpeiProtocol; + spei_clabe: string | null; + spei_institution_code: string | null; + spei_protocol: SpeiProtocol | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + force_cpf_cnpj?: boolean | null; + swift_ifsc_branch_code?: string | null; }; export type CreateSpeiResponse = { id: string; type: "spei_bitso"; name: string; - beneficiary_name: string; - spei_protocol: SpeiProtocol; - spei_institution_code: string; - spei_clabe: string; - created_at: string; + beneficiary_name: string | null; + spei_protocol: SpeiProtocol | null; + spei_institution_code: string | null; + spei_clabe: string | null; + created_at: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + plaid_connected_at?: string | null; + swift_ifsc_branch_code?: string | null; }; export type CreateColombiaAchInput = { customer_id: string; name: string; - account_type: BankAccountType; - ach_cop_beneficiary_first_name: string; - ach_cop_beneficiary_last_name: string; - ach_cop_document_id: string; - ach_cop_document_type: AchCopDocument; - ach_cop_email: string; - ach_cop_bank_code: string; - ach_cop_bank_account: string; + account_type: BankAccountType | null; + ach_cop_beneficiary_first_name: string | null; + ach_cop_beneficiary_last_name: string | null; + ach_cop_document_id: string | null; + ach_cop_document_type: AchCopDocument | null; + ach_cop_email: string | null; + ach_cop_bank_code: string | null; + ach_cop_bank_account: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + force_cpf_cnpj?: boolean | null; + swift_ifsc_branch_code?: string | null; }; export type CreateColombiaAchResponse = { id: string; type: "ach_cop_bitso"; name: string; - account_type: BankAccountType; - ach_cop_beneficiary_first_name: string; - ach_cop_beneficiary_last_name: string; - ach_cop_document_id: string; - ach_cop_document_type: AchCopDocument; - ach_cop_email: string; - ach_cop_bank_code: string; - ach_cop_bank_account: string; - created_at: string; + account_type: BankAccountType | null; + ach_cop_beneficiary_first_name: string | null; + ach_cop_beneficiary_last_name: string | null; + ach_cop_document_id: string | null; + ach_cop_document_type: AchCopDocument | null; + ach_cop_email: string | null; + ach_cop_bank_code: string | null; + ach_cop_bank_account: string | null; + created_at: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + plaid_connected_at?: string | null; + swift_ifsc_branch_code?: string | null; }; export type CreateAchInput = { customer_id: string; name: string; - account_class: AccountClass; - account_number: string; - account_type: BankAccountType; - beneficiary_name: string; - routing_number: string; - recipient_relationship: RecipientRelationship; - address_line_1: string; - city: string; - state_province_region: string; - country: Country; - postal_code: string; - address_line_2?: string; - business_industry?: BusinessIndustry; - phone_number?: string; - tax_id?: string; - date_of_birth?: string; + account_class: AccountClass | null; + account_number: string | null; + account_type: BankAccountType | null; + beneficiary_name: string | null; + routing_number: string | null; + recipient_relationship: RecipientRelationship | null; + address_line_1: string | null; + city: string | null; + state_province_region: string | null; + country: Country | null; + postal_code: string | null; + address_line_2?: string | null; + business_industry?: BusinessIndustry | null; + phone_number?: string | null; + tax_id?: string | null; + date_of_birth?: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + force_cpf_cnpj?: boolean | null; + swift_ifsc_branch_code?: string | null; }; export type CreateAchResponse = { id: string; type: "ach"; name: string; - beneficiary_name: string; - routing_number: string; - account_number: string; - account_type: BankAccountType; - account_class: AccountClass; - recipient_relationship: RecipientRelationship; + beneficiary_name: string | null; + routing_number: string | null; + account_number: string | null; + account_type: BankAccountType | null; + account_class: AccountClass | null; + recipient_relationship: RecipientRelationship | null; address_line_1: string | null; address_line_2: string | null; city: string | null; @@ -278,77 +413,122 @@ export type CreateAchResponse = { ach_cop_email: string | null; ach_cop_bank_code: string | null; ach_cop_bank_account: string | null; - created_at: string; + created_at: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + plaid_connected_at?: string | null; + swift_ifsc_branch_code?: string | null; }; export type CreateWireInput = { customer_id: string; name: string; - account_class: AccountClass; - account_number: string; - beneficiary_name: string; - routing_number: string; - recipient_relationship: RecipientRelationship; - address_line_1: string; - address_line_2?: string; - city: string; - state_province_region: string; - country: Country; - postal_code: string; - business_industry?: BusinessIndustry; - phone_number?: string; - tax_id?: string; - date_of_birth?: string; + account_class: AccountClass | null; + account_number: string | null; + beneficiary_name: string | null; + routing_number: string | null; + recipient_relationship: RecipientRelationship | null; + address_line_1: string | null; + address_line_2?: string | null; + city: string | null; + state_province_region: string | null; + country: Country | null; + postal_code: string | null; + business_industry?: BusinessIndustry | null; + phone_number?: string | null; + tax_id?: string | null; + date_of_birth?: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + force_cpf_cnpj?: boolean | null; + swift_ifsc_branch_code?: string | null; }; export type CreateWireResponse = { id: string; type: "wire"; name: string; - beneficiary_name: string; - routing_number: string; - account_number: string; - account_class: AccountClass; - recipient_relationship: RecipientRelationship; - address_line_1: string; + beneficiary_name: string | null; + routing_number: string | null; + account_number: string | null; + account_class: AccountClass | null; + recipient_relationship: RecipientRelationship | null; + address_line_1: string | null; address_line_2: string | null; - city: string; - state_province_region: string; - country: Country; - postal_code: string; - created_at: string; + city: string | null; + state_province_region: string | null; + country: Country | null; + postal_code: string | null; + created_at: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + plaid_connected_at?: string | null; + swift_ifsc_branch_code?: string | null; }; export type CreateInternationalSwiftInput = { customer_id: string; name: string; - account_class: AccountClass; - recipient_relationship: RecipientRelationship; - swift_account_holder_name: string; - swift_account_number_iban: string; - swift_bank_address_line_1: string; - swift_bank_address_line_2?: string; - swift_bank_city: string; - swift_bank_country: Country; - swift_bank_name: string; - swift_bank_postal_code: string; - swift_bank_state_province_region: string; - swift_beneficiary_address_line_1: string; - swift_beneficiary_address_line_2?: string; - swift_beneficiary_city: string; - swift_beneficiary_country: Country; - swift_beneficiary_postal_code: string; - swift_beneficiary_state_province_region: string; - swift_code_bic: string; + account_class: AccountClass | null; + recipient_relationship: RecipientRelationship | null; + swift_account_holder_name: string | null; + swift_account_number_iban: string | null; + swift_bank_address_line_1: string | null; + swift_bank_address_line_2?: string | null; + swift_bank_city: string | null; + swift_bank_country: Country | null; + swift_bank_name: string | null; + swift_bank_postal_code: string | null; + swift_bank_state_province_region: string | null; + swift_beneficiary_address_line_1: string | null; + swift_beneficiary_address_line_2?: string | null; + swift_beneficiary_city: string | null; + swift_beneficiary_country: Country | null; + swift_beneficiary_postal_code: string | null; + swift_beneficiary_state_province_region: string | null; + swift_code_bic: string | null; swift_intermediary_bank_account_number_iban?: string | null; swift_intermediary_bank_country?: Country | null; swift_intermediary_bank_name?: string | null; swift_intermediary_bank_swift_code_bic?: string | null; - swift_payment_code?: string; - business_industry?: BusinessIndustry; - phone_number?: string; - tax_id?: string; - date_of_birth?: string; + swift_intermediary_bank_routing_number?: string | null; + swift_payment_code?: string | null; + business_industry?: BusinessIndustry | null; + phone_number?: string | null; + tax_id?: string | null; + date_of_birth?: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + force_cpf_cnpj?: boolean | null; + swift_ifsc_branch_code?: string | null; }; export type CreateInternationalSwiftResponse = { @@ -356,127 +536,250 @@ export type CreateInternationalSwiftResponse = { type: "international_swift"; name: string; beneficiary_name: string | null; - account_class: AccountClass; - recipient_relationship: RecipientRelationship; + account_class: AccountClass | null; + recipient_relationship: RecipientRelationship | null; address_line_1: string | null; address_line_2: string | null; city: string | null; state_province_region: string | null; country: Country | null; postal_code: string | null; - swift_code_bic: string; - swift_account_holder_name: string; - swift_account_number_iban: string; - swift_beneficiary_address_line_1: string; + swift_code_bic: string | null; + swift_account_holder_name: string | null; + swift_account_number_iban: string | null; + swift_beneficiary_address_line_1: string | null; swift_beneficiary_address_line_2: string | null; - swift_beneficiary_country: Country; - swift_beneficiary_city: string; - swift_beneficiary_state_province_region: string; - swift_beneficiary_postal_code: string; - swift_bank_name: string; - swift_bank_address_line_1: string; + swift_beneficiary_country: Country | null; + swift_beneficiary_city: string | null; + swift_beneficiary_state_province_region: string | null; + swift_beneficiary_postal_code: string | null; + swift_bank_name: string | null; + swift_bank_address_line_1: string | null; swift_bank_address_line_2: string | null; - swift_bank_country: Country; - swift_bank_city: string; - swift_bank_state_province_region: string; - swift_bank_postal_code: string; + swift_bank_country: Country | null; + swift_bank_city: string | null; + swift_bank_state_province_region: string | null; + swift_bank_postal_code: string | null; swift_intermediary_bank_swift_code_bic: string | null; swift_intermediary_bank_account_number_iban: string | null; swift_intermediary_bank_name: string | null; swift_intermediary_bank_country: Country | null; + swift_intermediary_bank_routing_number?: string | null; swift_payment_code: string | null; - created_at: string; + created_at: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + plaid_connected_at?: string | null; + swift_ifsc_branch_code?: string | null; }; export type CreateRtpInput = { customer_id: string; name: string; - account_class: AccountClass; - beneficiary_name: string; - routing_number: string; - account_number: string; - recipient_relationship: RecipientRelationship; - address_line_1: string; - address_line_2?: string; - city: string; - state_province_region: string; - country: Country; - postal_code: string; - business_industry?: BusinessIndustry; - phone_number?: string; - tax_id?: string; - date_of_birth?: string; + account_class: AccountClass | null; + beneficiary_name: string | null; + routing_number: string | null; + account_number: string | null; + recipient_relationship: RecipientRelationship | null; + address_line_1: string | null; + address_line_2?: string | null; + city: string | null; + state_province_region: string | null; + country: Country | null; + postal_code: string | null; + business_industry?: BusinessIndustry | null; + phone_number?: string | null; + tax_id?: string | null; + date_of_birth?: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + force_cpf_cnpj?: boolean | null; + swift_ifsc_branch_code?: string | null; }; export type CreateRtpResponse = { id: string; type: "rtp"; name: string; - beneficiary_name: string; - routing_number: string; - account_number: string; - account_class: AccountClass; - recipient_relationship: RecipientRelationship; - address_line_1: string; + beneficiary_name: string | null; + routing_number: string | null; + account_number: string | null; + account_class: AccountClass | null; + recipient_relationship: RecipientRelationship | null; + address_line_1: string | null; address_line_2: string | null; - city: string; - state_province_region: string; - country: Country; - postal_code: string; - created_at: string; + city: string | null; + state_province_region: string | null; + country: Country | null; + postal_code: string | null; + created_at: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + plaid_connected_at?: string | null; + swift_ifsc_branch_code?: string | null; }; export type CreateSepaInput = { customer_id: string; name: string; - account_class: AccountClass; - sepa_iban: string; - sepa_beneficiary_bic: string; - sepa_beneficiary_legal_name: string; - sepa_beneficiary_address_line_1: string; + account_class: AccountClass | null; + sepa_iban: string | null; + sepa_beneficiary_bic: string | null; + sepa_beneficiary_legal_name: string | null; + sepa_beneficiary_address_line_1: string | null; sepa_beneficiary_address_line_2?: string | null; - sepa_beneficiary_city: string; + sepa_beneficiary_city: string | null; sepa_beneficiary_state_province_region?: string | null; - sepa_beneficiary_postal_code: string; - sepa_beneficiary_country: Country; + sepa_beneficiary_postal_code: string | null; + sepa_beneficiary_country: Country | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + force_cpf_cnpj?: boolean | null; + swift_ifsc_branch_code?: string | null; }; export type CreateSepaResponse = { id: string; type: "sepa"; name: string; - account_class: AccountClass; + account_class: AccountClass | null; recipient_relationship: RecipientRelationship | null; - sepa_iban: string; - sepa_beneficiary_bic: string; - sepa_beneficiary_legal_name: string; - sepa_beneficiary_address_line_1: string; + sepa_iban: string | null; + sepa_beneficiary_bic: string | null; + sepa_beneficiary_legal_name: string | null; + sepa_beneficiary_address_line_1: string | null; sepa_beneficiary_address_line_2: string | null; - sepa_beneficiary_city: string; + sepa_beneficiary_city: string | null; sepa_beneficiary_state_province_region: string | null; - sepa_beneficiary_postal_code: string; - sepa_beneficiary_country: Country; - created_at: string; + sepa_beneficiary_postal_code: string | null; + sepa_beneficiary_country: Country | null; + created_at: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + plaid_connected_at?: string | null; + swift_ifsc_branch_code?: string | null; }; export type CreateTedInput = { customer_id: string; name: string; - beneficiary_name: string; - ted_bank_code: string; - ted_branch_code: string; - ted_cpf_cnpj: string; + beneficiary_name: string | null; + ted_bank_code: string | null; + ted_branch_code: string | null; + ted_cpf_cnpj: string | null; + account_number: string | null; + account_type: BankAccountType | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + force_cpf_cnpj?: boolean | null; + swift_ifsc_branch_code?: string | null; }; export type CreateTedResponse = { id: string; type: "ted"; name: string; - beneficiary_name: string; - ted_bank_code: string; - ted_branch_code: string; - ted_cpf_cnpj: string; - created_at: string; + beneficiary_name: string | null; + ted_bank_code: string | null; + ted_branch_code: string | null; + ted_cpf_cnpj: string | null; + account_number: string | null; + account_type: BankAccountType | null; + created_at: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_sort_code?: string | null; + plaid_connected_at?: string | null; + swift_ifsc_branch_code?: string | null; +}; + +export type CreateFasterPaymentsInput = { + customer_id: string; + name: string; + account_class: AccountClass | null; + faster_payments_sort_code: string | null; + faster_payments_account_number: string | null; + faster_payments_beneficiary_legal_name: string | null; + faster_payments_beneficiary_address_line_1: string | null; + faster_payments_beneficiary_address_line_2?: string | null; + faster_payments_beneficiary_city: string | null; + faster_payments_beneficiary_state_province_region?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_beneficiary_country: Country | null; +}; + +export type CreateFasterPaymentsResponse = { + id: string; + type: "faster_payments"; + name: string; + account_class: AccountClass | null; + faster_payments_sort_code: string | null; + faster_payments_account_number: string | null; + faster_payments_beneficiary_legal_name: string | null; + faster_payments_beneficiary_address_line_1: string | null; + faster_payments_beneficiary_address_line_2: string | null; + faster_payments_beneficiary_city: string | null; + faster_payments_beneficiary_state_province_region: string | null; + faster_payments_beneficiary_postal_code: string | null; + faster_payments_beneficiary_country: Country | null; + created_at: string | null; +}; + +export type CreatePlaidBankAccountInput = { + customer_id: string; + redirect_url?: string | null; +}; + +export type CreatePlaidBankAccountResponse = { + url: string; }; export function createBankAccountsResource(instanceId: string, client: InternalApiClient) { @@ -500,113 +803,181 @@ export function createBankAccountsResource(instanceId: string, client: InternalA `/instances/${instanceId}/customers/${customer_id}/bank-accounts/${id}` ); }, - delete({ customer_id, id }: DeleteBankAccountInput): Promise> { + delete( + { customer_id, id }: DeleteBankAccountInput, + options?: RequestOptions + ): Promise> { return client.delete( - `/instances/${instanceId}/customers/${customer_id}/bank-accounts/${id}` + `/instances/${instanceId}/customers/${customer_id}/bank-accounts/${id}`, + options ); }, - createPix({ - customer_id, - ...data - }: CreatePixInput): Promise> { - return client.post(`/instances/${instanceId}/customers/${customer_id}/bank-accounts`, { - type: "pix", - ...data, - }); + createPix( + { customer_id, ...data }: CreatePixInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/customers/${customer_id}/bank-accounts`, + { + type: "pix", + ...data, + }, + options + ); }, - createPixSafe({ - customer_id, - ...data - }: CreatePixSafeInput): Promise> { - return client.post(`/instances/${instanceId}/customers/${customer_id}/bank-accounts`, { - type: "pix_safe", - ...data, - }); + createPixSafe( + { customer_id, ...data }: CreatePixSafeInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/customers/${customer_id}/bank-accounts`, + { + type: "pix_safe", + ...data, + }, + options + ); }, - createArgentinaTransfers({ - customer_id, - ...data - }: CreateArgentinaTransfersInput): Promise< - BlindpayApiResponse - > { - return client.post(`/instances/${instanceId}/customers/${customer_id}/bank-accounts`, { - type: "transfers_bitso", - ...data, - }); + createArgentinaTransfers( + { customer_id, ...data }: CreateArgentinaTransfersInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/customers/${customer_id}/bank-accounts`, + { + type: "transfers_bitso", + ...data, + }, + options + ); }, - createSpei({ - customer_id, - ...data - }: CreateSpeiInput): Promise> { - return client.post(`/instances/${instanceId}/customers/${customer_id}/bank-accounts`, { - type: "spei_bitso", - ...data, - }); + createSpei( + { customer_id, ...data }: CreateSpeiInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/customers/${customer_id}/bank-accounts`, + { + type: "spei_bitso", + ...data, + }, + options + ); }, - createColombiaAch({ - customer_id, - ...data - }: CreateColombiaAchInput): Promise> { - return client.post(`/instances/${instanceId}/customers/${customer_id}/bank-accounts`, { - type: "ach_cop_bitso", - ...data, - }); + createColombiaAch( + { customer_id, ...data }: CreateColombiaAchInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/customers/${customer_id}/bank-accounts`, + { + type: "ach_cop_bitso", + ...data, + }, + options + ); }, - createAch({ - customer_id, - ...data - }: CreateAchInput): Promise> { - return client.post(`/instances/${instanceId}/customers/${customer_id}/bank-accounts`, { - type: "ach", - ...data, - }); + createAch( + { customer_id, ...data }: CreateAchInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/customers/${customer_id}/bank-accounts`, + { + type: "ach", + ...data, + }, + options + ); }, - createWire({ - customer_id, - ...data - }: CreateWireInput): Promise> { - return client.post(`/instances/${instanceId}/customers/${customer_id}/bank-accounts`, { - type: "wire", - ...data, - }); + createWire( + { customer_id, ...data }: CreateWireInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/customers/${customer_id}/bank-accounts`, + { + type: "wire", + ...data, + }, + options + ); }, - createInternationalSwift({ - customer_id, - ...data - }: CreateInternationalSwiftInput): Promise< - BlindpayApiResponse - > { - return client.post(`/instances/${instanceId}/customers/${customer_id}/bank-accounts`, { - type: "international_swift", - ...data, - }); + createInternationalSwift( + { customer_id, ...data }: CreateInternationalSwiftInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/customers/${customer_id}/bank-accounts`, + { + type: "international_swift", + ...data, + }, + options + ); }, - createRtp({ - customer_id, - ...data - }: CreateRtpInput): Promise> { - return client.post(`/instances/${instanceId}/customers/${customer_id}/bank-accounts`, { - type: "rtp", - ...data, - }); + createRtp( + { customer_id, ...data }: CreateRtpInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/customers/${customer_id}/bank-accounts`, + { + type: "rtp", + ...data, + }, + options + ); }, - createTed({ - customer_id, - ...data - }: CreateTedInput): Promise> { - return client.post(`/instances/${instanceId}/customers/${customer_id}/bank-accounts`, { - type: "ted", - ...data, - }); + createTed( + { customer_id, ...data }: CreateTedInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/customers/${customer_id}/bank-accounts`, + { + type: "ted", + ...data, + }, + options + ); }, - createSepa({ - customer_id, - ...data - }: CreateSepaInput): Promise> { - return client.post(`/instances/${instanceId}/customers/${customer_id}/bank-accounts`, { - type: "sepa", - ...data, - }); + createSepa( + { customer_id, ...data }: CreateSepaInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/customers/${customer_id}/bank-accounts`, + { + type: "sepa", + ...data, + }, + options + ); + }, + createFasterPayments( + { customer_id, ...data }: CreateFasterPaymentsInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/customers/${customer_id}/bank-accounts`, + { + type: "faster_payments", + ...data, + }, + options + ); + }, + + createPlaid( + { customer_id, ...data }: CreatePlaidBankAccountInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/customers/${customer_id}/bank-accounts/plaid`, + data, + options + ); }, }; } diff --git a/src/resources/customers/customers.test.ts b/src/resources/customers/customers.test.ts index 7dba1b8..e996406 100644 --- a/src/resources/customers/customers.test.ts +++ b/src/resources/customers/customers.test.ts @@ -1,4 +1,5 @@ import { afterEach, describe, expect, it } from "vitest"; +import type { SuccessResponse } from "../../../types"; import { BlindPay } from "../../client"; import type { CreateBusinessWithStandardKYBResponse, @@ -15,6 +16,25 @@ describe("Customers", () => { afterEach(() => fetchMock.resetMocks()); const blindpay = new BlindPay({ apiKey: "test-key", instanceId: "in_000000000000" }); + const mockedSuccess: SuccessResponse = { success: true }; + + describe("List customers without pagination params", () => { + it("should return a plain array", async () => { + const mockedResponse: ListCustomersResponse = []; + + fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.customers.list(); + + expect(error).toBeNull(); + expect(data).toEqual([]); + expect(fetchMock.mock.calls[0][0]).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/customers" + ); + }); + }); describe("List customers", () => { it("should list customers", async () => { @@ -54,7 +74,6 @@ describe("Customers", () => { id_doc_type: "PASSPORT", id_doc_front_file: "https://example.com/image.png", id_doc_back_file: "https://example.com/image.png", - aiprise_validation_key: "", instance_id: "in_000000000000", tos_id: "to_3ZZhllJkvo5Z", created_at: "2021-01-01T00:00:00.000Z", @@ -92,11 +111,9 @@ describe("Customers", () => { id_doc_type: "PASSPORT", id_doc_front_file: "https://example.com/image.png", id_doc_back_file: null, - aiprise_validation_key: "enhanced-key", instance_id: "in_000000000001", source_of_funds_doc_type: "salary", source_of_funds_doc_file: "https://example.com/image.png", - individual_holding_doc_front_file: "https://example.com/image.png", purpose_of_transactions: "investment_purposes", purpose_of_transactions_explanation: "Investing in stocks", tos_id: "to_nppX66ntvtHs", @@ -162,7 +179,6 @@ describe("Customers", () => { external_id: null, instance_id: "in_000000000002", tos_id: "to_nppX66ntvtHs", - aiprise_validation_key: "", created_at: "2015-03-15T00:00:00.000Z", updated_at: "2015-03-15T00:00:00.000Z", limit: { @@ -194,6 +210,7 @@ describe("Customers", () => { it("should create an individual customer with standard KYC", async () => { const mockedCustomer: CreateIndividualWithStandardKYCResponse = { id: "re_Euw7HN4OdxPn", + customer_id: "re_Euw7HN4OdxPn", }; fetchMock.mockResponseOnce(JSON.stringify(mockedCustomer), { @@ -223,12 +240,13 @@ describe("Customers", () => { }); expect(error).toBeNull(); - expect(data).toEqual({ id: "re_Euw7HN4OdxPn" }); + expect(data).toEqual(mockedCustomer); }); it("should create an individual customer with enhanced KYC", async () => { const mockedCustomer: CreateIndividualWithEnhancedKYCResponse = { id: "re_YuaMcI2B8zbQ", + customer_id: "re_YuaMcI2B8zbQ", }; fetchMock.mockResponseOnce(JSON.stringify(mockedCustomer), { @@ -264,12 +282,13 @@ describe("Customers", () => { }); expect(error).toBeNull(); - expect(data).toEqual({ id: "re_YuaMcI2B8zbQ" }); + expect(data).toEqual(mockedCustomer); }); it("should create a business customer with standard KYB", async () => { const mockedCustomer: CreateBusinessWithStandardKYBResponse = { id: "re_IOxAUL24LG7P", + customer_id: "re_IOxAUL24LG7P", }; fetchMock.mockResponseOnce(JSON.stringify(mockedCustomer), { @@ -323,11 +342,26 @@ describe("Customers", () => { ownership_percentage: 25, title: "CEO", }, + { + role: "controlling_person", + first_name: "Ana", + last_name: "Souza", + date_of_birth: "1990-03-10T00:00:00.000Z", + tax_id: "10987654321", + address_line_1: "Rua Oscar Freire, 200", + city: "São Paulo", + state_province_region: "SP", + country: "BR", + postal_code: "01426-000", + id_doc_country: "BR", + id_doc_type: "ID_CARD", + id_doc_front_file: "https://example.com/image.png", + }, ], }); expect(error).toBeNull(); - expect(data).toEqual({ id: "re_IOxAUL24LG7P" }); + expect(data).toEqual(mockedCustomer); }); }); @@ -359,7 +393,6 @@ describe("Customers", () => { id_doc_type: "PASSPORT", id_doc_front_file: "https://example.com/image.png", id_doc_back_file: "https://example.com/image.png", - aiprise_validation_key: "", instance_id: "in_000000000000", tos_id: null, created_at: "2021-01-01T00:00:00.000Z", @@ -401,6 +434,76 @@ describe("Customers", () => { expect(data).toEqual(mockedCustomer); }); + it("should get a business customer with CNAE condition and virtual account preapproval", async () => { + const mockedCustomer: GetCustomerResponse = { + id: "re_YuaMcI2B8zbQ", + is_tos_accepted: true, + is_fbo: false, + type: "business", + kyc_type: "standard", + kyc_status: "approved", + kyc_warnings: null, + email: "finance@example.com.br", + tax_id: "12345678000190", + address_line_1: "Av. Paulista, 1000", + city: "Sao Paulo", + state_province_region: "SP", + country: "BR", + postal_code: "01310100", + ip_address: null, + image_url: null, + phone_number: null, + proof_of_address_doc_type: "UTILITY_BILL", + proof_of_address_doc_file: "https://example.com/image.png", + legal_name: "Empresa Exemplo LTDA", + alternate_name: null, + formation_date: "2015-01-01T00:00:00.000Z", + website: null, + owners: [], + incorporation_doc_file: "https://example.com/image.png", + proof_of_ownership_doc_file: "https://example.com/image.png", + external_id: null, + instance_id: "in_000000000000", + tos_id: null, + created_at: "2021-01-01T00:00:00.000Z", + updated_at: "2021-01-01T00:00:00.000Z", + limit: { + per_transaction: 100000, + daily: 200000, + monthly: 1000000, + }, + cnae_condition: { + status: "pending", + expected_cnaes: ["6201501", "6202300"], + cnae_at_approval: { + primary: { code: "4751201", description: "Comercio varejista" }, + secondary: [ + { code: "6201501", description: "Desenvolvimento de software" }, + ], + }, + result_cnae: null, + due_at: "2021-04-01T00:00:00.000Z", + created_at: "2021-01-01T00:00:00.000Z", + reviewed_at: null, + }, + virtual_account_preapproval: { + status: "approved", + banking_partners: ["jpmorgan", "portage"], + rejection_reason: null, + reviewed_at: "2021-01-02T00:00:00.000Z", + }, + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedCustomer), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.customers.get("re_YuaMcI2B8zbQ"); + + expect(error).toBeNull(); + expect(data).toEqual(mockedCustomer); + }); + it("should get a customer", async () => { const mockedCustomer: GetCustomerResponse = { id: "re_YuaMcI2B8zbQ", @@ -436,10 +539,8 @@ describe("Customers", () => { id_doc_type: "PASSPORT", id_doc_front_file: "https://example.com/image.png", id_doc_back_file: "https://example.com/image.png", - aiprise_validation_key: "", source_of_funds_doc_type: "savings", source_of_funds_doc_file: "https://example.com/image.png", - individual_holding_doc_front_file: "https://example.com/image.png", purpose_of_transactions: "personal_or_living_expenses", purpose_of_transactions_explanation: "I am receiving salary payments from my employer", @@ -465,9 +566,60 @@ describe("Customers", () => { }); }); + describe("Get customer with light KYC", () => { + it("should get a migrated customer that carries the legacy light tier", async () => { + const mockedCustomer: GetCustomerResponse = { + id: "re_L1ghtKyc0000", + customer_id: "re_L1ghtKyc0000", + is_tos_accepted: true, + type: "individual", + kyc_type: "light", + kyc_status: "approved", + kyc_warnings: null, + email: "legacy@example.com", + tax_id: null, + address_line_1: null, + city: null, + state_province_region: null, + country: "US", + postal_code: null, + ip_address: null, + image_url: null, + phone_number: null, + proof_of_address_doc_type: null, + proof_of_address_doc_file: null, + first_name: "Legacy", + last_name: "Customer", + date_of_birth: null, + id_doc_country: null, + id_doc_type: null, + id_doc_front_file: null, + id_doc_back_file: null, + instance_id: "in_000000000000", + tos_id: null, + created_at: "2024-01-01T00:00:00.000Z", + updated_at: "2024-01-01T00:00:00.000Z", + limit: { + per_transaction: 1000, + daily: 2000, + monthly: 5000, + }, + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedCustomer), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.customers.get("re_L1ghtKyc0000"); + + expect(error).toBeNull(); + expect(data).toEqual(mockedCustomer); + }); + }); + describe("Update customer", () => { it("should update a customer", async () => { - fetchMock.mockResponseOnce(JSON.stringify({ data: null }), { + fetchMock.mockResponseOnce(JSON.stringify(mockedSuccess), { headers: { "Content-Type": "application/json" }, }); @@ -498,6 +650,7 @@ describe("Customers", () => { website: "https://site.com", owners: [ { + id: "ub_000000000000", first_name: "Carlos", last_name: "Silva", role: "beneficial_owner", @@ -531,20 +684,46 @@ describe("Customers", () => { }); expect(error).toBeNull(); - expect(data).toEqual({ data: null }); + expect(data).toEqual(mockedSuccess); + }); + + it("should update a single owner by id", async () => { + fetchMock.mockResponseOnce(JSON.stringify(mockedSuccess), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.customers.update({ + customer_id: "re_IOxAUL24LG7P", + email: "contato@empresa.com.br", + country: "BR", + owners: [{ id: "ub_000000000000", title: "CFO" }], + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedSuccess); + + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/customers/re_IOxAUL24LG7P" + ); + expect(JSON.parse(init?.body as string)).toEqual({ + email: "contato@empresa.com.br", + country: "BR", + owners: [{ id: "ub_000000000000", title: "CFO" }], + }); }); }); describe("Delete customer", () => { it("should delete a customer", async () => { - fetchMock.mockResponseOnce(JSON.stringify({ data: null }), { + fetchMock.mockResponseOnce(JSON.stringify(mockedSuccess), { headers: { "Content-Type": "application/json" }, }); const { data, error } = await blindpay.customers.delete("re_YuaMcI2B8zbQ"); expect(error).toBeNull(); - expect(data).toEqual({ data: null }); + expect(data).toEqual(mockedSuccess); }); }); @@ -667,5 +846,95 @@ describe("Customers", () => { expect(error).toBeNull(); expect(data).toEqual(mockedResponse); }); + + it("should request a limit increase with multiple supporting documents", async () => { + const mockedResponse: RequestLimitIncreaseResponse = { + id: "rl_000000000000", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.customers.requestLimitIncrease({ + customer_id: "re_YuaMcI2B8zbQ", + daily: 100000, + monthly: 500000, + per_transaction: 50000, + supporting_documents: [ + { + type: "individual_pay_stub", + file: "https://example.com/pay-stub.pdf", + }, + { + type: "individual_crypto_exchange_statement", + file: "https://example.com/exchange-statement.pdf", + }, + ], + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedResponse); + + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toContain( + "/instances/in_000000000000/customers/re_YuaMcI2B8zbQ/limit-increase" + ); + expect(init?.method).toBe("POST"); + expect(JSON.parse(init?.body as string)).toEqual({ + daily: 100000, + monthly: 500000, + per_transaction: 50000, + supporting_documents: [ + { + type: "individual_pay_stub", + file: "https://example.com/pay-stub.pdf", + }, + { + type: "individual_crypto_exchange_statement", + file: "https://example.com/exchange-statement.pdf", + }, + ], + }); + }); + }); + + describe("Get limit increase requests with supporting documents", () => { + it("should get limit increase requests with every supporting document", async () => { + const mockedLimitIncreaseRequests: GetLimitIncreaseRequestsResponse = [ + { + id: "rl_000000000000", + customer_id: "re_YuaMcI2B8zbQ", + status: "in_review", + daily: 50000, + monthly: 250000, + per_transaction: 25000, + supporting_document_file: "https://example.com/contract.pdf", + supporting_document_type: "business_contract", + supporting_documents: [ + { + type: "business_contract", + file: "https://example.com/contract.pdf", + }, + { + type: "business_shareholder_loan", + file: "https://example.com/loan.pdf", + }, + ], + created_at: "2025-01-15T10:30:00.000Z", + updated_at: "2025-01-15T10:30:00.000Z", + }, + ]; + + fetchMock.mockResponseOnce(JSON.stringify(mockedLimitIncreaseRequests), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = + await blindpay.customers.getLimitIncreaseRequests("re_YuaMcI2B8zbQ"); + + expect(error).toBeNull(); + expect(data).toEqual(mockedLimitIncreaseRequests); + }); }); }); diff --git a/src/resources/customers/index.ts b/src/resources/customers/index.ts index c5b5fa6..6a781af 100644 --- a/src/resources/customers/index.ts +++ b/src/resources/customers/index.ts @@ -11,9 +11,11 @@ import type { PaginationParams, PurposeOfTransactions, RecipientRelationship, + RequestOptions, SoleProprietorDocType, SourceOfFundsDocType, SourceOfWealth, + SuccessResponse, } from "../../../types"; import type { InternalApiClient } from "../../internal/api-client"; import type { StrictOmit } from "../../internal/helpers/strict-omit"; @@ -56,7 +58,7 @@ export type Owner = { first_name: string; last_name: string; date_of_birth: string; - tax_id: string; + tax_id: string | null; address_line_1: string; address_line_2: string | null; city: string; @@ -65,9 +67,9 @@ export type Owner = { postal_code: string; id_doc_country: Country; id_doc_type: IdentificationDocument; - id_doc_front_file: string; + id_doc_front_file: string | null; id_doc_back_file: string | null; - proof_of_address_doc_type: ProofOfAddressDocType; + proof_of_address_doc_type: ProofOfAddressDocType | null; proof_of_address_doc_file: string | null; ownership_percentage: number | null; title: string | null; @@ -76,9 +78,118 @@ export type Owner = { customer_id?: string; }; +/** An owner sent when creating a business customer. */ +export type CreateCustomerOwnerInput = { + role: OwnerRole; + first_name: string; + last_name: string; + date_of_birth: string; + tax_id: string; + address_line_1: string; + address_line_2?: string | null; + city: string; + state_province_region: string; + country: Country; + postal_code: string; + id_doc_country: Country; + id_doc_type: IdentificationDocument; + id_doc_front_file: string; + id_doc_back_file?: string | null; + proof_of_address_doc_type?: ProofOfAddressDocType | null; + proof_of_address_doc_file?: string | null; + ownership_percentage?: number | null; + title?: string | null; + tax_type?: OwnerTaxType | null; +}; + +/** An existing owner to update. `id` must match one of the customer's owners. */ +export type UpdateCustomerOwnerInput = { + id: string; + role?: OwnerRole; + first_name?: string; + last_name?: string; + date_of_birth?: string; + tax_id?: string; + address_line_1?: string; + address_line_2?: string | null; + city?: string; + state_province_region?: string; + country?: Country; + postal_code?: string; + id_doc_country?: Country; + id_doc_type?: IdentificationDocument; + id_doc_front_file?: string; + id_doc_back_file?: string | null; + proof_of_address_doc_type?: ProofOfAddressDocType | null; + proof_of_address_doc_file?: string | null; + ownership_percentage?: number | null; + title?: string | null; + tax_type?: OwnerTaxType | null; +}; + +export type VirtualAccountPreapprovalStatus = "in_review" | "approved" | "rejected"; + +export type VirtualAccountPreapprovalBankingPartner = "jpmorgan" | "portage"; + +export type CustomerVirtualAccountPreapproval = { + status: VirtualAccountPreapprovalStatus; + banking_partners: VirtualAccountPreapprovalBankingPartner[]; + rejection_reason: string | null; + reviewed_at: string | null; +}; + +export type CnaeConditionStatus = "pending" | "passed" | "failed" | "cancelled"; + +export type Cnae = { + code: string; + description: string; +}; + +export type CnaeSet = { + primary: Cnae; + secondary: Cnae[]; +}; + +export type CustomerCnaeCondition = { + status: CnaeConditionStatus; + expected_cnaes: string[]; + cnae_at_approval: CnaeSet; + result_cnae: CnaeSet | null; + due_at: string; + created_at: string; + reviewed_at: string | null; +}; + +export type AdditionalInfoLabel = + | "EIN_LETTER" + | "KYC_PROVIDER_DOCUMENT" + | "FLOW_OF_FUNDS" + | "BANK_STATEMENT" + | "TAX_RETURN" + | "AUDITED_FINANCIALS" + | "OPERATING_AGREEMENT" + | "BOARD_RESOLUTION" + | "CERTIFICATE_OF_GOOD_STANDING" + | "BUSINESS_LICENSE" + | "MSB_LICENSE" + | "POWER_OF_ATTORNEY" + | "TRUST_DEED" + | "SHAREHOLDER_REGISTRY" + | "BENEFICIAL_OWNER_DECLARATION" + | "COMPLIANCE_QUESTIONNAIRE" + | "PROOF_OF_EMPLOYMENT" + | "REFERENCE_LETTER" + | "OTHER"; + +export type AdditionalInfoItem = { + label: AdditionalInfoLabel; + /** A document URL (re-hosted on BlindPay storage) or a free-text note. */ + value: string; +}; + export type IndividualWithStandardKYC = { id: string; - is_tos_accepted: boolean; + is_tos_accepted: boolean | null; type: Extract; kyc_type: Extract; kyc_status: KycStatus; @@ -89,30 +200,29 @@ export type IndividualWithStandardKYC = { warning_id: string | null; }> | null; email: string; - tax_id: string; - address_line_1: string; + tax_id: string | null; + address_line_1: string | null; address_line_2?: string | null; - city: string; - state_province_region: string; + city: string | null; + state_province_region: string | null; country: Country; - postal_code: string; + postal_code: string | null; ip_address: string | null; image_url: string | null; - phone_number: string; - proof_of_address_doc_type: ProofOfAddressDocType; - proof_of_address_doc_file: string; - first_name: string; - last_name: string; - date_of_birth: string; - id_doc_country: Country; - id_doc_type: IdentificationDocument; - id_doc_front_file: string; - id_doc_back_file: string; - aiprise_validation_key: string; + phone_number: string | null; + proof_of_address_doc_type: ProofOfAddressDocType | null; + proof_of_address_doc_file: string | null; + first_name: string | null; + last_name: string | null; + date_of_birth?: string | null; + id_doc_country: Country | null; + id_doc_type: IdentificationDocument | null; + id_doc_front_file: string | null; + id_doc_back_file: string | null; instance_id: string; tos_id: string | null; - created_at: string; - updated_at: string; + created_at: string | null; + updated_at: string | null; limit: { per_transaction: number; daily: number; @@ -136,11 +246,19 @@ export type IndividualWithStandardKYC = { recipient_relationship?: RecipientRelationship | null; sole_proprietor_doc_type?: SoleProprietorDocType | null; publicly_traded?: boolean | null; + cnae_condition?: CustomerCnaeCondition | null; + virtual_account_preapproval?: CustomerVirtualAccountPreapproval | null; + is_nested?: boolean | null; + additional_info?: AdditionalInfoItem[] | null; + business_type?: BusinessType | null; + customer_id?: string; + latitude?: number | null; + longitude?: number | null; }; export type IndividualWithEnhancedKYC = { id: string; - is_tos_accepted: boolean; + is_tos_accepted: boolean | null; type: Extract; kyc_type: Extract; kyc_status: KycStatus; @@ -151,35 +269,33 @@ export type IndividualWithEnhancedKYC = { warning_id: string | null; }> | null; email: string; - tax_id: string; - address_line_1: string; + tax_id: string | null; + address_line_1: string | null; address_line_2?: string | null; - city: string; - state_province_region: string; + city: string | null; + state_province_region: string | null; country: Country; - postal_code: string; + postal_code: string | null; ip_address: string | null; image_url: string | null; phone_number: string | null; - proof_of_address_doc_type: ProofOfAddressDocType; - proof_of_address_doc_file: string; - first_name: string; - last_name: string; - date_of_birth: string; - id_doc_country: Country; - id_doc_type: IdentificationDocument; - id_doc_front_file: string; + proof_of_address_doc_type: ProofOfAddressDocType | null; + proof_of_address_doc_file: string | null; + first_name: string | null; + last_name: string | null; + date_of_birth?: string | null; + id_doc_country: Country | null; + id_doc_type: IdentificationDocument | null; + id_doc_front_file: string | null; id_doc_back_file: string | null; - aiprise_validation_key: string; instance_id: string; - source_of_funds_doc_type: string; - source_of_funds_doc_file: string; - individual_holding_doc_front_file: string; - purpose_of_transactions: PurposeOfTransactions; + source_of_funds_doc_type: SourceOfFundsDocType | null; + source_of_funds_doc_file: string | null; + purpose_of_transactions: PurposeOfTransactions | null; purpose_of_transactions_explanation: string | null; tos_id: string | null; - created_at: string; - updated_at: string; + created_at: string | null; + updated_at: string | null; limit: { per_transaction: number; daily: number; @@ -201,12 +317,20 @@ export type IndividualWithEnhancedKYC = { recipient_relationship?: RecipientRelationship | null; sole_proprietor_doc_type?: SoleProprietorDocType | null; publicly_traded?: boolean | null; + cnae_condition?: CustomerCnaeCondition | null; + virtual_account_preapproval?: CustomerVirtualAccountPreapproval | null; + is_nested?: boolean | null; + additional_info?: AdditionalInfoItem[] | null; + business_type?: BusinessType | null; + customer_id?: string; + latitude?: number | null; + longitude?: number | null; }; export type BusinessWithStandardKYB = { id: string; - is_tos_accepted: boolean; - is_fbo: boolean; + is_tos_accepted: boolean | null; + is_fbo: boolean | null; type: Extract; kyc_type: Extract; kyc_status: KycStatus; @@ -217,31 +341,30 @@ export type BusinessWithStandardKYB = { warning_id: string | null; }> | null; email: string; - tax_id: string; - address_line_1: string; + tax_id: string | null; + address_line_1: string | null; address_line_2?: string | null; - city: string; - state_province_region: string; + city: string | null; + state_province_region: string | null; country: Country; - postal_code: string; + postal_code: string | null; ip_address: string | null; image_url: string | null; phone_number: string | null; - proof_of_address_doc_type: ProofOfAddressDocType; - proof_of_address_doc_file: string; - legal_name: string; + proof_of_address_doc_type: ProofOfAddressDocType | null; + proof_of_address_doc_file: string | null; + legal_name: string | null; alternate_name: string | null; - formation_date: string; + formation_date?: string | null; website: string | null; - owners: Owner[]; - incorporation_doc_file: string; - proof_of_ownership_doc_file: string; + owners: Owner[] | null; + incorporation_doc_file: string | null; + proof_of_ownership_doc_file: string | null; external_id: string | null; instance_id: string; tos_id: string | null; - aiprise_validation_key: string; - created_at: string; - updated_at: string; + created_at: string | null; + updated_at: string | null; limit: { per_transaction: number; daily: number; @@ -262,8 +385,34 @@ export type BusinessWithStandardKYB = { source_of_wealth?: SourceOfWealth | null; recipient_relationship?: RecipientRelationship | null; sole_proprietor_doc_type?: SoleProprietorDocType | null; + publicly_traded?: boolean | null; + cnae_condition?: CustomerCnaeCondition | null; + virtual_account_preapproval?: CustomerVirtualAccountPreapproval | null; + is_nested?: boolean | null; + additional_info?: AdditionalInfoItem[] | null; + business_type?: BusinessType | null; + customer_id?: string; + latitude?: number | null; + longitude?: number | null; }; +/** Legacy KYC tier carried by customers migrated from older tiers. It can't be created. */ +export type IndividualWithLightKYC = StrictOmit & { + kyc_type: Extract; +}; + +/** Legacy KYB tier carried by customers migrated from older tiers. It can't be created. */ +export type BusinessWithLightKYB = StrictOmit & { + kyc_type: Extract; +}; + +export type Customer = + | IndividualWithStandardKYC + | IndividualWithEnhancedKYC + | IndividualWithLightKYC + | BusinessWithStandardKYB + | BusinessWithLightKYB; + export type CreateIndividualWithStandardKYCInput = { country: Country; email: string; @@ -296,10 +445,14 @@ export type CreateIndividualWithStandardKYCInput = { occupation?: string | null; recipient_relationship?: RecipientRelationship | null; sole_proprietor_doc_type?: SoleProprietorDocType | null; + additional_info?: AdditionalInfoItem[] | null; + latitude?: number | null; + longitude?: number | null; }; export type CreateIndividualWithStandardKYCResponse = { id: string; + customer_id: string; }; export type CreateIndividualWithEnhancedKYCInput = { @@ -336,10 +489,14 @@ export type CreateIndividualWithEnhancedKYCInput = { occupation?: string | null; recipient_relationship?: RecipientRelationship | null; sole_proprietor_doc_type?: SoleProprietorDocType | null; + additional_info?: AdditionalInfoItem[] | null; + latitude?: number | null; + longitude?: number | null; }; export type CreateIndividualWithEnhancedKYCResponse = { id: string; + customer_id: string; }; export type CreateBusinessWithStandardKYBInput = { @@ -360,7 +517,7 @@ export type CreateBusinessWithStandardKYBInput = { incorporation_doc_file?: string | null; ip_address?: string | null; legal_name?: string | null; - owners?: Array> | null; + owners?: CreateCustomerOwnerInput[] | null; phone_number?: string | null; postal_code?: string | null; proof_of_address_doc_file?: string | null; @@ -378,80 +535,86 @@ export type CreateBusinessWithStandardKYBInput = { occupation?: string | null; recipient_relationship?: RecipientRelationship | null; sole_proprietor_doc_type?: SoleProprietorDocType | null; + additional_info?: AdditionalInfoItem[] | null; + latitude?: number | null; + longitude?: number | null; }; export type CreateBusinessWithStandardKYBResponse = { id: string; + customer_id: string; }; export type ListCustomersInput = PaginationParams & { full_name?: string; customer_name?: string; - status?: string; + status?: KycStatus; customer_id?: string; bank_account_id?: string; country?: Country; }; -export type ListCustomersResponse = { - data: Array; - pagination: PaginationMetadata; -}; +export type ListCustomersResponse = + | { + data: Customer[]; + pagination: PaginationMetadata; + } + | Customer[]; export type GetCustomerInput = string; -export type GetCustomerResponse = - | IndividualWithStandardKYC - | IndividualWithEnhancedKYC - | BusinessWithStandardKYB; +export type GetCustomerResponse = Customer; export type UpdateCustomerInput = { customer_id: string; account_purpose?: AccountPurpose | null; - address_line_1?: string; - address_line_2?: string; - alternate_name?: string; - business_description?: string; + address_line_1?: string | null; + address_line_2?: string | null; + alternate_name?: string | null; + business_description?: string | null; business_industry?: BusinessIndustry | null; business_type?: BusinessType | null; - city?: string; - country?: Country; - date_of_birth?: string; - email?: string; + city?: string | null; + country: Country; + date_of_birth?: string | null; + email: string; estimated_annual_revenue?: EstimatedAnnualRevenue | null; - external_id?: string; - first_name?: string; - formation_date?: string; - id_doc_back_file?: string; - id_doc_country?: Country; - id_doc_front_file?: string; - id_doc_type?: IdentificationDocument; - image_url?: string; - incorporation_doc_file?: string; - ip_address?: string; - last_name?: string; - legal_name?: string; - owners?: Array>; - phone_number?: string; - postal_code?: string; - proof_of_address_doc_file?: string; - proof_of_address_doc_type?: ProofOfAddressDocType; - proof_of_ownership_doc_file?: string; + external_id?: string | null; + first_name?: string | null; + formation_date?: string | null; + id_doc_back_file?: string | null; + id_doc_country?: Country | null; + id_doc_front_file?: string | null; + id_doc_type?: IdentificationDocument | null; + image_url?: string | null; + incorporation_doc_file?: string | null; + ip_address?: string | null; + last_name?: string | null; + legal_name?: string | null; + owners?: UpdateCustomerOwnerInput[] | null; + phone_number?: string | null; + postal_code?: string | null; + proof_of_address_doc_file?: string | null; + proof_of_address_doc_type?: ProofOfAddressDocType | null; + proof_of_ownership_doc_file?: string | null; publicly_traded?: boolean | null; - purpose_of_transactions?: PurposeOfTransactions; - purpose_of_transactions_explanation?: string; - selfie_file?: string; - source_of_funds_doc_file?: string; - source_of_funds_doc_type?: SourceOfFundsDocType; + purpose_of_transactions?: PurposeOfTransactions | null; + purpose_of_transactions_explanation?: string | null; + selfie_file?: string | null; + source_of_funds_doc_file?: string | null; + source_of_funds_doc_type?: SourceOfFundsDocType | null; source_of_wealth?: SourceOfWealth | null; - state_province_region?: string; - tax_id?: string; - tos_id?: string; - website?: string; + state_province_region?: string | null; + tax_id?: string | null; + tos_id?: string | null; + website?: string | null; account_purpose_other?: string | null; occupation?: string | null; recipient_relationship?: RecipientRelationship | null; sole_proprietor_doc_type?: SoleProprietorDocType | null; + additional_info?: AdditionalInfoItem[] | null; + latitude?: number | null; + longitude?: number | null; }; export type DeleteCustomerInput = string; @@ -479,21 +642,36 @@ export type LimitIncreaseRequestSupportingDocumentType = | "individual_bank_statement" | "individual_tax_return" | "individual_proof_of_income" + | "individual_pay_stub" + | "individual_employment_letter" + | "individual_investment_statement" + | "individual_crypto_exchange_statement" + | "individual_blockchain_wallet_statement" | "business_bank_statement" | "business_financial_statements" + | "business_accounts_receivable" + | "business_contract" + | "business_merchant_processor_statement" + | "business_shareholder_loan" | "business_tax_return"; +export type LimitIncreaseSupportingDocument = { + type: LimitIncreaseRequestSupportingDocumentType; + file: string; +}; + export type GetLimitIncreaseRequestsResponse = Array<{ id: string; customer_id: string; status: LimitIncreaseRequestStatus; - daily: number; - monthly: number; - per_transaction: number; - supporting_document_file: string; - supporting_document_type: LimitIncreaseRequestSupportingDocumentType; - created_at: string; - updated_at: string; + daily: number | null; + monthly: number | null; + per_transaction: number | null; + supporting_document_file: string | null; + supporting_document_type: LimitIncreaseRequestSupportingDocumentType | null; + supporting_documents?: LimitIncreaseSupportingDocument[] | null; + created_at: string | null; + updated_at: string | null; approved_per_transaction?: number | null; approved_daily?: number | null; approved_monthly?: number | null; @@ -501,11 +679,12 @@ export type GetLimitIncreaseRequestsResponse = Array<{ export type RequestLimitIncreaseInput = { customer_id: string; - daily: number; - monthly: number; - per_transaction: number; - supporting_document_file: string; - supporting_document_type: LimitIncreaseRequestSupportingDocumentType; + daily: number | null; + monthly: number | null; + per_transaction: number | null; + supporting_document_file?: string; + supporting_document_type?: LimitIncreaseRequestSupportingDocumentType; + supporting_documents?: LimitIncreaseSupportingDocument[]; }; export type RequestLimitIncreaseResponse = { @@ -519,40 +698,61 @@ export function createCustomersResource(instanceId: string, client: InternalApiC return client.get(`/instances/${instanceId}/customers${queryParams}`); }, createIndividualWithStandardKYC( - data: CreateIndividualWithStandardKYCInput + data: CreateIndividualWithStandardKYCInput, + options?: RequestOptions ): Promise> { - return client.post(`/instances/${instanceId}/customers`, { - kyc_type: "standard", - type: "individual", - ...data, - }); + return client.post( + `/instances/${instanceId}/customers`, + { + kyc_type: "standard", + type: "individual", + ...data, + }, + options + ); }, createIndividualWithEnhancedKYC( - data: CreateIndividualWithEnhancedKYCInput + data: CreateIndividualWithEnhancedKYCInput, + options?: RequestOptions ): Promise> { - return client.post(`/instances/${instanceId}/customers`, { - kyc_type: "enhanced", - type: "individual", - ...data, - }); + return client.post( + `/instances/${instanceId}/customers`, + { + kyc_type: "enhanced", + type: "individual", + ...data, + }, + options + ); }, createBusinessWithStandardKYB( - data: CreateBusinessWithStandardKYBInput + data: CreateBusinessWithStandardKYBInput, + options?: RequestOptions ): Promise> { - return client.post(`/instances/${instanceId}/customers`, { - kyc_type: "standard", - type: "business", - ...data, - }); + return client.post( + `/instances/${instanceId}/customers`, + { + kyc_type: "standard", + type: "business", + ...data, + }, + options + ); }, get(customer_id: GetCustomerInput): Promise> { return client.get(`/instances/${instanceId}/customers/${customer_id}`); }, - update({ customer_id, ...data }: UpdateCustomerInput): Promise> { - return client.put(`/instances/${instanceId}/customers/${customer_id}`, data); + update( + { customer_id, ...data }: UpdateCustomerInput, + options?: RequestOptions + ): Promise> { + return client.put(`/instances/${instanceId}/customers/${customer_id}`, data, options); }, - delete(customer_id: DeleteCustomerInput): Promise> { - return client.delete(`/instances/${instanceId}/customers/${customer_id}`); + delete( + customer_id: DeleteCustomerInput, + options?: RequestOptions + ): Promise> { + return client.delete(`/instances/${instanceId}/customers/${customer_id}`, options); }, getLimits( customer_id: GetCustomerLimitsInput @@ -564,13 +764,14 @@ export function createCustomersResource(instanceId: string, client: InternalApiC ): Promise> { return client.get(`/instances/${instanceId}/customers/${customer_id}/limit-increase`); }, - requestLimitIncrease({ - customer_id, - ...data - }: RequestLimitIncreaseInput): Promise> { + requestLimitIncrease( + { customer_id, ...data }: RequestLimitIncreaseInput, + options?: RequestOptions + ): Promise> { return client.post( `/instances/${instanceId}/customers/${customer_id}/limit-increase`, - data + data, + options ); }, }; diff --git a/src/resources/fees/fees.test.ts b/src/resources/fees/fees.test.ts index d9abb2d..bcbaeca 100644 --- a/src/resources/fees/fees.test.ts +++ b/src/resources/fees/fees.test.ts @@ -28,6 +28,8 @@ describe("Fees", () => { ach_colombia: mockFeeOptions, transfers_3: mockFeeOptions, spei: mockFeeOptions, + sepa: mockFeeOptions, + faster_payments: mockFeeOptions, tron: mockFeeOptions, ethereum: mockFeeOptions, polygon: mockFeeOptions, diff --git a/src/resources/fees/index.ts b/src/resources/fees/index.ts index 5c15591..518f6d2 100644 --- a/src/resources/fees/index.ts +++ b/src/resources/fees/index.ts @@ -20,6 +20,8 @@ export type GetFeesResponse = { ach_colombia: FeeOptions; transfers_3: FeeOptions; spei: FeeOptions; + sepa: FeeOptions; + faster_payments: FeeOptions; tron: FeeOptions; ethereum: FeeOptions; polygon: FeeOptions; @@ -27,9 +29,14 @@ export type GetFeesResponse = { arbitrum: FeeOptions; stellar: FeeOptions; solana: FeeOptions; - ted: FeeOptions; - created_at: string; - updated_at: string; + ted?: FeeOptions | null; + created_at: string | null; + updated_at: string | null; + yield?: { + blindpay_share_bps: number; + partner_share_bps: number; + partner_wallet_address?: string | null; + } | null; }; export function createFeesResource(instanceId: string, client: InternalApiClient) { diff --git a/src/resources/instances/index.ts b/src/resources/instances/index.ts index 9bab425..ea6f2e5 100644 --- a/src/resources/instances/index.ts +++ b/src/resources/instances/index.ts @@ -1,4 +1,4 @@ -import type { BlindpayApiResponse } from "../../../types"; +import type { BlindpayApiResponse, RequestOptions, SuccessResponse } from "../../../types"; import type { InternalApiClient } from "../../internal/api-client"; export type InstanceMemberRole = @@ -14,18 +14,46 @@ export type GetInstanceMembersResponse = Array<{ id: string; email: string; first_name: string; - middle_name: string; + middle_name: string | null; last_name: string; image_url: string; - created_at: string; + created_at: string | null; role: InstanceMemberRole; + has_passkey?: boolean | null; }>; +export type InstanceType = "production" | "development"; + +export type InstanceOnboardingStep = + | "initial" + | "business_details" + | "business_profile" + | "documents" + | "applicant" + | "completed" + | "blocked"; + +export type Instance = { + id: string; + name: string; + type: InstanceType; + onboarding_step: InstanceOnboardingStep; +}; + +export type GetInstanceResponse = Instance; + export type UpdateInstanceInput = { name: string; - customer_invite_redirect_url?: string; + customer_invite_redirect_url?: string | null; email_notifications?: boolean; require_passkey?: boolean; + accent_color?: string | null; + logo_url?: string | null; + partner_tos_link?: string | null; + partner_tos_screenshot?: string | null; + partner_tos_terms_accepted?: boolean; + compliance_emails?: string[] | null; + customer_rfi_emails_enabled?: boolean; }; export type DeleteInstanceMemberInput = string; @@ -39,36 +67,46 @@ export type MigrateInstanceOwnershipInput = { user_id: string; }; -export type MigrateInstanceOwnershipResponse = { - success: boolean; -}; +export type MigrateInstanceOwnershipResponse = SuccessResponse; export function createInstancesResource(instanceId: string, client: InternalApiClient) { return { + get(): Promise> { + return client.get(`/instances/${instanceId}`); + }, getMembers(): Promise> { return client.get(`/instances/${instanceId}/members`); }, - update({ ...data }: UpdateInstanceInput): Promise> { - return client.put(`/instances/${instanceId}`, data); + update( + { ...data }: UpdateInstanceInput, + options?: RequestOptions + ): Promise> { + return client.put(`/instances/${instanceId}`, data, options); }, - delete(): Promise> { - return client.delete(`/instances/${instanceId}`); + delete(options?: RequestOptions): Promise> { + return client.delete(`/instances/${instanceId}`, options); }, - deleteMember(memberId: DeleteInstanceMemberInput): Promise> { - return client.delete(`/instances/${instanceId}/members/${memberId}`); + deleteMember( + memberId: DeleteInstanceMemberInput, + options?: RequestOptions + ): Promise> { + return client.delete(`/instances/${instanceId}/members/${memberId}`, options); }, - updateMemberRole({ - memberId, - role, - }: UpdateInstanceMemberRoleInput): Promise> { - return client.put(`/instances/${instanceId}/members/${memberId}`, { user_role: role }); + updateMemberRole( + { memberId, role }: UpdateInstanceMemberRoleInput, + options?: RequestOptions + ): Promise> { + return client.put( + `/instances/${instanceId}/members/${memberId}`, + { user_role: role }, + options + ); }, - migrateOwnership({ - ...data - }: MigrateInstanceOwnershipInput): Promise< - BlindpayApiResponse - > { - return client.post(`/instances/${instanceId}/ownership`, data); + migrateOwnership( + { ...data }: MigrateInstanceOwnershipInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/ownership`, data, options); }, }; } diff --git a/src/resources/instances/instances.test.ts b/src/resources/instances/instances.test.ts index 5082623..4415a94 100644 --- a/src/resources/instances/instances.test.ts +++ b/src/resources/instances/instances.test.ts @@ -1,10 +1,36 @@ import { afterEach, describe, expect, it } from "vitest"; +import type { SuccessResponse } from "../../../types"; import { BlindPay } from "../../client"; +import type { GetInstanceResponse } from "."; describe("Instances", () => { afterEach(() => fetchMock.resetMocks()); const blindpay = new BlindPay({ apiKey: "test-key", instanceId: "in_000000000000" }); + const mockedSuccess: SuccessResponse = { success: true }; + + describe("Get instance", () => { + it("should get the instance", async () => { + const mockedInstance: GetInstanceResponse = { + id: "in_000000000000", + name: "My Instance", + type: "development", + onboarding_step: "completed", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedInstance), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.instances.get(); + + expect(error).toBeNull(); + expect(data).toEqual(mockedInstance); + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe("https://api.blindpay.com/v1/instances/in_000000000000"); + expect(init?.method).toBe("GET"); + }); + }); describe("Get instance members", () => { it("should get instance members", async () => { @@ -34,7 +60,7 @@ describe("Instances", () => { describe("Update instance", () => { it("should update an instance", async () => { - fetchMock.mockResponseOnce(JSON.stringify({ data: null }), { + fetchMock.mockResponseOnce(JSON.stringify(mockedSuccess), { headers: { "Content-Type": "application/json" }, }); @@ -43,39 +69,39 @@ describe("Instances", () => { }); expect(error).toBeNull(); - expect(data).toEqual({ data: null }); + expect(data).toEqual(mockedSuccess); }); }); describe("Delete instance", () => { it("should delete an instance", async () => { - fetchMock.mockResponseOnce(JSON.stringify({ data: null }), { + fetchMock.mockResponseOnce(JSON.stringify(mockedSuccess), { headers: { "Content-Type": "application/json" }, }); const { data, error } = await blindpay.instances.delete(); expect(error).toBeNull(); - expect(data).toEqual({ data: null }); + expect(data).toEqual(mockedSuccess); }); }); describe("Delete instance member", () => { it("should delete an instance member", async () => { - fetchMock.mockResponseOnce(JSON.stringify({ data: null }), { + fetchMock.mockResponseOnce(JSON.stringify(mockedSuccess), { headers: { "Content-Type": "application/json" }, }); const { data, error } = await blindpay.instances.deleteMember("us_000000000000"); expect(error).toBeNull(); - expect(data).toEqual({ data: null }); + expect(data).toEqual(mockedSuccess); }); }); describe("Update instance member role", () => { it("should update instance member role", async () => { - fetchMock.mockResponseOnce(JSON.stringify({ data: null }), { + fetchMock.mockResponseOnce(JSON.stringify(mockedSuccess), { headers: { "Content-Type": "application/json" }, }); @@ -85,7 +111,7 @@ describe("Instances", () => { }); expect(error).toBeNull(); - expect(data).toEqual({ data: null }); + expect(data).toEqual(mockedSuccess); }); }); }); diff --git a/src/resources/instances/onboarding.test.ts b/src/resources/instances/onboarding.test.ts new file mode 100644 index 0000000..770a3c7 --- /dev/null +++ b/src/resources/instances/onboarding.test.ts @@ -0,0 +1,124 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { BlindPay } from "../../client"; +import type { + GetInstanceBusinessDetailsResponse, + GetInstanceBusinessProfileResponse, + GetInstanceOwnershipDocumentsResponse, +} from "./onboarding"; + +describe("Instance onboarding", () => { + afterEach(() => fetchMock.resetMocks()); + + const blindpay = new BlindPay({ apiKey: "test-key", instanceId: "in_000000000000" }); + + describe("Get business details", () => { + it("should get the instance business details", async () => { + const mockedBusinessDetails: GetInstanceBusinessDetailsResponse = { + legal_name: "My Company", + tax_id: "000.000.000-00", + formation_date: "2020-04-23T00:00:00Z", + trading_names: ["My Company Trading"], + address_line_1: "123 Main St", + address_line_2: null, + city: "New York", + state_province_region: "NY", + postal_code: "10001", + country: "US", + entity_type: "corporation", + state_of_incorporation: "DE", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedBusinessDetails), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.instances.onboarding.getBusinessDetails(); + + expect(error).toBeNull(); + expect(data).toEqual(mockedBusinessDetails); + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/onboarding/business_details" + ); + expect(init?.method).toBe("GET"); + }); + }); + + describe("Get business profile", () => { + it("should get the instance business profile", async () => { + const mockedBusinessProfile: GetInstanceBusinessProfileResponse = { + scenario: "custodial", + scenario_description: null, + has_kyc_screening: true, + is_regulated: false, + business_industry: "wallet", + website: "https://example.com", + top_volume_by_country: ["US", "BR"], + estimated_volume_per_month: "up_to_1000", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedBusinessProfile), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.instances.onboarding.getBusinessProfile(); + + expect(error).toBeNull(); + expect(data).toEqual(mockedBusinessProfile); + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/onboarding/business_profile" + ); + expect(init?.method).toBe("GET"); + }); + }); + + describe("Get ownership documents", () => { + it("should get the instance ownership documents", async () => { + const mockedOwnershipDocuments: GetInstanceOwnershipDocumentsResponse = { + incorporation_doc_file: "https://example.com/incorporation.pdf", + proof_of_ownership_doc_file: "https://example.com/ownership.pdf", + proof_of_address_doc_type: "UTILITY_BILL", + proof_of_address_doc_file: "https://example.com/address.pdf", + owners: [ + { + id: "ub_000000000000", + instance_id: "in_000000000000", + role: "beneficial_owner", + first_name: "John", + last_name: "Doe", + ownership_percentage: 50, + date_of_birth: "1990-01-01T00:00:00Z", + tax_id: "123456789", + address_line_1: "123 Main St", + address_line_2: null, + city: "New York", + state_province_region: "NY", + country: "US", + postal_code: "10001", + id_doc_country: "US", + id_doc_type: "PASSPORT", + id_doc_front_file: "https://example.com/front.png", + id_doc_back_file: null, + proof_of_address_doc_type: "BANK_STATEMENT", + proof_of_address_doc_file: "https://example.com/owner-address.pdf", + }, + ], + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedOwnershipDocuments), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.instances.onboarding.getOwnershipDocuments(); + + expect(error).toBeNull(); + expect(data).toEqual(mockedOwnershipDocuments); + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/onboarding/ownership_documents" + ); + expect(init?.method).toBe("GET"); + }); + }); +}); diff --git a/src/resources/instances/onboarding.ts b/src/resources/instances/onboarding.ts new file mode 100644 index 0000000..6f11a95 --- /dev/null +++ b/src/resources/instances/onboarding.ts @@ -0,0 +1,107 @@ +import type { BlindpayApiResponse, Country } from "../../../types"; +import type { InternalApiClient } from "../../internal/api-client"; +import type { IdentificationDocument, OwnerRole, ProofOfAddressDocType } from "../customers"; + +export type InstanceEntityType = + | "cooperative" + | "corporation" + | "company" + | "partnership" + | "sole_proprietor" + | "trust" + | "other"; + +export type InstanceOnboardingScenario = "custodial" | "custodial_mtl" | "non_custodial" | "other"; + +export type InstanceBusinessIndustry = + | "wallet" + | "exchange" + | "dapp" + | "neo_bank" + | "gaming" + | "marketplace" + | "saas" + | "social" + | "infra" + | "gambling" + | "other"; + +export type InstanceEstimatedVolumePerMonth = + | "up_to_100" + | "up_to_500" + | "up_to_1000" + | "up_to_10000" + | "more_than_10000"; + +export type GetInstanceBusinessDetailsResponse = { + legal_name?: string; + tax_id?: string; + formation_date?: string; + trading_names?: string[]; + address_line_1?: string; + address_line_2?: string | null; + city?: string; + state_province_region?: string; + postal_code?: string; + country?: Country; + entity_type?: InstanceEntityType; + state_of_incorporation?: string; +}; + +export type GetInstanceBusinessProfileResponse = { + scenario?: InstanceOnboardingScenario; + scenario_description?: string | null; + has_kyc_screening?: boolean | null; + is_regulated?: boolean | null; + business_industry?: InstanceBusinessIndustry; + website?: string | null; + top_volume_by_country?: Country[]; + estimated_volume_per_month?: InstanceEstimatedVolumePerMonth; +}; + +export type InstanceOnboardingOwner = { + id?: string; + instance_id?: string; + role?: OwnerRole; + first_name?: string; + last_name?: string; + ownership_percentage?: number | null; + date_of_birth?: string; + tax_id?: string; + address_line_1?: string; + address_line_2?: string | null; + city?: string; + state_province_region?: string; + country?: Country; + postal_code?: string; + id_doc_country?: Country; + id_doc_type?: IdentificationDocument; + id_doc_front_file?: string | null; + id_doc_back_file?: string | null; + proof_of_address_doc_type?: ProofOfAddressDocType | null; + proof_of_address_doc_file?: string | null; +}; + +export type GetInstanceOwnershipDocumentsResponse = { + incorporation_doc_file?: string | null; + proof_of_ownership_doc_file?: string | null; + proof_of_address_doc_type?: ProofOfAddressDocType | null; + proof_of_address_doc_file?: string | null; + owners?: InstanceOnboardingOwner[] | null; +}; + +export function createInstanceOnboardingResource(instanceId: string, client: InternalApiClient) { + return { + getBusinessDetails(): Promise> { + return client.get(`/instances/${instanceId}/onboarding/business_details`); + }, + getBusinessProfile(): Promise> { + return client.get(`/instances/${instanceId}/onboarding/business_profile`); + }, + getOwnershipDocuments(): Promise< + BlindpayApiResponse + > { + return client.get(`/instances/${instanceId}/onboarding/ownership_documents`); + }, + }; +} diff --git a/src/resources/partner-fees/index.ts b/src/resources/partner-fees/index.ts index b1da3ed..48bff5e 100644 --- a/src/resources/partner-fees/index.ts +++ b/src/resources/partner-fees/index.ts @@ -1,4 +1,4 @@ -import type { BlindpayApiResponse } from "../../../types"; +import type { BlindpayApiResponse, RequestOptions, SuccessResponse } from "../../../types"; import type { InternalApiClient } from "../../internal/api-client"; export type ListPartnerFeesResponse = Array<{ @@ -9,19 +9,15 @@ export type ListPartnerFeesResponse = Array<{ payout_flat_fee: number; payin_percentage_fee: number; payin_flat_fee: number; - evm_wallet_address: string; - stellar_wallet_address: string; }>; export type CreatePartnerFeeInput = { virtual_account_set?: boolean | null; - evm_wallet_address: string; name: string; payin_flat_fee: number; payin_percentage_fee: number; payout_flat_fee: number; payout_percentage_fee: number; - stellar_wallet_address?: string | null; }; export type CreatePartnerFeeResponse = { @@ -32,8 +28,6 @@ export type CreatePartnerFeeResponse = { payout_flat_fee: number; payin_percentage_fee: number; payin_flat_fee: number; - evm_wallet_address?: string; - stellar_wallet_address?: string; }; export type GetPartnerFeeInput = string; @@ -41,13 +35,11 @@ export type GetPartnerFeeInput = string; export type GetPartnerFeeResponse = { id: string; instance_id: string; - evm_wallet_address: string; name: string; payin_flat_fee: number; payin_percentage_fee: number; payout_flat_fee: number; payout_percentage_fee: number; - stellar_wallet_address?: string | null; }; export type DeletePartnerFeeInput = string; @@ -57,16 +49,20 @@ export function createPartnerFeesResource(instanceId: string, client: InternalAp list(): Promise> { return client.get(`/instances/${instanceId}/partner-fees`); }, - create({ - ...data - }: CreatePartnerFeeInput): Promise> { - return client.post(`/instances/${instanceId}/partner-fees`, data); + create( + { ...data }: CreatePartnerFeeInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/partner-fees`, data, options); }, get(id: GetPartnerFeeInput): Promise> { return client.get(`/instances/${instanceId}/partner-fees/${id}`); }, - delete(id: DeletePartnerFeeInput): Promise> { - return client.delete(`/instances/${instanceId}/partner-fees/${id}`); + delete( + id: DeletePartnerFeeInput, + options?: RequestOptions + ): Promise> { + return client.delete(`/instances/${instanceId}/partner-fees/${id}`, options); }, }; } diff --git a/src/resources/partner-fees/partner-fees.test.ts b/src/resources/partner-fees/partner-fees.test.ts index 647f5fd..823358d 100644 --- a/src/resources/partner-fees/partner-fees.test.ts +++ b/src/resources/partner-fees/partner-fees.test.ts @@ -1,4 +1,5 @@ import { afterEach, describe, expect, it } from "vitest"; +import type { SuccessResponse } from "../../../types"; import { BlindPay } from "../../client"; import type { CreatePartnerFeeResponse, GetPartnerFeeResponse, ListPartnerFeesResponse } from "."; @@ -18,9 +19,6 @@ describe("Partner fees", () => { payout_flat_fee: 0, payin_percentage_fee: 0, payin_flat_fee: 0, - evm_wallet_address: "0x1234567890123456789012345678901234567890", - stellar_wallet_address: - "GAB22222222222222222222222222222222222222222222222222222222222222", }, ]; @@ -45,9 +43,6 @@ describe("Partner fees", () => { payout_flat_fee: 0, payin_percentage_fee: 0, payin_flat_fee: 0, - evm_wallet_address: "0x1234567890123456789012345678901234567890", - stellar_wallet_address: - "GAB22222222222222222222222222222222222222222222222222222222222222", }; fetchMock.mockResponseOnce(JSON.stringify(mockPartnerFee), { @@ -60,9 +55,6 @@ describe("Partner fees", () => { payout_flat_fee: 0, payin_percentage_fee: 0, payin_flat_fee: 0, - evm_wallet_address: "0x1234567890123456789012345678901234567890", - stellar_wallet_address: - "GAB22222222222222222222222222222222222222222222222222222222222222", }); expect(error).toBeNull(); @@ -80,9 +72,6 @@ describe("Partner fees", () => { payout_flat_fee: 0, payin_percentage_fee: 0, payin_flat_fee: 0, - evm_wallet_address: "0x1234567890123456789012345678901234567890", - stellar_wallet_address: - "GAB22222222222222222222222222222222222222222222222222222222222222", }; fetchMock.mockResponseOnce(JSON.stringify(mockedFee), { @@ -98,14 +87,16 @@ describe("Partner fees", () => { describe("Delete partner fee", () => { it("should delete a partner fee", async () => { - fetchMock.mockResponseOnce(JSON.stringify({ data: null }), { + const mockedResponse: SuccessResponse = { success: true }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { headers: { "Content-Type": "application/json" }, }); const { data, error } = await blindpay.partnerFees.delete("fe_000000000000"); expect(error).toBeNull(); - expect(data).toEqual({ data: null }); + expect(data).toEqual(mockedResponse); }); }); }); diff --git a/src/resources/payables/index.ts b/src/resources/payables/index.ts new file mode 100644 index 0000000..117001d --- /dev/null +++ b/src/resources/payables/index.ts @@ -0,0 +1,147 @@ +import type { + BlindpayApiResponse, + PaginationMetadata, + PaginationParams, + RequestOptions, +} from "../../../types"; +import type { InternalApiClient } from "../../internal/api-client"; +import type { StrictOmit } from "../../internal/helpers/strict-omit"; +import type { CreateAchInput, CreateWireInput } from "../bank-accounts"; + +export type PayableCurrency = "BRL" | "USD" | "MXN" | "COP" | "ARS" | "EUR" | "GBP"; + +export type PayableStatus = "draft" | "processing" | "completed" | "canceled"; + +export type PayableLastAttemptStatus = "failed" | "refunded"; + +export type PayableBankAccountType = "ach" | "wire"; + +export type PayableType = "boleto" | "pix_code" | "invoice"; + +export type PayableParty = { + legal_name?: string | null; + address_line_1?: string | null; + address_line_2?: string | null; + city?: string | null; + state_province_region?: string | null; + postal_code?: string | null; + country?: string | null; + tax_id?: string | null; +}; + +export type PayableLineItem = { + name: string; + quantity: number; + price: number | null; +}; + +export type PayableBankAccount = { + type: PayableBankAccountType; + beneficiary_name?: string | null; + routing_number?: string | null; + account_number?: string | null; + account_type?: string | null; +}; + +export type Payable = { + id: string; + instance_id: string; + customer_id: string; + from?: PayableParty | null; + to?: PayableParty | null; + currency: PayableCurrency; + line_items?: PayableLineItem[]; + note?: string | null; + discount?: number | null; + taxes?: number | null; + boleto_barcode?: string | null; + pix_qrcode?: string | null; + document_file?: string | null; + due_date?: string | null; + scheduled_at?: string | null; + status: PayableStatus; + created_at?: string | null; + updated_at?: string | null; + amount: number | null; + payout_id?: string | null; + bank_account?: PayableBankAccount | null; + last_attempt_status?: PayableLastAttemptStatus | null; + first_name?: string | null; + last_name?: string | null; + legal_name?: string | null; +}; + +export type ListPayablesInput = PaginationParams & { + status?: PayableStatus; + customer_id?: string; + customer_name?: string; + type?: PayableType; + beneficiary_name?: string; +}; + +export type ListPayablesResponse = + | { + data: Payable[]; + pagination: PaginationMetadata; + } + | Payable[]; + +/** + * Vendor bank account for an invoice payable: the same body + * `POST /customers/{customer_id}/bank-accounts` takes, limited to `ach` or `wire`. + * The account belongs to the payable, so no `customer_id` is sent here. + */ +export type CreatePayableBankAccountInput = + | (StrictOmit & { type: "ach" }) + | (StrictOmit & { type: "wire" }); + +export type CreatePayableInput = { + customer_id: string; + currency: PayableCurrency; + from?: PayableParty | null; + to?: PayableParty | null; + line_items?: PayableLineItem[]; + note?: string | null; + discount?: number | null; + taxes?: number | null; + boleto_barcode?: string | null; + pix_qrcode?: string | null; + document_file?: string | null; + due_date?: string | null; + scheduled_at?: string | null; + bank_account?: CreatePayableBankAccountInput | null; +}; + +export type CreatePayableResponse = Payable; + +export type GetPayableInput = string; + +export type GetPayableResponse = Payable; + +export type DeletePayableInput = string; + +export type DeletePayableResponse = Payable; + +export function createPayablesResource(instanceId: string, client: InternalApiClient) { + return { + list(params?: ListPayablesInput): Promise> { + const queryParams = params ? `?${new URLSearchParams(params)}` : ""; + return client.get(`/instances/${instanceId}/payables${queryParams}`); + }, + create( + { ...data }: CreatePayableInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/payables`, data, options); + }, + get(id: GetPayableInput): Promise> { + return client.get(`/instances/${instanceId}/payables/${id}`); + }, + delete( + id: DeletePayableInput, + options?: RequestOptions + ): Promise> { + return client.delete(`/instances/${instanceId}/payables/${id}`, options); + }, + }; +} diff --git a/src/resources/payables/payables.test.ts b/src/resources/payables/payables.test.ts new file mode 100644 index 0000000..9065fe7 --- /dev/null +++ b/src/resources/payables/payables.test.ts @@ -0,0 +1,250 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { BlindPay } from "../../client"; +import type { + CreatePayableInput, + CreatePayableResponse, + DeletePayableResponse, + GetPayableResponse, + ListPayablesResponse, + Payable, +} from "."; + +describe("Payables", () => { + afterEach(() => fetchMock.resetMocks()); + + const blindpay = new BlindPay({ apiKey: "test-key", instanceId: "in_000000000000" }); + + const boletoPayable: Payable = { + id: "pb_000000000000", + instance_id: "in_000000000000", + customer_id: "re_000000000000", + currency: "BRL", + status: "draft", + amount: 15000, + from: null, + to: { + legal_name: "Companhia de Energia SA", + address_line_1: null, + address_line_2: null, + city: null, + state_province_region: null, + postal_code: null, + country: "BR", + tax_id: "12345678000199", + }, + line_items: [], + note: null, + discount: null, + taxes: null, + boleto_barcode: "23793381286000000000000000000000000000000000", + pix_qrcode: null, + document_file: null, + due_date: "2026-11-10", + scheduled_at: null, + created_at: "2026-10-27T00:00:00Z", + updated_at: "2026-10-27T00:00:00Z", + payout_id: null, + last_attempt_status: null, + first_name: null, + last_name: null, + legal_name: "Acme Ltda", + }; + + const invoicePayable: Payable = { + id: "pb_000000000001", + instance_id: "in_000000000000", + customer_id: "re_000000000000", + currency: "USD", + status: "draft", + amount: 120000, + from: { legal_name: "Acme Inc" }, + to: { legal_name: "Northwind Cloud Services Inc", country: "US" }, + line_items: [{ name: "Cloud hosting", quantity: 1, price: 120000 }], + note: "October invoice", + discount: null, + taxes: null, + bank_account: { + type: "ach", + beneficiary_name: "Northwind Cloud Services Inc", + routing_number: "021000021", + account_number: "123456789", + account_type: "checking", + }, + }; + + describe("List payables without pagination params", () => { + it("should return a plain array", async () => { + const mockedResponse: ListPayablesResponse = []; + + fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.payables.list(); + + expect(error).toBeNull(); + expect(data).toEqual([]); + expect(fetchMock.mock.calls[0][0]).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/payables" + ); + }); + }); + + describe("List payables", () => { + it("should list payables", async () => { + const mockedPayables: ListPayablesResponse = { + data: [boletoPayable], + pagination: { + has_more: false, + next_page: null, + prev_page: null, + }, + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedPayables), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.payables.list(); + + expect(error).toBeNull(); + expect(data).toEqual(mockedPayables); + + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe("https://api.blindpay.com/v1/instances/in_000000000000/payables"); + expect(init?.method).toBe("GET"); + }); + + it("should pass filters as query params", async () => { + fetchMock.mockResponseOnce( + JSON.stringify({ + data: [], + pagination: { has_more: false, next_page: null, prev_page: null }, + }), + { headers: { "Content-Type": "application/json" } } + ); + + const { error } = await blindpay.payables.list({ + limit: "10", + status: "draft", + type: "boleto", + customer_id: "re_000000000000", + }); + + expect(error).toBeNull(); + + const [url] = fetchMock.mock.calls[0]; + expect(url).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/payables?limit=10&status=draft&type=boleto&customer_id=re_000000000000" + ); + }); + }); + + describe("Create payable", () => { + it("should create a boleto payable", async () => { + const mockedPayable: CreatePayableResponse = boletoPayable; + + fetchMock.mockResponseOnce(JSON.stringify(mockedPayable), { + headers: { "Content-Type": "application/json" }, + }); + + const input: CreatePayableInput = { + customer_id: "re_000000000000", + currency: "BRL", + boleto_barcode: "23793381286000000000000000000000000000000000", + }; + + const { data, error } = await blindpay.payables.create(input); + + expect(error).toBeNull(); + expect(data).toEqual(mockedPayable); + + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe("https://api.blindpay.com/v1/instances/in_000000000000/payables"); + expect(init?.method).toBe("POST"); + expect(JSON.parse(init?.body as string)).toEqual(input); + }); + + it("should create an invoice payable with a bank account", async () => { + fetchMock.mockResponseOnce(JSON.stringify(invoicePayable), { + headers: { "Content-Type": "application/json" }, + }); + + const input: CreatePayableInput = { + customer_id: "re_000000000000", + currency: "USD", + from: { legal_name: "Acme Inc" }, + to: { legal_name: "Northwind Cloud Services Inc", country: "US" }, + line_items: [{ name: "Cloud hosting", quantity: 1, price: 120000 }], + note: "October invoice", + due_date: "2026-11-30", + bank_account: { + type: "ach", + name: "Northwind Cloud Services Inc", + beneficiary_name: "Northwind Cloud Services Inc", + routing_number: "021000021", + account_number: "123456789", + account_type: "checking", + account_class: "business", + recipient_relationship: "vendor_or_supplier", + address_line_1: "1 Market St", + city: "San Francisco", + state_province_region: "CA", + country: "US", + postal_code: "94105", + }, + }; + + const { data, error } = await blindpay.payables.create(input); + + expect(error).toBeNull(); + expect(data).toEqual(invoicePayable); + + const [, init] = fetchMock.mock.calls[0]; + expect(init?.method).toBe("POST"); + expect(JSON.parse(init?.body as string)).toEqual(input); + }); + }); + + describe("Get payable", () => { + it("should get a payable", async () => { + const mockedPayable: GetPayableResponse = boletoPayable; + + fetchMock.mockResponseOnce(JSON.stringify(mockedPayable), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.payables.get("pb_000000000000"); + + expect(error).toBeNull(); + expect(data).toEqual(mockedPayable); + + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/payables/pb_000000000000" + ); + expect(init?.method).toBe("GET"); + }); + }); + + describe("Delete payable", () => { + it("should delete a payable", async () => { + const mockedPayable: DeletePayableResponse = { ...boletoPayable, status: "canceled" }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedPayable), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.payables.delete("pb_000000000000"); + + expect(error).toBeNull(); + expect(data).toEqual(mockedPayable); + + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/payables/pb_000000000000" + ); + expect(init?.method).toBe("DELETE"); + }); + }); +}); diff --git a/src/resources/payins/index.ts b/src/resources/payins/index.ts index edc72c8..dda4ebc 100644 --- a/src/resources/payins/index.ts +++ b/src/resources/payins/index.ts @@ -12,6 +12,7 @@ import type { PayinTrackingPartnerFee, PayinTrackingPayment, PayinTrackingTransaction, + RequestOptions, StablecoinToken, TransactionStatus, } from "../../../types"; @@ -65,22 +66,22 @@ export type Payin = { tracking_payment: PayinTrackingPayment; tracking_complete: PayinTrackingComplete; tracking_partner_fee?: PayinTrackingPartnerFee; - created_at: string; - updated_at: string; + created_at: string | null; + updated_at: string | null; image_url?: string | null | undefined; first_name?: string | null | undefined; last_name?: string | null | undefined; legal_name?: string | null | undefined; type: AccountClass; payment_method: PayinPaymentMethod; - sender_amount: number; - receiver_amount: number; + sender_amount: number | null; + receiver_amount: number | null; token: StablecoinToken; partner_fee_id?: string | null; partner_fee_amount?: number | null; total_fee_amount?: number | null; - commercial_quotation: number; - blindpay_quotation: number; + commercial_quotation: number | null; + blindpay_quotation: number | null; currency: Extract; billing_fee?: number | null; billing_fee_amount?: number | null; @@ -94,11 +95,22 @@ export type Payin = { pse_full_name?: string | null; pse_tax_id?: string | null; pse_document_type?: Extract | null; + manual_concluded_at?: string; + manual_concluded_by?: string | null; + manual_execution_status?: "pending" | "concluded" | "failed" | null; + partner_fee?: number; + transaction_fee_amount?: number | null; }; export type ListPayinsInput = PaginationParams & { status?: TransactionStatus; customer_id?: string; + customer_name?: string; + bank_account_id?: string; + country?: string; + payment_method?: PayinPaymentMethod; + network?: string; + token?: string; }; export type ListPayinsResponse = @@ -108,10 +120,6 @@ export type ListPayinsResponse = } | Payin[]; -export type CreatePayinInput = { - quote_id: string; -}; - export type GetPayinInput = string; export type GetPayinResponse = Payin; @@ -140,6 +148,9 @@ export type CreateEvmPayinResponse = Pick< payment_method?: PayinPaymentMethod | null; billing_fee?: number | null; sender_amount?: number | null; + billing_fee_amount?: number | null; + partner_fee?: number; + transaction_fee_amount?: number | null; }; export function createPayinsResource(instanceId: string, client: InternalApiClient) { @@ -155,11 +166,16 @@ export function createPayinsResource(instanceId: string, client: InternalApiClie return client.get(`/e/payins/${payinId}`); }, createEvm( - payin_quote_id: CreateEvmPayinInput + payin_quote_id: CreateEvmPayinInput, + options?: RequestOptions ): Promise> { - return client.post(`/instances/${instanceId}/payins/evm`, { - payin_quote_id, - }); + return client.post( + `/instances/${instanceId}/payins/evm`, + { + payin_quote_id, + }, + options + ); }, }; } diff --git a/src/resources/payins/payins-quotes.test.ts b/src/resources/payins/payins-quotes.test.ts index f1e7f22..c4dd0b8 100644 --- a/src/resources/payins/payins-quotes.test.ts +++ b/src/resources/payins/payins-quotes.test.ts @@ -40,6 +40,38 @@ describe("Payin quotes", () => { expect(error).toBeNull(); expect(data).toEqual(mockedPayinQuote); }); + + it("should create a payin quote with only the required fields", async () => { + const mockedPayinQuote: CreatePayinQuoteResponse = { + id: "qu_000000000000", + expires_at: 1712958191, + commercial_quotation: 495, + blindpay_quotation: 505, + receiver_amount: 1010, + sender_amount: 5240, + flat_fee: 50, + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedPayinQuote), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.payins.quotes.create({ + currency_type: "sender", + request_amount: 1000, + payment_method: "pix", + token: "USDC", + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedPayinQuote); + expect(JSON.parse(fetchMock.mock.calls[0][1]?.body as string)).toEqual({ + currency_type: "sender", + request_amount: 1000, + payment_method: "pix", + token: "USDC", + }); + }); }); describe("Get FX rate", () => { diff --git a/src/resources/payins/payins.test.ts b/src/resources/payins/payins.test.ts index e73983b..c8ae609 100644 --- a/src/resources/payins/payins.test.ts +++ b/src/resources/payins/payins.test.ts @@ -148,6 +148,39 @@ describe("Payins", () => { expect(error).toBeNull(); expect(data).toEqual(mockedPayins); }); + + it("should send every list filter as a query parameter", async () => { + fetchMock.mockResponseOnce(JSON.stringify([]), { + headers: { "Content-Type": "application/json" }, + }); + + const { error } = await blindpay.payins.list({ + limit: "10", + status: "completed", + customer_id: "cu_000000000000", + customer_name: "Jane Doe", + bank_account_id: "ba_000000000000", + country: "BR", + payment_method: "pix", + network: "polygon", + token: "USDC", + }); + + expect(error).toBeNull(); + const url = new URL(fetchMock.mock.calls[0][0] as string); + expect(url.pathname).toBe("/v1/instances/in_000000000000/payins"); + expect(Object.fromEntries(url.searchParams)).toEqual({ + limit: "10", + status: "completed", + customer_id: "cu_000000000000", + customer_name: "Jane Doe", + bank_account_id: "ba_000000000000", + country: "BR", + payment_method: "pix", + network: "polygon", + token: "USDC", + }); + }); }); describe("Get payin", () => { diff --git a/src/resources/payins/quotes.ts b/src/resources/payins/quotes.ts index 73fcea8..3c33389 100644 --- a/src/resources/payins/quotes.ts +++ b/src/resources/payins/quotes.ts @@ -3,34 +3,37 @@ import type { Currency, CurrencyType, PayerRules, - PayinPaymentMethod, + PaymentMethod, + RequestOptions, StablecoinToken, } from "../../../types"; import type { InternalApiClient } from "../../internal/api-client"; export type CreatePayinQuoteInput = { - blockchain_wallet_id: string; + blockchain_wallet_id?: string | null; currency_type: CurrencyType; - payment_method: PayinPaymentMethod; + payment_method: PaymentMethod; request_amount: number; token: StablecoinToken; is_otc?: boolean | null; - cover_fees: boolean; - partner_fee_id: string | null; + cover_fees?: boolean | null; + partner_fee_id?: string | null; payer_rules?: PayerRules | null; - wallet_id?: string; + wallet_id?: string | null; + funding_bank_account_id?: string | null; }; export type CreatePayinQuoteResponse = { id: string; - expires_at: number; - commercial_quotation: number; - blindpay_quotation: number; - receiver_amount: number; - sender_amount: number; + expires_at: number | null; + commercial_quotation: number | null; + blindpay_quotation: number | null; + receiver_amount: number | null; + sender_amount: number | null; partner_fee_amount?: number | null; - flat_fee: number; + flat_fee: number | null; is_otc?: boolean | null; + billing_fee_amount?: number | null; }; export type GetPayinFxRateInput = { @@ -41,24 +44,26 @@ export type GetPayinFxRateInput = { }; export type GetPayinFxRateResponse = { - commercial_quotation: number; - blindpay_quotation: number; + commercial_quotation: number | null; + blindpay_quotation: number | null; result_amount: number; - instance_flat_fee: number; + instance_flat_fee: number | null; instance_percentage_fee: number; }; export function createPayinQuotesResource(instanceId: string, client: InternalApiClient) { return { - create({ - ...data - }: CreatePayinQuoteInput): Promise> { - return client.post(`/instances/${instanceId}/payin-quotes`, data); + create( + { ...data }: CreatePayinQuoteInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/payin-quotes`, data, options); }, - getFxRate({ - ...data - }: GetPayinFxRateInput): Promise> { - return client.post(`/instances/${instanceId}/payin-quotes/fx`, data); + getFxRate( + { ...data }: GetPayinFxRateInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/payin-quotes/fx`, data, options); }, }; } diff --git a/src/resources/payouts/index.ts b/src/resources/payouts/index.ts index 4493240..6a80f31 100644 --- a/src/resources/payouts/index.ts +++ b/src/resources/payouts/index.ts @@ -1,5 +1,6 @@ import type { AccountClass, + AchCopDocument, BankAccountType, BlindpayApiResponse, Country, @@ -13,7 +14,10 @@ import type { PayoutTrackingPayment, PayoutTrackingTransaction, Rail, + RequestOptions, StablecoinToken, + SuccessResponse, + TrackingStatus, TransactionDocumentType, TransactionStatus, } from "../../../types"; @@ -26,82 +30,118 @@ export type Payout = { id: string; status: TransactionStatus; sender_wallet_address: string; - signed_transaction: string; + signed_transaction: string | null; quote_id: string; instance_id: string; tracking_transaction: PayoutTrackingTransaction; tracking_payment: PayoutTrackingPayment; - tracking_liquidity: PayoutTrackingLiquidity; + tracking_liquidity: PayoutTrackingLiquidity | null; tracking_complete: PayoutTrackingComplete; tracking_partner_fee: PayoutTrackingPartnerFee; - created_at: string; - updated_at: string; - image_url: string; - first_name: string; - last_name: string; - legal_name: string; + created_at: string | null; + updated_at: string | null; + image_url: string | null; + first_name: string | null; + last_name: string | null; + legal_name: string | null; network: Network; token: StablecoinToken; - description: string; - sender_amount: number; - receiver_amount: number; + description: string | null; + sender_amount: number | null; + receiver_amount: number | null; partner_fee_id?: string | null; - partner_fee_amount: number; - commercial_quotation: number; - blindpay_quotation: number; - total_fee_amount: number; - customer_local_amount: number; + partner_fee_amount: number | null; + commercial_quotation: number | null; + blindpay_quotation: number | null; + total_fee_amount: number | null; + customer_local_amount: number | null; currency: Exclude; - transaction_document_file: string; - transaction_document_type: TransactionDocumentType; - transaction_document_id: string; - name: string; - type: Rail; - pix_key?: string; - account_number?: string; - routing_number?: string; - country?: Country; - account_class?: AccountClass; - address_line_1?: string; - address_line_2?: string; - city?: string; - state_province_region?: string; - postal_code?: string; - account_type?: BankAccountType; - ach_cop_beneficiary_first_name?: string; - ach_cop_bank_account?: string; - ach_cop_bank_code?: string; - ach_cop_beneficiary_last_name?: string; - ach_cop_document_id?: string; - ach_cop_document_type?: string; - ach_cop_email?: string; - beneficiary_name?: string; - spei_clabe?: string; - spei_protocol?: SpeiProtocol; - spei_institution_code?: string; - swift_beneficiary_country?: Country; - swift_code_bic?: string; - swift_account_holder_name?: string; - swift_account_number_iban?: string; - transfers_account?: string; - transfers_type: "CVU" | "CBU" | "ALIAS"; - has_virtual_account: boolean; + transaction_document_file: string | null; + transaction_document_type: TransactionDocumentType | null; + transaction_document_id: string | null; + name: string | null; + type: Rail | null; + pix_key?: string | null; + account_number?: string | null; + routing_number?: string | null; + country?: Country | null; + account_class?: AccountClass | null; + address_line_1?: string | null; + address_line_2?: string | null; + city?: string | null; + state_province_region?: string | null; + postal_code?: string | null; + account_type?: BankAccountType | null; + ach_cop_beneficiary_first_name?: string | null; + ach_cop_bank_account?: string | null; + ach_cop_bank_code?: string | null; + ach_cop_beneficiary_last_name?: string | null; + ach_cop_document_id?: string | null; + ach_cop_document_type?: AchCopDocument | null; + ach_cop_email?: string | null; + beneficiary_name?: string | null; + spei_clabe?: string | null; + spei_protocol?: SpeiProtocol | null; + spei_institution_code?: string | null; + swift_beneficiary_country?: Country | null; + swift_code_bic?: string | null; + swift_account_holder_name?: string | null; + swift_account_number_iban?: string | null; + transfers_account?: string | null; + transfers_type: "CVU" | "CBU" | "ALIAS" | null; + has_virtual_account: boolean | null; billing_fee_amount?: number | null; cpn_payment_id?: string | null; jpm_track_data?: Record | string | null; ted_bank_code?: string | null; ted_branch_code?: string | null; ted_cpf_cnpj?: string | null; + bank_account_id?: string | null; + faster_payments_account_number?: string | null; + faster_payments_beneficiary_address_line_1?: string | null; + faster_payments_beneficiary_city?: string | null; + faster_payments_beneficiary_country?: Country | null; + faster_payments_beneficiary_legal_name?: string | null; + faster_payments_beneficiary_postal_code?: string | null; + faster_payments_sort_code?: string | null; + payable_id?: string | null; + sepa_beneficiary_address_line_1?: string | null; + sepa_beneficiary_city?: string | null; + sepa_beneficiary_country?: Country | null; + sepa_beneficiary_legal_name?: string | null; + sepa_beneficiary_postal_code?: string | null; + sepa_iban?: string | null; + partner_fee?: number; + pix_safe_bank_code?: string | null; + pix_safe_branch_code?: string | null; + pix_safe_cpf_cnpj?: string | null; + sender_legal_name?: string | null; + tracking_documents?: { + step: TrackingStatus; + status?: "waiting_documents" | "compliance_reviewing" | null; + reviewed_by?: string | null; + completed_at?: string | null; + } | null; + transaction_fee_amount?: number | null; }; export type ListPayoutsInput = PaginationParams & { customer_id?: string; + status?: TransactionStatus; + customer_name?: string; + bank_account_id?: string; + country?: string; + payment_method?: Rail; + network?: string; + token?: string; }; -export type ListPayoutsResponse = { - data: Payout[]; - pagination: PaginationMetadata; -}; +export type ListPayoutsResponse = + | { + data: Payout[]; + pagination: PaginationMetadata; + } + | Payout[]; export type CreatePayoutInput = { customer_id: string; @@ -122,9 +162,7 @@ export type SubmitPayoutDocumentsInput = { description?: string; }; -export type SubmitPayoutDocumentsResponse = { - id: string; -}; +export type SubmitPayoutDocumentsResponse = SuccessResponse; export type GetPayoutInput = string; @@ -136,7 +174,8 @@ export type GetPayoutTrackResponse = Payout; export type AuthorizeStellarTokenInput = { quote_id: string; - sender_wallet_address: string; + sender_wallet_address?: string; + wallet_id?: string; }; export type AuthorizeStellarTokenResponse = { @@ -145,8 +184,9 @@ export type AuthorizeStellarTokenResponse = { export type CreateStellarPayoutInput = { quote_id: string; - sender_wallet_address: string; - signed_transaction?: string; + sender_wallet_address?: string; + signed_transaction?: string | null; + wallet_id?: string; }; export type CreateStellarPayoutResponse = { @@ -157,13 +197,26 @@ export type CreateStellarPayoutResponse = { tracking_payment?: PayoutTrackingPayment; tracking_transaction?: PayoutTrackingTransaction; tracking_partner_fee?: PayoutTrackingPartnerFee; - tracking_liquidity?: PayoutTrackingLiquidity; - customer_id: string; + tracking_liquidity?: PayoutTrackingLiquidity | null; + customer_id: string | null; + payable_id?: string | null; + bank_account_id?: string | null; + billing_fee_amount?: number | null; + offramp_wallet_id?: string | null; + partner_fee?: number; + tracking_documents?: { + step: TrackingStatus; + status?: "waiting_documents" | "compliance_reviewing" | null; + reviewed_by?: string | null; + completed_at?: string | null; + } | null; + transaction_fee_amount?: number | null; }; export type CreateEvmPayoutInput = { quote_id: string; - sender_wallet_address: string; + sender_wallet_address?: string; + wallet_id?: string; }; export type CreateEvmPayoutResponse = { @@ -174,14 +227,27 @@ export type CreateEvmPayoutResponse = { tracking_payment?: PayoutTrackingPayment; tracking_transaction?: PayoutTrackingTransaction; tracking_partner_fee?: PayoutTrackingPartnerFee; - tracking_liquidity?: PayoutTrackingLiquidity; - customer_id: string; + tracking_liquidity?: PayoutTrackingLiquidity | null; + customer_id: string | null; + payable_id?: string | null; + bank_account_id?: string | null; + billing_fee_amount?: number | null; + offramp_wallet_id?: string | null; + partner_fee?: number; + tracking_documents?: { + step: TrackingStatus; + status?: "waiting_documents" | "compliance_reviewing" | null; + reviewed_by?: string | null; + completed_at?: string | null; + } | null; + transaction_fee_amount?: number | null; }; export type CreateSolanaPayoutInput = { quote_id: string; - sender_wallet_address: string; - signed_transaction: string | null; + sender_wallet_address?: string; + signed_transaction?: string | null; + wallet_id?: string; }; export type CreateSolanaPayoutResponse = { @@ -194,6 +260,18 @@ export type CreateSolanaPayoutResponse = { tracking_partner_fee?: PayoutTrackingPartnerFee | null; tracking_liquidity?: PayoutTrackingLiquidity | null; customer_id: string | null; + payable_id?: string | null; + bank_account_id?: string | null; + billing_fee_amount?: number | null; + offramp_wallet_id?: string | null; + partner_fee?: number; + tracking_documents?: { + step: TrackingStatus; + status?: "waiting_documents" | "compliance_reviewing" | null; + reviewed_by?: string | null; + completed_at?: string | null; + } | null; + transaction_fee_amount?: number | null; }; export function createPayoutsResource(instanceId: string, client: InternalApiClient) { @@ -210,35 +288,39 @@ export function createPayoutsResource(instanceId: string, client: InternalApiCli ): Promise> { return client.get(`/e/payouts/${payoutId}`); }, - authorizeStellarToken({ - ...data - }: AuthorizeStellarTokenInput): Promise< - BlindpayApiResponse - > { - return client.post(`/instances/${instanceId}/payouts/stellar/authorize`, data); + authorizeStellarToken( + { ...data }: AuthorizeStellarTokenInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/payouts/stellar/authorize`, data, options); }, - createStellar({ - ...data - }: CreateStellarPayoutInput): Promise> { - return client.post(`/instances/${instanceId}/payouts/stellar`, data); + createStellar( + { ...data }: CreateStellarPayoutInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/payouts/stellar`, data, options); }, - createEvm({ - ...data - }: CreateEvmPayoutInput): Promise> { - return client.post(`/instances/${instanceId}/payouts/evm`, data); + createEvm( + { ...data }: CreateEvmPayoutInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/payouts/evm`, data, options); }, - createSolana({ - ...data - }: CreateSolanaPayoutInput): Promise> { - return client.post(`/instances/${instanceId}/payouts/solana`, data); + createSolana( + { ...data }: CreateSolanaPayoutInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/payouts/solana`, data, options); }, - submitDocuments({ - payout_id, - ...data - }: SubmitPayoutDocumentsInput): Promise< - BlindpayApiResponse - > { - return client.post(`/instances/${instanceId}/payouts/${payout_id}/documents`, data); + submitDocuments( + { payout_id, ...data }: SubmitPayoutDocumentsInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/payouts/${payout_id}/documents`, + data, + options + ); }, }; } diff --git a/src/resources/payouts/payouts.test.ts b/src/resources/payouts/payouts.test.ts index f13f006..6c627fe 100644 --- a/src/resources/payouts/payouts.test.ts +++ b/src/resources/payouts/payouts.test.ts @@ -16,6 +16,24 @@ describe("Payouts", () => { const blindpay = new BlindPay({ apiKey: "test-key", instanceId: "in_000000000000" }); + describe("List payouts without pagination params", () => { + it("should return a plain array", async () => { + const mockedResponse: ListPayoutsResponse = []; + + fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.payouts.list(); + + expect(error).toBeNull(); + expect(data).toEqual([]); + expect(fetchMock.mock.calls[0][0]).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/payouts" + ); + }); + }); + describe("List payouts", () => { it("should list payouts", async () => { const mockedPayouts: ListPayoutsResponse = { @@ -565,11 +583,86 @@ describe("Payouts", () => { }); }); + describe("List payouts with filters", () => { + it("should send every filter as a query param", async () => { + fetchMock.mockResponseOnce(JSON.stringify([]), { + headers: { "Content-Type": "application/json" }, + }); + + const { error } = await blindpay.payouts.list({ + customer_id: "re_000000000000", + status: "on_hold", + customer_name: "John", + bank_account_id: "ba_000000000000", + country: "BR", + payment_method: "faster_payments", + network: "base", + token: "USDC", + }); + + expect(error).toBeNull(); + expect(fetchMock.mock.calls[0][0]).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/payouts?customer_id=re_000000000000&status=on_hold&customer_name=John&bank_account_id=ba_000000000000&country=BR&payment_method=faster_payments&network=base&token=USDC" + ); + }); + }); + + describe("Create payout from a BlindPay-managed wallet", () => { + it("should create an EVM payout with only quote_id and wallet_id", async () => { + const mockedEvmPayout: CreateEvmPayoutResponse = { + id: "pa_000000000000", + status: "processing", + sender_wallet_address: "0x123...890", + tracking_complete: { step: "processing" }, + tracking_payment: { step: "processing" }, + tracking_transaction: { step: "processing" }, + tracking_liquidity: { step: "processing" }, + customer_id: "re_000000000000", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedEvmPayout), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.payouts.createEvm({ + quote_id: "qu_000000000000", + wallet_id: "bl_000000000000", + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedEvmPayout); + const [, init] = fetchMock.mock.calls[0]; + expect(JSON.parse(init?.body as string)).toEqual({ + quote_id: "qu_000000000000", + wallet_id: "bl_000000000000", + }); + }); + + it("should accept quote_id alone on stellar, solana and stellar authorize", async () => { + fetchMock.mockResponse(JSON.stringify({ transaction_hash: "hash" }), { + headers: { "Content-Type": "application/json" }, + }); + + await blindpay.payouts.authorizeStellarToken({ quote_id: "qu_000000000000" }); + await blindpay.payouts.createStellar({ quote_id: "qu_000000000000" }); + await blindpay.payouts.createSolana({ + quote_id: "qu_000000000000", + wallet_id: "bl_000000000000", + }); + + expect( + fetchMock.mock.calls.map(([, init]) => JSON.parse(init?.body as string)) + ).toEqual([ + { quote_id: "qu_000000000000" }, + { quote_id: "qu_000000000000" }, + { quote_id: "qu_000000000000", wallet_id: "bl_000000000000" }, + ]); + }); + }); + describe("Submit payout documents", () => { it("should submit payout documents", async () => { - const mockedResponse: SubmitPayoutDocumentsResponse = { - id: "pd_000000000000", - }; + const mockedResponse: SubmitPayoutDocumentsResponse = { success: true }; fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { headers: { "Content-Type": "application/json" }, diff --git a/src/resources/quotes/index.ts b/src/resources/quotes/index.ts index 90fea94..d91c856 100644 --- a/src/resources/quotes/index.ts +++ b/src/resources/quotes/index.ts @@ -3,28 +3,30 @@ import type { Currency, CurrencyType, Network, + RequestOptions, StablecoinToken, } from "../../../types"; import type { InternalApiClient } from "../../internal/api-client"; export type CreateQuoteInput = { - bank_account_id: string; - currency_type: CurrencyType; - cover_fees: boolean; - request_amount: number; + bank_account_id?: string | null; + currency_type?: CurrencyType; + cover_fees?: boolean | null; + request_amount?: number | null; network: Network; token: StablecoinToken; description?: string | null; partner_fee_id?: string | null; refund_wallet_address?: string | null; + payable_id?: string | null; }; export type CreateQuoteResponse = { id: string; - expires_at: number; - commercial_quotation: number; - blindpay_quotation: number; - receiver_amount: number; - sender_amount: number; + expires_at: number | null; + commercial_quotation: number | null; + blindpay_quotation: number | null; + receiver_amount: number | null; + sender_amount: number | null; partner_fee_amount?: number | null; flat_fee?: number | null; contract?: { @@ -40,6 +42,7 @@ export type CreateQuoteResponse = { } | null; customer_local_amount?: number | null; description?: string | null; + billing_fee_amount?: number | null; }; export type GetFxRateInput = { @@ -50,8 +53,8 @@ export type GetFxRateInput = { }; export type GetFxRateResponse = { - commercial_quotation: number; - blindpay_quotation: number; + commercial_quotation: number | null; + blindpay_quotation: number | null; result_amount: number; instance_flat_fee?: number | null; instance_percentage_fee: number; @@ -59,12 +62,18 @@ export type GetFxRateResponse = { export function createQuotesResource(instanceId: string, client: InternalApiClient) { return { - create({ ...data }: CreateQuoteInput): Promise> { - return client.post(`/instances/${instanceId}/quotes`, data); + create( + { ...data }: CreateQuoteInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/quotes`, data, options); }, - getFxRate({ ...data }: GetFxRateInput): Promise> { - return client.post(`/instances/${instanceId}/quotes/fx`, data); + getFxRate( + { ...data }: GetFxRateInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/quotes/fx`, data, options); }, }; } diff --git a/src/resources/request-options.test.ts b/src/resources/request-options.test.ts new file mode 100644 index 0000000..8c01fab --- /dev/null +++ b/src/resources/request-options.test.ts @@ -0,0 +1,31 @@ +import { readdirSync, readFileSync, statSync } from "node:fs"; +import { join, relative } from "node:path"; +import { describe, expect, it } from "vitest"; + +const RESOURCES = __dirname; + +function sourceFiles(dir: string): string[] { + return readdirSync(dir).flatMap((name) => { + const path = join(dir, name); + if (statSync(path).isDirectory()) return sourceFiles(path); + return path.endsWith(".ts") && !path.endsWith(".test.ts") ? [path] : []; + }); +} + +/** Every `client.post|put|patch|delete(...)` call whose last argument isn't `options`. */ +function mutationsWithoutOptions(): string[] { + return sourceFiles(RESOURCES).flatMap((file) => { + const source = readFileSync(file, "utf8"); + const calls = source.matchAll(/client\.(post|put|patch|delete)\(([\s\S]*?)\);/g); + return [...calls] + .filter(([, , args]) => !args.trim().startsWith("`/e/")) + .filter(([, , args]) => !/\boptions,?$/.test(args.trim())) + .map(([call]) => `${relative(RESOURCES, file)}: ${call.split("\n")[0]}`); + }); +} + +describe("RequestOptions", () => { + it("is forwarded by every authenticated mutation, so each one can send an Idempotency-Key", () => { + expect(mutationsWithoutOptions()).toEqual([]); + }); +}); diff --git a/src/resources/rfi/index.ts b/src/resources/rfi/index.ts new file mode 100644 index 0000000..707c0b1 --- /dev/null +++ b/src/resources/rfi/index.ts @@ -0,0 +1,118 @@ +import type { AccountClass, BlindpayApiResponse, RequestOptions } from "../../../types"; +import type { InternalApiClient } from "../../internal/api-client"; + +export type RfiStatus = "pending" | "submitted" | "expired" | "cancelled"; + +export type RfiDocumentType = + | "ADDRESS_PROOF_DOCUMENT" + | "SOURCE_OF_FUNDS_DOCUMENT" + | "BANK_STATEMENT_DOCUMENT" + | "USER_SELFIE" + | "TAX_CERTIFICATE" + | "VISA_DOCUMENT" + | "OTHER"; + +export type RfiField = { + key: string; + label: string; + regex?: string; + required: boolean; + items?: Array<{ + label: string; + value: string; + }>; + multiple?: boolean; + aiprise_document_type?: RfiDocumentType; +}; + +export type RfiSection = { + title: string; + description: string; + supporting_document?: string; + fields: RfiField[]; +}; + +/** Answers keyed by RfiField.key: a text value, or a list of uploaded file URLs. */ +export type RfiResponse = Record; + +export type InstanceRfi = { + id: string; + instance_id: string; + status: RfiStatus; + request: RfiSection[]; + response: RfiResponse; + expires_at: string; + submitted_at: string | null; + created_at: string; +}; + +export type CustomerRfi = { + id: string; + customer_id: string; + instance_id: string; + status: RfiStatus; + request: RfiSection[]; + response: RfiResponse; + expires_at: string; + submitted_at: string | null; + created_at: string; + customer_type?: AccountClass; + customer_aiprise_session_id?: string | null; + customer_aiprise_user_profile_id?: string | null; + customer_kyc_status?: string; +}; + +export type SubmitRfiResponse = + | { success: true } + | { success: false; reason: "no_pending_rfi" | "already_resolved" }; + +export type GetInstanceRfiResponse = InstanceRfi | null; + +export type SubmitInstanceRfiInput = { + response: RfiResponse; +}; + +export type GetCustomerRfiInput = string; + +export type GetCustomerRfiResponse = CustomerRfi | null; + +export type SubmitCustomerRfiInput = { + customer_id: string; + response: RfiResponse; +}; + +export function createInstanceRfiResource(instanceId: string, client: InternalApiClient) { + return { + /** Returns the open (pending) RFI for this instance, or null if there is none. */ + get(): Promise> { + return client.get(`/instances/${instanceId}/rfi`); + }, + /** On `{ success: false }` there is no pending RFI: refetch with `get` instead of retrying. */ + submit( + { response }: SubmitInstanceRfiInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/rfi`, response, options); + }, + }; +} + +export function createCustomerRfiResource(instanceId: string, client: InternalApiClient) { + return { + /** Returns the open (pending) RFI for this customer, or null if there is none. */ + get(customerId: GetCustomerRfiInput): Promise> { + return client.get(`/instances/${instanceId}/customers/${customerId}/rfi`); + }, + /** On success the customer's kyc_status flips back to verifying. On `{ success: false }`, refetch with `get` instead of retrying. */ + submit( + { customer_id, response }: SubmitCustomerRfiInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/customers/${customer_id}/rfi`, + response, + options + ); + }, + }; +} diff --git a/src/resources/rfi/rfi.test.ts b/src/resources/rfi/rfi.test.ts new file mode 100644 index 0000000..8cd1db3 --- /dev/null +++ b/src/resources/rfi/rfi.test.ts @@ -0,0 +1,154 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { BlindPay } from "../../client"; +import type { GetCustomerRfiResponse, GetInstanceRfiResponse, SubmitRfiResponse } from "."; + +describe("RFI", () => { + afterEach(() => fetchMock.resetMocks()); + + const blindpay = new BlindPay({ apiKey: "test-key", instanceId: "in_000000000000" }); + + const request = [ + { + title: "Source of funds", + description: "Tell us where the funds come from.", + supporting_document: "https://example.com/guide.pdf", + fields: [ + { + key: "source_of_funds", + label: "Source of funds", + required: true, + items: [{ label: "Salary", value: "salary" }], + }, + { + key: "bank_statement", + label: "Bank statement", + required: true, + multiple: true, + aiprise_document_type: "BANK_STATEMENT_DOCUMENT" as const, + }, + ], + }, + ]; + + describe("Instance RFI", () => { + it("should get the open instance RFI", async () => { + const mockedRfi: GetInstanceRfiResponse = { + id: "rf_000000000000", + instance_id: "in_000000000000", + status: "pending", + request, + response: {}, + expires_at: "2025-01-01T00:00:00Z", + submitted_at: null, + created_at: "2025-01-01T00:00:00Z", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedRfi), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.instances.rfi.get(); + + expect(error).toBeNull(); + expect(data).toEqual(mockedRfi); + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe("https://api.blindpay.com/v1/instances/in_000000000000/rfi"); + expect(init?.method).toBe("GET"); + }); + + it("should return null when the instance has no open RFI", async () => { + fetchMock.mockResponseOnce("null", { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.instances.rfi.get(); + + expect(error).toBeNull(); + expect(data).toBeNull(); + }); + + it("should submit an instance RFI response", async () => { + const mockedResponse: SubmitRfiResponse = { success: true }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.instances.rfi.submit({ + response: { + source_of_funds: "salary", + bank_statement: ["https://example.com/statement.pdf"], + }, + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedResponse); + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe("https://api.blindpay.com/v1/instances/in_000000000000/rfi"); + expect(init?.method).toBe("POST"); + expect(JSON.parse(init?.body as string)).toEqual({ + source_of_funds: "salary", + bank_statement: ["https://example.com/statement.pdf"], + }); + }); + }); + + describe("Customer RFI", () => { + it("should get the open customer RFI", async () => { + const mockedRfi: GetCustomerRfiResponse = { + id: "rf_000000000000", + customer_id: "cu_000000000000", + instance_id: "in_000000000000", + status: "pending", + request, + response: {}, + expires_at: "2025-01-01T00:00:00Z", + submitted_at: null, + created_at: "2025-01-01T00:00:00Z", + customer_type: "individual", + customer_aiprise_session_id: null, + customer_aiprise_user_profile_id: null, + customer_kyc_status: "compliance_request", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedRfi), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.customers.rfi.get("cu_000000000000"); + + expect(error).toBeNull(); + expect(data).toEqual(mockedRfi); + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/customers/cu_000000000000/rfi" + ); + expect(init?.method).toBe("GET"); + }); + + it("should submit a customer RFI response", async () => { + const mockedResponse: SubmitRfiResponse = { + success: false, + reason: "no_pending_rfi", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.customers.rfi.submit({ + customer_id: "cu_000000000000", + response: { source_of_funds: "salary" }, + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedResponse); + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe( + "https://api.blindpay.com/v1/instances/in_000000000000/customers/cu_000000000000/rfi" + ); + expect(init?.method).toBe("POST"); + expect(JSON.parse(init?.body as string)).toEqual({ source_of_funds: "salary" }); + }); + }); +}); diff --git a/src/resources/terms-of-service/index.ts b/src/resources/terms-of-service/index.ts index 088096d..8b81d24 100644 --- a/src/resources/terms-of-service/index.ts +++ b/src/resources/terms-of-service/index.ts @@ -3,8 +3,8 @@ import type { InternalApiClient } from "../../internal/api-client"; export type InitiateInput = { idempotency_key: string; - customer_id: string | null; - redirect_url: string | null; + customer_id?: string | null; + redirect_url?: string | null; }; export type InitiateResponse = { diff --git a/src/resources/terms-of-service/terms-of-service.test.ts b/src/resources/terms-of-service/terms-of-service.test.ts index aede016..3d7cf8f 100644 --- a/src/resources/terms-of-service/terms-of-service.test.ts +++ b/src/resources/terms-of-service/terms-of-service.test.ts @@ -26,5 +26,28 @@ describe("Terms of Service", () => { expect(error).toBeNull(); expect(data).toEqual(mockedUrl); }); + + it("should initiate terms of service with only an idempotency key", async () => { + const mockedUrl: InitiateResponse = { + url: "https://app.blindpay.com/e/terms-of-service?session_token=token", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedUrl), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.instances.tos.initiate({ + idempotency_key: "123e4567-e89b-12d3-a456-426614174000", + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedUrl); + + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe("https://api.blindpay.com/v1/e/instances/in_000000000000/tos"); + expect(JSON.parse(init?.body as string)).toEqual({ + idempotency_key: "123e4567-e89b-12d3-a456-426614174000", + }); + }); }); }); diff --git a/src/resources/transfers/index.ts b/src/resources/transfers/index.ts index 2e15cb3..a5a3704 100644 --- a/src/resources/transfers/index.ts +++ b/src/resources/transfers/index.ts @@ -3,9 +3,10 @@ import type { Network, PaginationMetadata, PaginationParams, - StablecoinToken, + RequestOptions, TrackingStatus, TransactionStatus, + WalletToken, } from "../../../types"; import type { InternalApiClient } from "../../internal/api-client"; @@ -33,36 +34,41 @@ export type Transfer = { tracking_paymaster: TransferTrackingStep; tracking_bridge_swap: TransferTrackingStep; tracking_complete: TransferTrackingStep; - tracking_partner_fee: TransferTrackingStep; - created_at: string; - updated_at: string; - image_url?: string; - first_name?: string; - last_name?: string; - legal_name?: string; + tracking_partner_fee: TransferTrackingStep | null; + created_at: string | null; + updated_at: string | null; + image_url?: string | null; + first_name?: string | null; + last_name?: string | null; + legal_name?: string | null; wallet_id: string; - sender_token: StablecoinToken; + sender_token: WalletToken; sender_amount: number; receiver_amount: number; customer_network: Network; - customer_token: StablecoinToken; + customer_token: WalletToken; customer_wallet_address: string; partner_fee_amount: number | null; customer_id: string; - address: string; + address: string | null; network: Network; + partner_flat_fee?: number; + partner_percentage_fee?: number; + external_id?: string | null; }; export type CreateTransferQuoteInput = { wallet_id: string; - sender_token: StablecoinToken; + sender_token: WalletToken; customer_wallet_address: string; - customer_token: StablecoinToken; + customer_token: WalletToken; customer_network: Network; request_amount: number; cover_fees?: boolean | null; amount_reference: "sender" | "receiver"; partner_fee_id?: string | null; + partner_flat_fee?: number; + partner_percentage_fee?: number; }; export type CreateTransferQuoteResponse = { @@ -74,6 +80,8 @@ export type CreateTransferQuoteResponse = { sender_amount: number; partner_fee_amount: number | null; flat_fee: number; + partner_flat_fee?: number; + partner_percentage_fee?: number; }; export type CreateTransferInput = { @@ -87,10 +95,16 @@ export type CreateTransferResponse = { tracking_complete: TransferTrackingStep; tracking_paymaster: TransferTrackingStep; tracking_transaction_monitoring: TransferTrackingTransactionMonitoring; - tracking_partner_fee: TransferTrackingStep; + tracking_partner_fee: TransferTrackingStep | null; }; -export type ListTransfersInput = PaginationParams; +export type ListTransfersInput = PaginationParams & { + customer_id?: string; + wallet_id?: string; + status?: "processing" | "failed" | "refunded" | "completed"; + network?: Network; + token?: WalletToken; +}; export type ListTransfersResponse = { data: Transfer[]; @@ -108,18 +122,18 @@ export type GetTransferTrackResponse = Transfer; export function createTransfersResource(instanceId: string, client: InternalApiClient) { return { quotes: { - create({ - ...data - }: CreateTransferQuoteInput): Promise< - BlindpayApiResponse - > { - return client.post(`/instances/${instanceId}/transfer-quotes`, data); + create( + { ...data }: CreateTransferQuoteInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/transfer-quotes`, data, options); }, }, - create({ - ...data - }: CreateTransferInput): Promise> { - return client.post(`/instances/${instanceId}/transfers`, data); + create( + { ...data }: CreateTransferInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/transfers`, data, options); }, list(params?: ListTransfersInput): Promise> { const queryParams = params ? `?${new URLSearchParams(params)}` : ""; diff --git a/src/resources/transfers/transfers.test.ts b/src/resources/transfers/transfers.test.ts index 10c197b..66e758c 100644 --- a/src/resources/transfers/transfers.test.ts +++ b/src/resources/transfers/transfers.test.ts @@ -132,6 +132,37 @@ describe("Transfers", () => { expect(error).toBeNull(); expect(data).toEqual(mockedTransfers); }); + + it("should send every list filter as a query parameter", async () => { + fetchMock.mockResponseOnce( + JSON.stringify({ + data: [], + pagination: { has_more: false, next_page: "", prev_page: "" }, + }), + { headers: { "Content-Type": "application/json" } } + ); + + const { error } = await blindpay.transfers.list({ + limit: "10", + customer_id: "cu_000000000000", + wallet_id: "wa_000000000000", + status: "refunded", + network: "base", + token: "EURC", + }); + + expect(error).toBeNull(); + const url = new URL(fetchMock.mock.calls[0][0] as string); + expect(url.pathname).toBe("/v1/instances/in_000000000000/transfers"); + expect(Object.fromEntries(url.searchParams)).toEqual({ + limit: "10", + customer_id: "cu_000000000000", + wallet_id: "wa_000000000000", + status: "refunded", + network: "base", + token: "EURC", + }); + }); }); describe("Get transfer", () => { diff --git a/src/resources/upload/index.ts b/src/resources/upload/index.ts index 4b53517..252a5db 100644 --- a/src/resources/upload/index.ts +++ b/src/resources/upload/index.ts @@ -1,6 +1,8 @@ -import type { BlindpayApiResponse } from "../../../types"; +import type { BlindpayApiResponse, RequestOptions } from "../../../types"; +import type { InternalApiClient } from "../../internal/api-client"; +import { toErrorResponse } from "../../internal/error-response"; -export type UploadBucket = "avatar" | "onboarding" | "limit_increase"; +export type UploadBucket = "avatar" | "onboarding" | "limit_increase" | "documents"; export type UploadInput = { file: File | Blob; @@ -12,9 +14,89 @@ export type UploadResponse = { file_url: string; }; -export function createUploadResource(baseUrl: string, headers: Record) { +export type UploadAnalyzeDocumentType = + | "proof_of_address" + | "identity_document" + | "incorporation_document" + | "proof_of_ownership" + | "source_of_funds" + | "selfie" + | "bank_statement" + | "tax_return" + | "proof_of_income" + | "financial_statement" + | "invoice" + | "transaction_document" + | "passport" + | "pay_stub" + | "employment_letter" + | "investment" + | "crypto_exchange" + | "blockchain_wallet" + | "contract" + | "accounts_receivable" + | "merchant_processor" + | "shareholder_loan"; + +export type UploadAnalyzeApprovalRate = "low" | "medium" | "high"; + +export type UploadAnalyzeInput = { + file: File | Blob; + type: UploadAnalyzeDocumentType; + metadata?: string; + instance_id?: string; +}; + +export type UploadAnalyzeResponse = { + approval_rate: UploadAnalyzeApprovalRate; + description: string; +}; + +export type PresignInput = { + file_url: string; + instance_id?: string; +}; + +export type PresignResponse = { + file_url: string; + expires_at: string; +}; + +export function createUploadResource( + instanceId: string, + baseUrl: string, + headers: Record, + client: InternalApiClient +) { + async function postMultipart( + path: string, + formData: FormData, + instance_id: string + ): Promise> { + const queryParams = `?${new URLSearchParams({ instance_id })}`; + + const { "Content-Type": _, ...headersWithoutContentType } = headers; + + const response = await fetch(`${baseUrl}${path}${queryParams}`, { + method: "POST", + headers: headersWithoutContentType, + body: formData, + }); + + if (!response.ok) { + return { data: null, error: toErrorResponse(await response.json()) }; + } + + const data = await response.json(); + + return { + data, + error: null, + }; + } + return { - async upload({ + upload({ file, bucket, instance_id, @@ -23,32 +105,32 @@ export function createUploadResource(baseUrl: string, headers: Record> { + const formData = new FormData(); + formData.append("file", file); + formData.append("type", type); + if (metadata !== undefined) { + formData.append("metadata", metadata); } - const data = await response.json(); - - return { + return postMultipart("/upload/analyze", formData, instance_id ?? instanceId); + }, + presign( + { instance_id, ...data }: PresignInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/presign?${new URLSearchParams({ instance_id: instance_id ?? instanceId })}`, data, - error: null, - }; + options + ); }, }; } diff --git a/src/resources/upload/upload.test.ts b/src/resources/upload/upload.test.ts index 0b330ad..30c1e98 100644 --- a/src/resources/upload/upload.test.ts +++ b/src/resources/upload/upload.test.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, it } from "vitest"; import { BlindPay } from "../../client"; -import type { UploadResponse } from "."; +import type { PresignResponse, UploadAnalyzeResponse, UploadResponse } from "."; describe("Upload", () => { afterEach(() => fetchMock.resetMocks()); @@ -47,6 +47,172 @@ describe("Upload", () => { expect(error).toBeNull(); expect(data).toEqual(mockedUpload); + + const [url] = fetchMock.mock.calls[0]; + expect(url).toBe("https://api.blindpay.com/v1/upload?instance_id=in_000000000000"); + }); + + it("should send an explicit instance_id instead of the client's", async () => { + const mockedUpload: UploadResponse = { + file_url: "https://storage.blindpay.com/uploads/abc123.pdf", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedUpload), { + headers: { "Content-Type": "application/json" }, + }); + + const file = new Blob(["test content"], { type: "image/png" }); + + await blindpay.upload.upload({ + file, + bucket: "avatar", + instance_id: "in_111111111111", + }); + + const [url] = fetchMock.mock.calls[0]; + expect(url).toBe("https://api.blindpay.com/v1/upload?instance_id=in_111111111111"); + }); + }); + + describe("Analyze document", () => { + it("should analyze a document", async () => { + const mockedAnalysis: UploadAnalyzeResponse = { + approval_rate: "high", + description: "The document is a legible utility bill matching the provided name.", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedAnalysis), { + headers: { "Content-Type": "application/json" }, + }); + + const file = new Blob(["test content"], { type: "application/pdf" }); + + const { data, error } = await blindpay.upload.analyze({ + file, + type: "proof_of_address", + metadata: JSON.stringify({ full_name: "Jane Doe" }), + instance_id: "in_000000000000", + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedAnalysis); + + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe( + "https://api.blindpay.com/v1/upload/analyze?instance_id=in_000000000000" + ); + expect(init?.method).toBe("POST"); + const body = init?.body as FormData; + expect(body).toBeInstanceOf(FormData); + expect(body.get("type")).toBe("proof_of_address"); + expect(body.get("metadata")).toBe(JSON.stringify({ full_name: "Jane Doe" })); + expect(body.get("file")).toBeInstanceOf(Blob); + expect(new Headers(init?.headers).has("Content-Type")).toBe(false); + }); + + it("should analyze a document without metadata or instance_id", async () => { + const mockedAnalysis: UploadAnalyzeResponse = { + approval_rate: "low", + description: "The document is blurry.", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedAnalysis), { + headers: { "Content-Type": "application/json" }, + }); + + const file = new Blob(["test content"], { type: "image/png" }); + + const { data, error } = await blindpay.upload.analyze({ + file, + type: "selfie", + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedAnalysis); + + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe( + "https://api.blindpay.com/v1/upload/analyze?instance_id=in_000000000000" + ); + const body = init?.body as FormData; + expect(body.has("metadata")).toBe(false); + }); + + it("should return an error when analysis fails", async () => { + fetchMock.mockResponseOnce( + JSON.stringify({ + success: false, + code: "UPLOAD_UNSUPPORTED_FILE", + message: "Unsupported file", + errors: [], + trace_id: "0af7651916cd43dd8448eb211c80319c", + }), + { status: 400, headers: { "Content-Type": "application/json" } } + ); + + const file = new Blob(["test content"], { type: "text/plain" }); + + const { data, error } = await blindpay.upload.analyze({ file, type: "invoice" }); + + expect(data).toBeNull(); + expect(error).toStrictEqual({ + code: "UPLOAD_UNSUPPORTED_FILE", + message: "Unsupported file", + errors: [], + trace_id: "0af7651916cd43dd8448eb211c80319c", + }); + }); + }); + + describe("Presign file URL", () => { + it("should presign a file URL", async () => { + const mockedPresign: PresignResponse = { + file_url: "https://storage.blindpay.com/uploads/abc123.pdf?signature=xyz", + expires_at: "2025-01-01T01:00:00Z", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedPresign), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.upload.presign({ + file_url: "https://storage.blindpay.com/uploads/abc123.pdf", + instance_id: "in_000000000000", + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedPresign); + + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe("https://api.blindpay.com/v1/presign?instance_id=in_000000000000"); + expect(init?.method).toBe("POST"); + expect(JSON.parse(init?.body as string)).toEqual({ + file_url: "https://storage.blindpay.com/uploads/abc123.pdf", + }); + }); + + it("should default instance_id to the client's instance", async () => { + const mockedPresign: PresignResponse = { + file_url: "https://storage.blindpay.com/uploads/abc123.pdf?signature=xyz", + expires_at: "2025-01-01T01:00:00Z", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedPresign), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.upload.presign({ + file_url: "https://storage.blindpay.com/uploads/abc123.pdf", + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedPresign); + + const [url, init] = fetchMock.mock.calls[0]; + expect(url).toBe("https://api.blindpay.com/v1/presign?instance_id=in_000000000000"); + expect(JSON.parse(init?.body as string)).toEqual({ + file_url: "https://storage.blindpay.com/uploads/abc123.pdf", + }); }); }); }); diff --git a/src/resources/virtual-accounts/index.ts b/src/resources/virtual-accounts/index.ts index 9d4b3a0..daf2468 100644 --- a/src/resources/virtual-accounts/index.ts +++ b/src/resources/virtual-accounts/index.ts @@ -1,49 +1,91 @@ -import type { BlindpayApiResponse, KycStatus, Network, StablecoinToken } from "../../../types"; +import type { + BlindpayApiResponse, + KycStatus, + Network, + RequestOptions, + StablecoinToken, + SuccessResponse, +} from "../../../types"; import type { InternalApiClient } from "../../internal/api-client"; -export type BankingPartner = "jpmorgan" | "citi" | "hsbc" | "cfsb" | "portage" | "ssb"; +export type BankingPartner = + | "jpmorgan" + | "citi" + | "hsbc" + | "cfsb" + | "portage" + | "bre_b" + | "portage_g" + | "spei"; export type SoleProprietorDocType = "master_service_agreement" | "salary_slip" | "bank_statement"; +export type VirtualAccountUsAccountType = "Personal checking" | "Business checking"; + export type VirtualAccount = { id: string; - banking_partner: BankingPartner; - kyc_status: KycStatus; - us: { - ach: { + banking_partner: BankingPartner | null; + kyc_status: KycStatus | null; + us?: { + ach?: { routing_number: string; account_number: string; - }; + } | null; wire: { routing_number: string; account_number: string; }; - rtp: { + rtp?: { routing_number: string; account_number: string; - }; - swift_bic_code: string; + } | null; + swift_bic_code?: string | null; swift_account_number?: string | null; - account_type: string; - beneficiary: { + account_type?: VirtualAccountUsAccountType | null; + beneficiary?: { name: string; address_line_1: string; address_line_2: string; - }; - receiving_bank: { + } | null; + receiving_bank?: { name: string; address_line_1: string; - address_line_2: string; - }; + address_line_2?: string | null; + } | null; swift_receiving_bank?: { - name: string | null; - address_line_1: string | null; - address_line_2: string | null; + name?: string | null; + address_line_1?: string | null; + address_line_2?: string | null; } | null; - }; + swift_intermediary_bank?: { + name?: string | null; + swift_code_bic?: string | null; + routing_number?: string | null; + address_line_1?: string | null; + address_line_2?: string | null; + } | null; + } | null; token: StablecoinToken; - blockchain_wallet_id: string; - blockchain_wallet: { network: Network; address: string } | null; + blockchain_wallet_id: string | null; + blockchain_wallet: { network: Network; address?: string | null } | null; + co?: { + bre_b: { + key: string; + }; + beneficiary?: { + name: string; + } | null; + } | null; + mx?: { + spei: { + clabe: string; + }; + beneficiary?: { + name: string; + } | null; + } | null; + partner_fee_id?: string | null; + customer_id?: string | null; }; export type ListVirtualAccountsInput = string; @@ -57,6 +99,10 @@ export type CreateVirtualAccountInput = { blockchain_wallet_id: string; sole_proprietor_doc_type?: SoleProprietorDocType | null; sole_proprietor_doc_file?: string | null; + bre_b?: { + gender: "male" | "female"; + } | null; + partner_fee_id?: string | null; }; export type CreateVirtualAccountResponse = VirtualAccount; @@ -73,6 +119,7 @@ export type UpdateVirtualAccountInput = { id: string; token: StablecoinToken; blockchain_wallet_id: string; + partner_fee_id?: string | null; }; export function createVirtualAccountsResource(instanceId: string, client: InternalApiClient) { @@ -90,23 +137,24 @@ export function createVirtualAccountsResource(instanceId: string, client: Intern `/instances/${instanceId}/customers/${customer_id}/virtual-accounts/${id}` ); }, - create({ - customer_id, - ...data - }: CreateVirtualAccountInput): Promise> { + create( + { customer_id, ...data }: CreateVirtualAccountInput, + options?: RequestOptions + ): Promise> { return client.post( `/instances/${instanceId}/customers/${customer_id}/virtual-accounts`, - data + data, + options ); }, - update({ - customer_id, - id, - ...data - }: UpdateVirtualAccountInput): Promise> { + update( + { customer_id, id, ...data }: UpdateVirtualAccountInput, + options?: RequestOptions + ): Promise> { return client.put( `/instances/${instanceId}/customers/${customer_id}/virtual-accounts/${id}`, - data + data, + options ); }, }; diff --git a/src/resources/virtual-accounts/virtual-accounts.test.ts b/src/resources/virtual-accounts/virtual-accounts.test.ts index f49d0ce..6ba3616 100644 --- a/src/resources/virtual-accounts/virtual-accounts.test.ts +++ b/src/resources/virtual-accounts/virtual-accounts.test.ts @@ -1,4 +1,5 @@ import { afterEach, describe, expect, it } from "vitest"; +import type { SuccessResponse } from "../../../types"; import { BlindPay } from "../../client"; import type { CreateVirtualAccountResponse, @@ -274,7 +275,9 @@ describe("Virtual accounts", () => { describe("Update virtual account", () => { it("should update a virtual account", async () => { - fetchMock.mockResponseOnce(JSON.stringify(null), { + const mockedResponse: SuccessResponse = { success: true }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { headers: { "Content-Type": "application/json" }, }); @@ -286,7 +289,37 @@ describe("Virtual accounts", () => { }); expect(error).toBeNull(); - expect(data).toEqual(null); + expect(data).toEqual(mockedResponse); + }); + }); + + describe("Get Bre-B virtual account", () => { + it("should type a virtual account without US bank details", async () => { + const mockedVirtualAccount: GetVirtualAccountResponse = { + id: "va_000000000000", + banking_partner: "bre_b", + kyc_status: "approved", + us: null, + co: { + bre_b: { key: "@blindpay123" }, + beneficiary: { name: "Jane Doe" }, + }, + token: "USDC", + blockchain_wallet_id: "bw_000000000000", + blockchain_wallet: { network: "polygon", address: null }, + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedVirtualAccount), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.virtualAccounts.get({ + customer_id: "cu_000000000000", + id: "va_000000000000", + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedVirtualAccount); }); }); }); diff --git a/src/resources/wallets/blockchain.test.ts b/src/resources/wallets/blockchain.test.ts index 458fe64..5d82c42 100644 --- a/src/resources/wallets/blockchain.test.ts +++ b/src/resources/wallets/blockchain.test.ts @@ -1,4 +1,5 @@ import { afterEach, describe, expect, it } from "vitest"; +import type { SuccessResponse } from "../../../types"; import { BlindPay } from "../../client"; import type { CreateAssetTrustlineResponse, @@ -184,7 +185,9 @@ describe("Blockchain wallets", () => { describe("Delete blockchain wallet", () => { it("should delete a blockchain wallet", async () => { - fetchMock.mockResponseOnce(JSON.stringify({ data: null }), { + const mockedResponse: SuccessResponse = { success: true }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { headers: { "Content-Type": "application/json" }, }); @@ -194,7 +197,7 @@ describe("Blockchain wallets", () => { }); expect(error).toBeNull(); - expect(data).toEqual({ data: null }); + expect(data).toEqual(mockedResponse); }); }); @@ -219,7 +222,9 @@ describe("Blockchain wallets", () => { describe("Mint USDB Stellar", () => { it("should mint usdb on stellar", async () => { - fetchMock.mockResponseOnce(JSON.stringify({}), { + const mockedResponse: SuccessResponse = { success: true }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { headers: { "Content-Type": "application/json" }, }); @@ -231,7 +236,27 @@ describe("Blockchain wallets", () => { }); expect(error).toBeNull(); - expect(data).toBeDefined(); + expect(data).toEqual(mockedResponse); + }); + + it("should mint usdb on stellar without a signed xdr", async () => { + const mockedResponse: SuccessResponse = { success: true }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.wallets.blockchain.mintUsdbStellar({ + address: "GCDNJUBQSX7AJWLJACMJ7I4BC3Z47BQUTMHEICZLE6MU4KQBRYG5JY6B", + amount: "1000000", + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedResponse); + expect(JSON.parse(fetchMock.mock.calls[0][1]?.body as string)).toEqual({ + address: "GCDNJUBQSX7AJWLJACMJ7I4BC3Z47BQUTMHEICZLE6MU4KQBRYG5JY6B", + amount: "1000000", + }); }); }); @@ -241,7 +266,6 @@ describe("Blockchain wallets", () => { success: true, signature: "4wceVEQeJG4vpS4k2o1dHU5cFWeWTQU8iaCEpRaV5KkqSxPfbdAc8hzXa7nNYG6rvqgAmDkzBycbcXkKKAeK8Jtu", - error: "", }; fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { @@ -280,5 +304,30 @@ describe("Blockchain wallets", () => { expect(error).toBeNull(); expect(data).toEqual(mockedResponse); }); + + it("should prepare a solana delegation transaction from a quote", async () => { + const mockedResponse: PrepareSolanaDelegationTransactionResponse = { + success: true, + transaction: + "AAGBf4K95Gp5i6f0BAEYAgABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIw==", + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = + await blindpay.wallets.blockchain.prepareSolanaDelegationTransaction({ + owner_address: "7YttLkHDoNj9wyDur5pM1ejNaAvT9X4eqaYcHQqtj2G5", + quote_id: "qu_000000000000", + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedResponse); + expect(JSON.parse(fetchMock.mock.calls[0][1]?.body as string)).toEqual({ + owner_address: "7YttLkHDoNj9wyDur5pM1ejNaAvT9X4eqaYcHQqtj2G5", + quote_id: "qu_000000000000", + }); + }); }); }); diff --git a/src/resources/wallets/blockchain.ts b/src/resources/wallets/blockchain.ts index 874b896..869e990 100644 --- a/src/resources/wallets/blockchain.ts +++ b/src/resources/wallets/blockchain.ts @@ -1,4 +1,4 @@ -import type { BlindpayApiResponse, Network } from "../../../types"; +import type { BlindpayApiResponse, Network, RequestOptions, SuccessResponse } from "../../../types"; import type { InternalApiClient } from "../../internal/api-client"; export type GetBlockchainWalletMessage = string; @@ -11,11 +11,11 @@ export type ListBlockchainWalletsInput = string; export type ListBlockchainWalletsResponse = Array<{ id: string; - name: string; - network: Network; - address?: string; - signature_tx_hash?: string; - is_account_abstraction: boolean; + name: string | null; + network: Network | null; + address?: string | null; + signature_tx_hash?: string | null; + is_account_abstraction: boolean | null; is_self_custody: boolean | null; customer_id: string; }>; @@ -24,7 +24,7 @@ export type CreateBlockchainWalletWithAddressInput = { customer_id: string; name: string; network: Network; - address: string; + address: string | null; is_self_custody?: boolean; }; @@ -32,7 +32,7 @@ export type CreateBlockchainWalletWithHashInput = { customer_id: string; name: string; network: Network; - signature_tx_hash: string; + signature_tx_hash: string | null; is_self_custody?: boolean; }; @@ -48,22 +48,22 @@ export type DeleteBlockchainWalletInput = { export type GetBlockchainWalletResponse = { id: string; - name: string; - network: Network; - address?: string; - signature_tx_hash?: string; - is_account_abstraction: boolean; + name: string | null; + network: Network | null; + address?: string | null; + signature_tx_hash?: string | null; + is_account_abstraction: boolean | null; is_self_custody: boolean | null; customer_id: string; }; export type CreateBlockchainWalletResponse = { id: string; - name: string; - network: Network; - address?: string; - signature_tx_hash?: string; - is_account_abstraction: boolean; + name: string | null; + network: Network | null; + address?: string | null; + signature_tx_hash?: string | null; + is_account_abstraction: boolean | null; is_self_custody: boolean | null; customer_id: string; }; @@ -85,13 +85,14 @@ export type CreateAssetTrustlineResponse = { export type MintUsdbStellarInput = { address: string; amount: string; - signedXdr: string; + signedXdr?: string; }; export type PrepareSolanaDelegationTransactionInput = { - token_address: string; - amount: string; owner_address: string; + quote_id?: string; + token_address?: string; + amount?: string; }; export type PrepareSolanaDelegationTransactionResponse = { @@ -106,8 +107,8 @@ export type MintUsdbSolanaInput = { export type MintUsdbSolanaResponse = { success: boolean; - signature: string; - error: string; + signature?: string; + error?: string; }; export function createBlockchainWalletsResource(instanceId: string, client: InternalApiClient) { @@ -119,32 +120,30 @@ export function createBlockchainWalletsResource(instanceId: string, client: Inte `/instances/${instanceId}/customers/${customer_id}/blockchain-wallets` ); }, - createWithAddress({ - customer_id, - ...data - }: CreateBlockchainWalletWithAddressInput): Promise< - BlindpayApiResponse - > { + createWithAddress( + { customer_id, ...data }: CreateBlockchainWalletWithAddressInput, + options?: RequestOptions + ): Promise> { return client.post( `/instances/${instanceId}/customers/${customer_id}/blockchain-wallets`, { ...data, is_account_abstraction: true, - } + }, + options ); }, - createWithHash({ - customer_id, - ...data - }: CreateBlockchainWalletWithHashInput): Promise< - BlindpayApiResponse - > { + createWithHash( + { customer_id, ...data }: CreateBlockchainWalletWithHashInput, + options?: RequestOptions + ): Promise> { return client.post( `/instances/${instanceId}/customers/${customer_id}/blockchain-wallets`, { ...data, is_account_abstraction: false, - } + }, + options ); }, getWalletMessage( @@ -162,45 +161,54 @@ export function createBlockchainWalletsResource(instanceId: string, client: Inte `/instances/${instanceId}/customers/${customer_id}/blockchain-wallets/${id}` ); }, - delete({ - customer_id, - id, - }: DeleteBlockchainWalletInput): Promise> { + delete( + { customer_id, id }: DeleteBlockchainWalletInput, + options?: RequestOptions + ): Promise> { return client.delete( - `/instances/${instanceId}/customers/${customer_id}/blockchain-wallets/${id}` + `/instances/${instanceId}/customers/${customer_id}/blockchain-wallets/${id}`, + options ); }, - setSelfCustody({ - customer_id, - id, - ...data - }: SetBlockchainWalletSelfCustodyInput): Promise< - BlindpayApiResponse - > { + setSelfCustody( + { customer_id, id, ...data }: SetBlockchainWalletSelfCustodyInput, + options?: RequestOptions + ): Promise> { return client.patch( `/instances/${instanceId}/customers/${customer_id}/blockchain-wallets/${id}`, - data + data, + options ); }, createAssetTrustline( - address: CreateAssetTrustlineInput + address: CreateAssetTrustlineInput, + options?: RequestOptions ): Promise> { - return client.post(`/instances/${instanceId}/create-asset-trustline`, { - address, - }); + return client.post( + `/instances/${instanceId}/create-asset-trustline`, + { + address, + }, + options + ); }, - mintUsdbStellar({ ...data }: MintUsdbStellarInput): Promise> { - return client.post(`/instances/${instanceId}/mint-usdb-stellar`, data); + mintUsdbStellar( + { ...data }: MintUsdbStellarInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/mint-usdb-stellar`, data, options); }, - mintUsdbSolana({ ...data }: MintUsdbSolanaInput): Promise> { - return client.post(`/instances/${instanceId}/mint-usdb-solana`, data); + mintUsdbSolana( + { ...data }: MintUsdbSolanaInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/mint-usdb-solana`, data, options); }, - prepareSolanaDelegationTransaction({ - ...data - }: PrepareSolanaDelegationTransactionInput): Promise< - BlindpayApiResponse - > { - return client.post(`/instances/${instanceId}/prepare-delegate-solana`, data); + prepareSolanaDelegationTransaction( + { ...data }: PrepareSolanaDelegationTransactionInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/prepare-delegate-solana`, data, options); }, }; } diff --git a/src/resources/wallets/custodial.test.ts b/src/resources/wallets/custodial.test.ts index 98838a9..9d27590 100644 --- a/src/resources/wallets/custodial.test.ts +++ b/src/resources/wallets/custodial.test.ts @@ -4,6 +4,7 @@ import type { CreateCustodialWalletResponse, CustodialWallet, GetCustodialWalletBalanceResponse, + GetCustodialWalletDepositsResponse, GetCustodialWalletResponse, ListCustodialWalletsResponse, } from "./custodial"; @@ -14,9 +15,13 @@ const mockWallet: CustodialWallet = { external_id: null, address: "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C", network: "polygon", + yield_status: "disabled", created_at: "2025-01-01T00:00:00Z", }; +const walletPath = + "https://api.blindpay.com/v1/instances/in_000000000000/customers/re_000000000000/wallets/wa_000000000000"; + describe("Custodial Wallets", () => { afterEach(() => fetchMock.resetMocks()); @@ -82,18 +87,24 @@ describe("Custodial Wallets", () => { id: "tok_000000000001", symbol: "USDC", amount: 10000, + earning_amount: 0, + total_amount: 10000, }, USDT: { address: "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C", id: "tok_000000000002", symbol: "USDT", amount: 5000, + earning_amount: 0, + total_amount: 5000, }, USDB: { address: "0xDD6a3aD0949396e57C7738ba8FC1A46A5a1C372C", id: "tok_000000000003", symbol: "USDB", amount: 0, + earning_amount: 0, + total_amount: 0, }, }; @@ -126,4 +137,64 @@ describe("Custodial Wallets", () => { expect(data).toEqual({ success: true }); }); }); + + describe("Get custodial wallet deposits", () => { + it("should list wallet deposits with filters", async () => { + const mockedDeposits: GetCustodialWalletDepositsResponse = { + data: [ + { + id: "wd_000000000000", + wallet_id: "wa_000000000000", + network: "tempo", + token: "EURC", + amount: 150000, + token_amount: "1500.000123", + status: "on_hold", + transaction_hash: "0x8f3e1b", + sender_address: null, + created_at: "2026-10-15T10:02:00Z", + }, + ], + pagination: { + has_more: false, + next_page: "", + prev_page: "", + }, + }; + + fetchMock.mockResponseOnce(JSON.stringify(mockedDeposits), { + headers: { "Content-Type": "application/json" }, + }); + + const { data, error } = await blindpay.wallets.custodial.getDeposits({ + customer_id: "re_000000000000", + id: "wa_000000000000", + limit: "10", + token: "EURC", + status: "on_hold", + }); + + expect(error).toBeNull(); + expect(data).toEqual(mockedDeposits); + expect(fetchMock.mock.calls[0][0]).toBe( + `${walletPath}/deposits?limit=10&token=EURC&status=on_hold` + ); + expect(fetchMock.mock.calls[0][1]?.method).toBe("GET"); + }); + + it("should list wallet deposits without filters", async () => { + fetchMock.mockResponseOnce( + JSON.stringify({ data: [], pagination: { has_more: false } }), + { headers: { "Content-Type": "application/json" } } + ); + + const { error } = await blindpay.wallets.custodial.getDeposits({ + customer_id: "re_000000000000", + id: "wa_000000000000", + }); + + expect(error).toBeNull(); + expect(fetchMock.mock.calls[0][0]).toBe(`${walletPath}/deposits`); + }); + }); }); diff --git a/src/resources/wallets/custodial.ts b/src/resources/wallets/custodial.ts index 6ad3dd9..9faeea4 100644 --- a/src/resources/wallets/custodial.ts +++ b/src/resources/wallets/custodial.ts @@ -1,13 +1,23 @@ -import type { BlindpayApiResponse, Network, StablecoinToken } from "../../../types"; +import type { + BlindpayApiResponse, + Network, + PaginationMetadata, + RequestOptions, + SuccessResponse, + WalletToken, +} from "../../../types"; import type { InternalApiClient } from "../../internal/api-client"; +export type YieldStatus = "disabled" | "enabled" | "disabling"; + export type CustodialWallet = { id: string; name: string; external_id: string | null; address: string | null; network: Network; - created_at: string; + yield_status?: YieldStatus; + created_at: string | null; }; export type CreateCustodialWalletInput = { @@ -33,8 +43,10 @@ export type GetCustodialWalletResponse = CustodialWallet; export type WalletTokenBalance = { address: string; id: string; - symbol: StablecoinToken; + symbol: WalletToken; amount: number; + earning_amount: number; + total_amount: number; }; export type GetCustodialWalletBalanceInput = { @@ -46,6 +58,8 @@ export type GetCustodialWalletBalanceResponse = { USDC: WalletTokenBalance; USDT: WalletTokenBalance; USDB: WalletTokenBalance; + EURB?: WalletTokenBalance; + EURC?: WalletTokenBalance; }; export type DeleteCustodialWalletInput = { @@ -53,6 +67,45 @@ export type DeleteCustodialWalletInput = { id: string; }; +export type WalletDepositStatus = "processing" | "completed" | "on_hold" | "refunded"; + +export type WalletDeposit = { + id: string; + wallet_id: string; + network: Network; + token: WalletToken; + amount: number; + token_amount: string | null; + status: WalletDepositStatus; + transaction_hash: string; + sender_address: string | null; + created_at: string; +}; + +export type GetCustodialWalletDepositsInput = { + customer_id: string; + id: string; + limit?: "5" | "10" | "50" | "100" | "200"; + starting_after?: string; + ending_before?: string; + token?: WalletToken; + status?: WalletDepositStatus; +}; + +export type GetCustodialWalletDepositsResponse = { + data: WalletDeposit[]; + pagination: PaginationMetadata; +}; + +function toQueryString(params: Record): string { + const query = new URLSearchParams(); + for (const [key, value] of Object.entries(params)) { + if (value !== undefined) query.append(key, value); + } + const serialized = query.toString(); + return serialized ? `?${serialized}` : ""; +} + export function createCustodialWalletsResource(instanceId: string, client: InternalApiClient) { return { list( @@ -66,13 +119,15 @@ export function createCustodialWalletsResource(instanceId: string, client: Inter }: GetCustodialWalletInput): Promise> { return client.get(`/instances/${instanceId}/customers/${customer_id}/wallets/${id}`); }, - create({ - customer_id, - ...data - }: CreateCustodialWalletInput): Promise< - BlindpayApiResponse - > { - return client.post(`/instances/${instanceId}/customers/${customer_id}/wallets`, data); + create( + { customer_id, ...data }: CreateCustodialWalletInput, + options?: RequestOptions + ): Promise> { + return client.post( + `/instances/${instanceId}/customers/${customer_id}/wallets`, + data, + options + ); }, getBalance({ customer_id, @@ -84,11 +139,25 @@ export function createCustodialWalletsResource(instanceId: string, client: Inter `/instances/${instanceId}/customers/${customer_id}/wallets/${id}/balance` ); }, - delete({ + delete( + { customer_id, id }: DeleteCustodialWalletInput, + options?: RequestOptions + ): Promise> { + return client.delete( + `/instances/${instanceId}/customers/${customer_id}/wallets/${id}`, + options + ); + }, + getDeposits({ customer_id, id, - }: DeleteCustodialWalletInput): Promise> { - return client.delete(`/instances/${instanceId}/customers/${customer_id}/wallets/${id}`); + ...params + }: GetCustodialWalletDepositsInput): Promise< + BlindpayApiResponse + > { + return client.get( + `/instances/${instanceId}/customers/${customer_id}/wallets/${id}/deposits${toQueryString(params)}` + ); }, }; } diff --git a/src/resources/wallets/offramp.ts b/src/resources/wallets/offramp.ts index 35ca46f..d15d640 100644 --- a/src/resources/wallets/offramp.ts +++ b/src/resources/wallets/offramp.ts @@ -1,4 +1,4 @@ -import type { BlindpayApiResponse } from "../../../types"; +import type { BlindpayApiResponse, RequestOptions } from "../../../types"; import type { InternalApiClient } from "../../internal/api-client"; export type OfframpWalletNetwork = @@ -12,18 +12,22 @@ export type OfframpWalletNetwork = | "polygon" | "polygon_amoy" | "sepolia" + | "arc" + | "arc_testnet" + | "tempo" + | "tempo_testnet" | "solana_devnet"; export type OfframpWallet = { id: string; - external_id: string; + external_id: string | null; instance_id: string; customer_id: string; bank_account_id: string; network: OfframpWalletNetwork; address: string; - created_at: string; - updated_at: string; + created_at: string | null; + updated_at: string | null; circle_wallet_id?: string | null; }; @@ -67,14 +71,14 @@ export function createOfframpWalletsResource(instanceId: string, client: Interna `/instances/${instanceId}/customers/${customer_id}/bank-accounts/${bank_account_id}/offramp-wallets` ); }, - create({ - customer_id, - bank_account_id, - ...data - }: CreateOfframpWalletInput): Promise> { + create( + { customer_id, bank_account_id, ...data }: CreateOfframpWalletInput, + options?: RequestOptions + ): Promise> { return client.post( `/instances/${instanceId}/customers/${customer_id}/bank-accounts/${bank_account_id}/offramp-wallets`, - data + data, + options ); }, get({ diff --git a/src/resources/webhooks/events.test.ts b/src/resources/webhooks/events.test.ts new file mode 100644 index 0000000..7f2d8df --- /dev/null +++ b/src/resources/webhooks/events.test.ts @@ -0,0 +1,102 @@ +import { Webhook } from "svix"; +import { describe, expect, expectTypeOf, it } from "vitest"; +import { BlindPay } from "../../client"; +import { BlindPayError } from "../../internal/blindpay-error"; +import type { WebhookEvents } from "."; +import type { WebhookEvent } from "./events"; + +describe("Webhook events", () => { + const secret = "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"; + const id = "msg_000000000000"; + const timestamp = new Date(); + + const blindpay = new BlindPay({ apiKey: "test-key", instanceId: "in_000000000000" }); + const sign = (body: string) => new Webhook(secret).sign(id, timestamp, body); + const headers = (signature: string) => ({ + id, + timestamp: Math.floor(timestamp.getTime() / 1000).toString(), + signature, + }); + + it("has exactly one union member per webhook event name", () => { + expectTypeOf().toEqualTypeOf(); + }); + + it("returns the verified payload as a typed event", () => { + const tosAccept = { + webhook_event: "tos.accept", + tos_id: "to_000000000000", + idempotency_key: "7c4f5f8e-5b0e-4a3b-9d5f-2f1c0e6a8b9d", + customer_id: null, + version: "1.0.1", + } satisfies WebhookEvent; + const payload = JSON.stringify(tosAccept); + + const event = blindpay.constructWebhookEvent({ + secret, + headers: headers(sign(payload)), + payload, + }); + + expect(event).toEqual(tosAccept); + if (event.webhook_event !== "tos.accept") { + throw new Error(`unexpected event ${event.webhook_event}`); + } + expectTypeOf(event.tos_id).toEqualTypeOf(); + expect(event.tos_id).toBe("to_000000000000"); + }); + + it("narrows each event to its own payload shape", () => { + const handle = (event: WebhookEvent): string => { + switch (event.webhook_event) { + case "customer.update": + return event.kyc_status; + case "customer.delete": + return event.deleted_at; + case "wallet.inbound": + return event.token.symbol; + case "payout.complete": + return event.sender_wallet_address; + case "payin.complete": + return event.blindpay_bank_details.beneficiary.name; + case "transfer.complete": + return event.tracking_complete.step; + default: + return event.webhook_event; + } + }; + + const deleted = { + webhook_event: "customer.delete", + id: "cu_000000000000", + customer_id: "cu_000000000000", + instance_id: "in_000000000000", + type: "individual", + kyc_type: "standard", + kyc_status: "approved", + deleted_at: "2025-01-01T00:00:00Z", + } satisfies WebhookEvent; + const payload = JSON.stringify(deleted); + + const event = blindpay.constructWebhookEvent({ + secret, + headers: headers(sign(payload)), + payload, + }); + + expect(handle(event)).toBe("2025-01-01T00:00:00Z"); + }); + + it("throws a BlindPayError when the payload was tampered with", () => { + const payload = JSON.stringify({ webhook_event: "tos.accept", tos_id: "to_000000000000" }); + const tampered = JSON.stringify({ webhook_event: "tos.accept", tos_id: "to_111111111111" }); + + expect(() => + blindpay.constructWebhookEvent({ + secret, + headers: headers(sign(payload)), + payload: tampered, + }) + ).toThrow(BlindPayError); + }); +}); diff --git a/src/resources/webhooks/events.ts b/src/resources/webhooks/events.ts new file mode 100644 index 0000000..0f3acaf --- /dev/null +++ b/src/resources/webhooks/events.ts @@ -0,0 +1,167 @@ +import type { + AccountClass, + KycStatus, + Network, + PayinPaymentMethod, + PayinTrackingComplete, + PayinTrackingPayment, + PayinTrackingTransaction, + PayoutTrackingComplete, + PayoutTrackingLiquidity, + PayoutTrackingPayment, + PayoutTrackingTransaction, + TrackingStatus, + TransactionStatus, + WalletToken, +} from "../../../types"; +import type { BankAccount } from "../bank-accounts"; +import type { GetCustomerResponse, GetLimitIncreaseRequestsResponse, KycType } from "../customers"; +import type { Payable } from "../payables"; +import type { BlindpayBankDetails } from "../payins"; +import type { TransferTrackingStep, TransferTrackingTransactionMonitoring } from "../transfers"; +import type { VirtualAccount } from "../virtual-accounts"; +import type { GetBlockchainWalletResponse } from "../wallets/blockchain"; +import type { CustodialWallet } from "../wallets/custodial"; + +// Payloads that are the resource itself plus `webhook_event` (same property set as the entity +// schema in the OpenAPI spec) reuse the SDK entity type. + +export type BankAccountWebhookEvent = { + webhook_event: "bankAccount.new"; +} & BankAccount; + +export type BlockchainWalletWebhookEvent = { + webhook_event: "blockchainWallet.new" | "blockchainWallet.update"; +} & GetBlockchainWalletResponse; + +export type CustomerWebhookEvent = { + webhook_event: "customer.new" | "customer.update"; +} & GetCustomerResponse; + +export type LimitIncreaseWebhookEvent = { + webhook_event: "limitIncrease.new" | "limitIncrease.update"; +} & GetLimitIncreaseRequestsResponse[number]; + +export type PayableWebhookEvent = { + webhook_event: "payable.new" | "payable.update" | "payable.complete"; +} & Payable; + +export type VirtualAccountWebhookEvent = { + webhook_event: "virtualAccount.new" | "virtualAccount.complete"; +} & VirtualAccount; + +export type WalletWebhookEvent = { + webhook_event: "wallet.new" | "wallet.update"; +} & CustodialWallet; + +// Payloads with their own shape (a subset of the entity, or no entity at all). + +export type PayinWebhookEvent = { + webhook_event: "payin.new" | "payin.update" | "payin.complete" | "payin.partnerFee"; + id: string; + status: TransactionStatus; + pix_code?: string | null; + memo_code?: string | null; + clabe?: string | null; + partner_fee?: number; + tracking_complete: PayinTrackingComplete; + tracking_payment: PayinTrackingPayment; + tracking_transaction: PayinTrackingTransaction; + billing_fee_amount?: number | null; + transaction_fee_amount?: number | null; + blindpay_bank_details: BlindpayBankDetails; + customer_id?: string | null; + receiver_amount?: number | null; + payment_method?: PayinPaymentMethod | null; + sender_amount?: number | null; +}; + +export type PayoutWebhookEvent = { + webhook_event: "payout.new" | "payout.update" | "payout.complete" | "payout.partnerFee"; + id: string; + status: TransactionStatus; + sender_wallet_address: string; + billing_fee_amount?: number | null; + transaction_fee_amount?: number | null; + partner_fee?: number; + tracking_complete: PayoutTrackingComplete; + tracking_payment: PayoutTrackingPayment; + tracking_transaction: PayoutTrackingTransaction; + tracking_liquidity?: PayoutTrackingLiquidity | null; + tracking_documents?: { + step: TrackingStatus; + status?: "waiting_documents" | "compliance_reviewing" | null; + reviewed_by?: string | null; + completed_at?: string | null; + } | null; + customer_id?: string | null; + bank_account_id?: string | null; + offramp_wallet_id?: string | null; + payable_id?: string | null; +}; + +export type TransferWebhookEvent = { + webhook_event: "transfer.new" | "transfer.update" | "transfer.complete"; + id: string; + status: Exclude; + tracking_bridge_swap: TransferTrackingStep; + tracking_complete: TransferTrackingStep; + tracking_paymaster: TransferTrackingStep; + tracking_transaction_monitoring: TransferTrackingTransactionMonitoring; + tracking_partner_fee?: TransferTrackingStep | null; +}; + +export type TosAcceptWebhookEvent = { + webhook_event: "tos.accept"; + tos_id: string; + idempotency_key: string; + customer_id?: string | null; + version?: "1.0.0" | "1.0.1" | null; +}; + +export type CustomerDeleteWebhookEvent = { + webhook_event: "customer.delete"; + id: string; + customer_id: string; + instance_id: string; + type: AccountClass; + kyc_type: KycType; + kyc_status: KycStatus; + deleted_at: string; +}; + +export type WalletInboundToken = { + address: string; + id: string; + symbol: WalletToken; + amount: number; +}; + +export type WalletInboundWebhookEvent = { + webhook_event: "wallet.inbound"; + id: string; + address: string; + network: Network; + token: WalletInboundToken; + deposit_id: string; + transaction_hash: string; +}; + +/** + * A verified webhook payload, discriminated by `webhook_event`. Narrow it with a `switch` on + * `event.webhook_event` to get the payload type of that event. + */ +export type WebhookEvent = + | BankAccountWebhookEvent + | BlockchainWalletWebhookEvent + | CustomerWebhookEvent + | CustomerDeleteWebhookEvent + | LimitIncreaseWebhookEvent + | PayableWebhookEvent + | PayinWebhookEvent + | PayoutWebhookEvent + | TosAcceptWebhookEvent + | TransferWebhookEvent + | VirtualAccountWebhookEvent + | WalletWebhookEvent + | WalletInboundWebhookEvent; diff --git a/src/resources/webhooks/index.ts b/src/resources/webhooks/index.ts index 1edc51c..a7777d4 100644 --- a/src/resources/webhooks/index.ts +++ b/src/resources/webhooks/index.ts @@ -1,4 +1,4 @@ -import type { BlindpayApiResponse } from "../../../types"; +import type { BlindpayApiResponse, RequestOptions, SuccessResponse } from "../../../types"; import type { InternalApiClient } from "../../internal/api-client"; export type WebhookEvents = @@ -25,6 +25,10 @@ export type WebhookEvents = | "wallet.inbound" | "customer.new" | "customer.update" + | "payable.complete" + | "payable.new" + | "payable.update" + | "wallet.update" | "customer.delete"; export type CreateWebhookEndpointInput = { @@ -42,10 +46,10 @@ export type ListWebhookEndpointsResponse = Array<{ id: string; url: string; events: WebhookEvents[]; - last_event_at: string; + last_event_at?: string | null; instance_id: string; - created_at: string; - updated_at: string; + created_at: string | null; + updated_at: string | null; }>; export type GetWebhookEndpointSecretInput = string; @@ -63,15 +67,17 @@ export function createWebhookEndpointsResource(instanceId: string, client: Inter list(): Promise> { return client.get(`/instances/${instanceId}/webhook-endpoints`); }, - create({ - ...data - }: CreateWebhookEndpointInput): Promise< - BlindpayApiResponse - > { - return client.post(`/instances/${instanceId}/webhook-endpoints`, data); + create( + { ...data }: CreateWebhookEndpointInput, + options?: RequestOptions + ): Promise> { + return client.post(`/instances/${instanceId}/webhook-endpoints`, data, options); }, - delete(id: DeleteWebhookEndpointInput): Promise> { - return client.delete(`/instances/${instanceId}/webhook-endpoints/${id}`); + delete( + id: DeleteWebhookEndpointInput, + options?: RequestOptions + ): Promise> { + return client.delete(`/instances/${instanceId}/webhook-endpoints/${id}`, options); }, getSecret( id: GetWebhookEndpointSecretInput diff --git a/src/resources/webhooks/webhooks.test.ts b/src/resources/webhooks/webhooks.test.ts index 49cd408..3c8d160 100644 --- a/src/resources/webhooks/webhooks.test.ts +++ b/src/resources/webhooks/webhooks.test.ts @@ -1,4 +1,5 @@ import { afterEach, describe, expect, it } from "vitest"; +import type { SuccessResponse } from "../../../types"; import { BlindPay } from "../../client"; import type { CreateWebhookEndpointResponse, ListWebhookEndpointsResponse } from "./index"; @@ -38,6 +39,15 @@ describe("Webhooks", () => { created_at: "2021-01-01T00:00:00Z", updated_at: "2021-01-01T00:00:00Z", }, + { + id: "we_000000000001", + url: "https://example.com/webhook", + events: ["tos.accept"], + last_event_at: null, + instance_id: "in_000000000000", + created_at: null, + updated_at: null, + }, ]; fetchMock.mockResponseOnce(JSON.stringify(mockedWebhookEndpoints), { headers: { "Content-Type": "application/json" }, @@ -52,7 +62,7 @@ describe("Webhooks", () => { describe("Delete webhook endpoint", () => { it("should delete a webhook endpoint", async () => { - const mockedResponse = { data: null }; + const mockedResponse: SuccessResponse = { success: true }; fetchMock.mockResponseOnce(JSON.stringify(mockedResponse), { headers: { "Content-Type": "application/json" }, }); diff --git a/types/index.d.ts b/types/index.d.ts index 0b72b6e..4852838 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,7 +1,15 @@ export type BlindpayApiResponse = BlindpayErrorResponse | BlindpaySuccessResponse export type ErrorResponse = { + /** Legacy machine-readable message; prefer `code` for programmatic handling. */ message: string; + /** Stable error code, e.g. `PAYOUTS_INSUFFICIENT_BALANCE`. */ + code?: string; + /** Human-readable explanation, safe to show to end users. */ + description?: string; + errors?: string[]; + /** Request trace ID; include it when contacting BlindPay support. */ + trace_id?: string; } export type BlindpayErrorResponse = { @@ -14,19 +22,36 @@ export type BlindpaySuccessResponse = { error: null; } +/** Per-call options for methods that change something (POST, PUT, PATCH, DELETE). */ +export type RequestOptions = { + /** + * Sent as the `Idempotency-Key` header (up to 255 characters, a UUID is a good default). + * Retrying with the same key and the exact same body replays the original response + * instead of acting twice; keys are kept for 24 hours. Ignored on file uploads. + */ + idempotencyKey?: string; +} + +/** Body of every endpoint whose only answer is `{ success: true }` (deletes, most updates). */ +export type SuccessResponse = { + success: boolean; +} + export type CurrencyType = "sender" | "receiver"; -export type Network = "base" | "sepolia" | "arbitrum_sepolia" | "base_sepolia" | "arbitrum" | "polygon" | "polygon_amoy" | "ethereum" | "stellar" | "stellar_testnet" | "tron" | "solana" | "solana_devnet"; +export type Network = "base" | "sepolia" | "arbitrum_sepolia" | "base_sepolia" | "arbitrum" | "polygon" | "polygon_amoy" | "ethereum" | "stellar" | "stellar_testnet" | "tron" | "solana" | "solana_devnet" | "arc" | "arc_testnet" | "tempo" | "tempo_testnet"; export type StablecoinToken = "USDC" | "USDT" | "USDB"; +export type WalletToken = "USDC" | "USDT" | "USDB" | "EURC" | "EURB"; + export type TransactionDocumentType = "invoice" | "purchase_order" | "delivery_slip" | "contract" | "customs_declaration" | "bill_of_lading" | "others"; export type BankAccountType = "checking" | "saving"; export type Currency = "USDC" | "USDT" | "USDB" | "BRL" | "USD" | "MXN" | "COP" | "ARS" | "EUR" | "GBP"; -export type Rail = "wire" | "ach" | "pix" | "pix_safe" | "spei_bitso" | "transfers_bitso" | "ach_cop_bitso" | "international_swift" | "rtp" | "ted" | "sepa"; +export type Rail = "wire" | "ach" | "pix" | "pix_safe" | "spei_bitso" | "transfers_bitso" | "ach_cop_bitso" | "international_swift" | "rtp" | "ted" | "sepa" | "faster_payments"; export type AccountClass = "individual" | "business"; @@ -292,8 +317,8 @@ export type PaginationParams = { export type PaginationMetadata = { has_more: boolean; - next_page: string; - prev_page: string; + next_page: string | null; + prev_page: string | null; } export type ArgentinaTransfers = "CVU" | "CBU" | "ALIAS"; @@ -327,6 +352,36 @@ export type PayinTrackingTransaction = { type: ArgentinaTransfers; tax_id?: string | null; } | null + card_claim_at?: string | null; + card_evidence?: { + eci?: string | null; + cavv?: string | null; + avs_response?: string | null; + cvv_response?: string | null; + auth_code?: string | null; + cardholder_name?: string | null; + three_ds_version?: string | null; + } | null; + card_failed_attempts?: number | null; + card_gates_failed_at?: string | null; + card_instruction?: { + provider: string; + tokenization_key: string; + } | null; + end_to_end_id?: string | null; + provider_name?: string | null; + provider_transaction_id?: string | null; + sender_bank_name?: string | null; + ted_instruction?: { + beneficiary_name: string; + tax_id: string; + bank_code: string; + bank_name: string; + branch_code: string; + account_number: string; + account_type: string; + } | null; + transaction_hash?: string | null; }; export type PayinTrackingPayment = { @@ -335,6 +390,9 @@ export type PayinTrackingPayment = { completed_at?: string | null review_contexts?: Record | null; review_sources?: unknown[] | null; + approved_risk_sources?: string[] | null; + review_context?: Record | null; + review_source?: string | null; }; export type PayinTrackingComplete = { @@ -349,7 +407,7 @@ export type PayinTrackingPartnerFee = { completed_at?: string | null } -export type PayinPaymentMethod = "ach" | "wire" | "pix" | "spei" | "transfers" | "pse" | "international_swift" | "rtp" | "ted" +export type PayinPaymentMethod = "ach" | "wire" | "pix" | "spei" | "transfers" | "pse" | "international_swift" | "rtp" | "ted" | "ach_pull" | "card" | "bre_b"; export type BusinessIndustry = | "111998" @@ -374,7 +432,6 @@ export type BusinessIndustry = | "334118" | "334210" | "336110" - | "336111" | "336390" | "337121" | "339112" @@ -417,7 +474,6 @@ export type BusinessIndustry = | "512250" | "513130" | "516120" - | "517110" | "517111" | "517112" | "517410" @@ -426,9 +482,7 @@ export type BusinessIndustry = | "522110" | "522210" | "522320" - | "523110" | "523150" - | "523920" | "523940" | "523999" | "524113" @@ -499,17 +553,252 @@ export type BusinessIndustry = | "813110" | "813211" | "813219" - | "dapp" - | "exchange" - | "gambling" - | "gaming" - | "infra" - | "marketplace" - | "neo_bank" - | "other" - | "saas" - | "social" - | "wallet"; + | "446120" + | "111120" + | "111219" + | "111336" + | "111421" + | "112111" + | "112210" + | "112310" + | "112410" + | "112519" + | "112990" + | "113110" + | "113210" + | "114119" + | "114210" + | "115113" + | "115210" + | "115310" + | "211130" + | "212290" + | "212390" + | "213113" + | "221122" + | "221210" + | "221320" + | "236118" + | "236210" + | "237130" + | "237210" + | "237990" + | "238191" + | "238391" + | "238991" + | "311119" + | "311212" + | "311314" + | "311422" + | "311511" + | "311612" + | "311710" + | "311811" + | "311999" + | "312111" + | "312230" + | "313240" + | "313310" + | "314120" + | "314999" + | "315120" + | "315250" + | "316110" + | "316210" + | "316990" + | "321113" + | "321211" + | "321918" + | "322120" + | "322299" + | "323120" + | "324110" + | "325180" + | "325220" + | "325320" + | "325510" + | "325611" + | "325998" + | "326111" + | "326220" + | "327120" + | "327212" + | "327310" + | "327410" + | "327999" + | "331110" + | "331210" + | "331313" + | "331410" + | "331511" + | "332111" + | "332215" + | "332311" + | "332410" + | "332510" + | "332613" + | "332710" + | "332812" + | "332999" + | "333111" + | "333248" + | "333310" + | "333413" + | "333517" + | "333611" + | "333618" + | "334310" + | "334413" + | "334511" + | "334610" + | "335131" + | "335220" + | "335311" + | "335999" + | "336211" + | "336412" + | "336510" + | "336611" + | "336999" + | "337122" + | "337214" + | "337920" + | "339999" + | "423120" + | "423220" + | "423310" + | "423490" + | "423520" + | "423620" + | "423710" + | "423990" + | "424110" + | "424310" + | "424490" + | "424590" + | "424720" + | "424820" + | "425120" + | "441110" + | "441227" + | "441330" + | "444180" + | "444240" + | "445132" + | "445298" + | "449110" + | "449129" + | "454390" + | "456120" + | "458320" + | "459310" + | "459410" + | "459510" + | "459999" + | "481211" + | "482111" + | "483112" + | "483212" + | "484110" + | "484220" + | "485119" + | "485310" + | "485410" + | "485510" + | "485999" + | "486110" + | "486210" + | "486990" + | "487110" + | "487210" + | "487990" + | "488190" + | "488210" + | "488390" + | "488490" + | "488999" + | "492110" + | "492210" + | "493190" + | "512199" + | "512290" + | "513210" + | "515210" + | "517810" + | "519290" + | "521110" + | "522130" + | "522298" + | "522390" + | "523210" + | "524128" + | "524298" + | "525190" + | "525910" + | "532289" + | "532310" + | "532490" + | "533110" + | "541199" + | "541213" + | "541219" + | "541310" + | "541490" + | "541690" + | "541720" + | "551114" + | "561110" + | "561210" + | "561599" + | "561611" + | "561790" + | "561990" + | "562211" + | "562998" + | "611210" + | "611420" + | "611519" + | "611699" + | "621498" + | "621610" + | "621999" + | "622210" + | "622310" + | "623210" + | "623311" + | "623990" + | "624190" + | "624230" + | "624310" + | "711190" + | "711219" + | "711310" + | "712120" + | "713290" + | "713990" + | "721199" + | "721211" + | "721310" + | "722310" + | "722410" + | "811198" + | "811310" + | "811411" + | "812210" + | "812320" + | "812990" + | "813319" + | "813410" + | "813930" + | "814110" + | "921140" + | "922190" + | "923130" + | "924110" + | "925120" + | "926110" + | "927110" + | "928110"; export type AccountPurpose = | "charitable_donations" @@ -551,9 +840,11 @@ export type SourceOfWealth = | "gambling" | "charitable_contributions" | "inheritance" + | "salary_or_wages" + | "savings" | "affiliate_or_royalty_income"; -export type BankingPartner = "jpmorgan" | "citi" | "hsbc" | "cfsb" | "portage" | "ssb"; +export type BankingPartner = "jpmorgan" | "citi" | "hsbc" | "cfsb" | "portage" | "bre_b" | "portage_g" | "spei"; export type SoleProprietorDocType = "master_service_agreement" | "salary_slip" | "bank_statement"; @@ -596,7 +887,7 @@ export type SourceOfFundsDocType = | "savings" | "someone_else_funds"; -export type PaymentMethod = "ach" | "wire" | "pix" | "spei" | "transfers" | "pse" | "international_swift" | "rtp" | "ted"; +export type PaymentMethod = "ach" | "wire" | "pix" | "spei" | "transfers" | "pse" | "international_swift" | "rtp" | "ted" | "ach_pull" | "card"; export type PayerRules = { pix_allowed_tax_ids?: string[] | null; @@ -610,51 +901,77 @@ export type PayerRules = { pse_bank_code?: string | null; } -export type TrackingStatus = 'processing' | 'on_hold' | 'completed' | 'pending_review'; +export type PayoutProviderIntegration = "veem" | "zenus" | "checkbook" | "onemoney" | "bitso" | "starkbank" | "triplea" | "infinitus" | "portage_g"; + +export type PayoutForcedProvider = "zenus" | "veem" | "infinitus_portage"; -export type EstimatedTimeOfArrival = '5_min' | '30_min' | '2_hours' | '1_business_day' | '2_business_days' | '5_business_days'; +export type TrackingStatus = 'processing' | 'on_hold' | 'completed' | 'pending_review' | "pending_refund_review"; + +export type EstimatedTimeOfArrival = '5_min' | '30_min' | '2_hours' | '1_business_day' | '2_business_days' | '5_business_days' | "5_30_min"; export type PayoutTrackingTransaction = { step: TrackingStatus - status: 'failed' | 'found'; - transaction_hash: string | null - completed_at: string | null + status?: 'failed' | 'found' | null; + transaction_hash?: string | null + completed_at?: string | null + ledger_in_transaction_id?: string | null; + ledger_out_transaction_id?: string | null; + provider_error_reason?: string | null; + provider_transaction_id?: string | null; }; export type PayoutTrackingPayment = { step: TrackingStatus - provider_name: string | null ; - provider_transaction_id: string | null ; - provider_status: 'canceled' | 'failed' | 'returned' | 'sent' | null - recipient_name: string | null ; - recipient_tax_id: string | null ; - recipient_bank_code: string | null ; - recipient_branch_code: string | null ; - recipient_account_number: string | null ; - recipient_account_type: string | null ; - estimated_time_of_arrival: EstimatedTimeOfArrival | null ; - completed_at: string | null ; + provider_name?: string | null ; + provider_transaction_id?: string | null ; + provider_status?: 'canceled' | 'failed' | 'returned' | 'sent' | null + recipient_name?: string | null ; + recipient_tax_id?: string | null ; + recipient_bank_code?: string | null ; + recipient_branch_code?: string | null ; + recipient_account_number?: string | null ; + recipient_account_type?: string | null ; + estimated_time_of_arrival?: EstimatedTimeOfArrival | null ; + completed_at?: string | null ; + forced_provider?: PayoutForcedProvider | null; + refund_review_actioned_at?: string | null; + refund_review_detected_at?: string | null; + refund_review_reason?: "amount_threshold" | "time_window" | "late_cancellation_no_live_run" | "master_account_return" | "policy_always_review" | "operator_requested" | "partial_return" | null; + returned_amount?: number | null; + review_context?: Record | null; + review_source?: string | null; + review_sources?: unknown[] | null; + coelsa_id?: string | null; + end_to_end_id?: string | null; + provider_clearing_system?: string | null; + provider_error_reason?: string | null; + provider_imad?: string | null; + provider_integration?: PayoutProviderIntegration | null; + provider_reference?: string | null; + provider_uetr?: string | null; }; export type PayoutTrackingLiquidity = { step: TrackingStatus - provider_transaction_id: string | null ; - provider_status: 'deposited' | 'converted' | 'withdrawn' | null; - estimated_time_of_arrival: EstimatedTimeOfArrival | null; - completed_at: string | null ; + provider_transaction_id?: string | null ; + provider_status?: 'deposited' | 'converted' | 'withdrawn' | null; + estimated_time_of_arrival?: EstimatedTimeOfArrival | null; + completed_at?: string | null ; } export type PayoutTrackingComplete = { step: TrackingStatus - status: 'tokens_refunded' | 'paid' | null; - transaction_hash: string | null; - completed_at: string | null; + status?: 'tokens_refunded' | 'paid' | null; + transaction_hash?: string | null; + completed_at?: string | null; + provider_transaction_id?: string | null; + refund_reason?: string | null; }; export type PayoutTrackingPartnerFee = { step: TrackingStatus - transaction_hash: string | null; - completed_at: string | null; + transaction_hash?: string | null; + completed_at?: string | null; } -export type KycStatus = "awaiting_contract" | "compliance_request" | "verifying" | "approved" | "rejected" | "deprecated" | "pending_review"; +export type KycStatus = "awaiting_contract" | "compliance_request" | "verifying" | "approved" | "rejected" | "deprecated" | "pending_review" | "approved_rfi";