OTC

Requester OTC surfaces: create and progress requests via /channel/vudy/otc/*, inspect status, check allowances, and produce user signatures. Provider-only routes: OTC provider.

Auth labels match the endpoint index. Envelopes follow Responses and errors.

For Header context routes, profile context may come from a valid session, both profile/team headers, or an API key scoped to both. GET /v1/otc is the exception documented below: it selects only the session profile or the API key’s scoped profile.

Endpoints#

MethodPathAuth
POST/channel/vudy/otc/createHeader context
POST/channel/vudy/otc/{id}/accept-offerAPI key
POST/channel/vudy/otc/{id}/deny-proofAPI key
POST/channel/vudy/otc/{id}/prepare-proofAPI key
POST/channel/vudy/otc/{id}/reject-offerAPI key
POST/channel/vudy/otc/{id}/submit-proofAPI key
POST/channel/vudy/otc/{id}/verify-proofAPI key
GET/v1/otcSession / scoped key
POST/v1/otc/allowance/checkWRITE
GET/v1/otc/gatingHeader context
GET/v1/otc/proof/{requestId}API key
POST/v1/otc/signatures/approveSession + WRITE
POST/v1/otc/signatures/approve-splitSession + WRITE
POST/v1/otc/signatures/create-escrow/userSession + WRITE
POST/v1/otc/signatures/deny-splitSession + WRITE
GET/v1/otc/txsHeader context

Details#

POST /channel/vudy/otc/create#

Creates an OTC request for the active profile/team context.

AuthSession / scoped key
PermissionsStandard API-key access (no extra permission flags).
GuideOTC requester guide

Requires x-api-key plus either Authorization: Bearer <session> or an API key scoped to a profile. This handler does not use x-profile-id / x-team-id as its profile selector.

Headers#

HeaderRequired
x-api-keyYes
AuthorizationRequired unless the API key carries profileId

Path parameters#

None.

Query parameters#

None.

Body#

FieldTypeRequired
targetAddressstringYes
amountnumberYes
channelParamsobjectYes
channelParams.requestTypeenum: buy, sellYes
channelParams.amountTypeenum: buy, sellYes
channelParams.buyCurrencystringYes
channelParams.sellCurrencystringYes
channelParams.buyChainstringYes
channelParams.sellChainstringYes
channelParams.userBankIdUUIDYes
channelParams.taxIdstringNo; 1–64 alphanumeric/dash characters

Success response#

Envelope wraps the created OTC request resource (DB row). Reliably known top-level keys include:

{
	"success": true,
	"data": {
		"id": "otc-uuid",
		"txId": "tx-uuid",
		"status": "new",
		"type": "buy",
		"buyAmount": 1000.5,
		"sellAmount": 0,
		"buyCurrency": "token-uuid",
		"sellCurrency": "token-uuid",
		"buyChainId": "chain-uuid",
		"sellChainId": "chain-uuid",
		"profileBankId": "bank-uuid",
		"amountUsd": 1000.5,
		"createdAt": "2026-07-28T12:00:00.000Z",
		"updatedAt": "2026-07-28T12:00:00.000Z"
	}
}

Additional row fields (for example idHash, feeInfo, escrowAddress, txs) may be present depending on persistence.

Errors and statuses#

HTTP statuses used by this route: 400, 403, 500, 200, 401.

CodeMeaning
CH-01Invalid API key
CH-02Invalid profile or team access
CH-03Invalid request body
CH-04Channel not available for app
CH-06Invalid channel parameters
CH-07Channel function execution failed

POST /channel/vudy/otc/{id}/accept-offer#

Accepting an OTC offer. It validates the user signature and creates the escrow contract on-chain.

AuthAPI key
PermissionsStandard API-key access (no extra permission flags).
GuideOTC requester guide

Requires x-api-key. No session required.

Headers#

HeaderRequired
x-api-keyYes

Path parameters#

ParamDescription
idPath parameter.

Query parameters#

None.

Body#

FieldTypeRequired
offerIdstringYes
userSignaturestringYes

Success response#

{
	"success": true,
	"data": {
		"escrowAddress": "0x...",
		"txHash": "0x...",
		"offerId": "offer-456",
		"requestId": "otc-123"
	}
}

Errors and statuses#

HTTP statuses used by this route: 400, 500, 200.

Typical failures: 403 (API key/permissions), 401 (session/context), 400 (validation), 429 (rate limit).

POST /channel/vudy/otc/{id}/deny-proof#

Denies submitted OTC proof for a request (moves the flow toward conflict when denial succeeds).

AuthAPI key
PermissionsStandard API-key access (no extra permission flags).
GuideOTC requester guide

Requires x-api-key. No session required.

Headers#

HeaderRequired
x-api-keyYes

Path parameters#

ParamDescription
idPath parameter.

Query parameters#

None.

Body#

FieldTypeRequired
splitIndexnumberYes
walletAddressstringYes
signaturestringYes
reasonstringNo

Success response#

{
	"success": true,
	"data": {
		"requestId": "otc-123",
		"splitIndex": 0,
		"reason": "Invalid receipt",
		"txHash": "0x...",
		"status": "conflict"
	}
}

Errors and statuses#

HTTP statuses used by this route: 400, 500, 200.

Typical failures: 403 (API key/permissions), 401 (session/context), 400 (validation), 429 (rate limit).

POST /channel/vudy/otc/{id}/prepare-proof#

Preparing proof upload on an OTC request. It generates signed URLs for uploading proof files to cloud storage.

AuthAPI key
PermissionsStandard API-key access (no extra permission flags).
GuideOTC requester guide

Requires x-api-key. No session required.

Headers#

HeaderRequired
x-api-keyYes

Path parameters#

ParamDescription
idPath parameter.

Query parameters#

None.

Body#

FieldTypeRequired
fileNamesstring[]Yes — at least one supported PDF/image filename
splitIndexnumberYes

Success response#

{
	"success": true,
	"data": {
		"uploadUrls": [
			{
				"fileName": "receipt.pdf",
				"signedUrl": "https://storage.googleapis.com/...",
				"expiresAt": "2024-01-01T01:00:00Z",
				"filePath": "otc-proofs/otc-123/..."
			}
		],
		"uploadId": "upload_1234567890_abc",
		"splitIndex": 0
	}
}

Errors and statuses#

HTTP statuses used by this route: 400, 500, 200.

Typical failures: 403 (API key/permissions), 401 (session/context), 400 (validation), 429 (rate limit).

POST /channel/vudy/otc/{id}/reject-offer#

Rejecting an OTC offer. It includes authorization checks to ensure only the OTC request creator’s team can reject offers.

AuthAPI key
PermissionsStandard API-key access (no extra permission flags).
GuideOTC requester guide

Requires x-api-key. No session required.

Headers#

HeaderRequired
x-api-keyYes

Path parameters#

ParamDescription
idPath parameter.

Query parameters#

None.

Body#

FieldTypeRequired
offerIdstringYes

Success response#

{
	"success": true,
	"data": {
		"offerId": "offer-456",
		"status": "rejected"
	}
}

Errors and statuses#

HTTP statuses used by this route: 400, 403, 500, 404, 200, 401.

Typical failures: 403 (API key/permissions), 401 (session/context), 400 (validation), 429 (rate limit).

POST /channel/vudy/otc/{id}/submit-proof#

Submitting proof on an OTC request. It processes uploaded proof files and submits approval transaction to blockchain.

AuthAPI key
PermissionsStandard API-key access (no extra permission flags).
GuideOTC requester guide

Requires x-api-key. No session required.

Headers#

HeaderRequired
x-api-keyYes

Path parameters#

ParamDescription
idPath parameter.

Query parameters#

None.

Body#

FieldTypeRequired
splitIndexnumberYes
signaturestringYes
forceNewProofbooleanNo

Success response#

{
	"success": true,
	"data": {
		"requestId": "otc-123",
		"splitIndex": 0,
		"txHash": "0x..."
	}
}

Errors and statuses#

HTTP statuses used by this route: 400, 500, 200.

Typical failures: 403 (API key/permissions), 401 (session/context), 400 (validation), 429 (rate limit).

POST /channel/vudy/otc/{id}/verify-proof#

Verifies submitted OTC proof for a request (advances the flow when verification succeeds).

AuthAPI key
PermissionsStandard API-key access (no extra permission flags).
GuideOTC requester guide

Requires x-api-key. No session required.

Headers#

HeaderRequired
x-api-keyYes

Path parameters#

ParamDescription
idPath parameter.

Query parameters#

None.

Body#

FieldTypeRequired
splitIndexnumberYes
signaturestringYes

Success response#

{
	"success": true,
	"data": {
		"requestId": "otc-123",
		"splitIndex": 0,
		"txHash": "0x...",
		"status": "verification sent"
	}
}

Errors and statuses#

HTTP statuses used by this route: 400, 500, 200.

Typical failures: 403 (API key/permissions), 401 (session/context), 400 (validation), 429 (rate limit).

GET /v1/otc#

Retrieving OTC requests for a profile with comprehensive filtering options.

AuthHeader context
PermissionsStandard API-key access (no extra permission flags).
GuideOTC requester guide

Requires x-api-key. Use Authorization: Bearer <session> or x-profile-id + x-team-id.

Headers#

HeaderRequired
x-api-keyYes
AuthorizationOptional (preferred)
x-profile-idRequired when no session
x-team-idRequired when no session

Path parameters#

None.

Query parameters#

FieldTypeRequired
buyCurrencystringNo
endDatestringNo
limitstringNo
maxAmountUsdstringNo
maxBuyAmountstringNo
maxSellAmountstringNo
minAmountUsdstringNo
minBuyAmountstringNo
minSellAmountstringNo
offsetstringNo
sellCurrencystringNo
startDatestringNo
statusrepeatable enum: new, processing, proofing, verifying, conflict, completed, cancelledNo
typeenum: buy, sellNo
updatedEndDatestringNo
updatedStartDatestringNo

Body#

Not applicable.

Success response#

{
	"success": true,
	"data": [
		{
			"otcRequest": {
				"id": "otc-123",
				"txId": "tx-456",
				"status": "new",
				"type": "buy",
				"buyAmount": 1000.5,
				"sellAmount": 950.0,
				"createdAt": "2024-01-01T00:00:00Z"
			},
			"tx": {
				"id": "tx-456",
				"status": "pending"
			},
			"buyToken": {
				"symbol": "USDC"
			},
			"sellToken": {
				"symbol": "USDT"
			}
		}
	]
}

Errors and statuses#

HTTP statuses used by this route: 400, 500, 200, 401.

Typical failures: 403 (API key/permissions), 401 (session/context), 400 (validation), 429 (rate limit).

POST /v1/otc/allowance/check#

Checking ERC20 token allowance for the escrow factory contract. Compares current allowance with required amount.

AuthAPI key + WRITE
PermissionsWRITE
GuideOTC requester guide

Requires x-api-key. No session required.

Headers#

HeaderRequired
x-api-keyYes

Path parameters#

None.

Query parameters#

None.

Body#

FieldTypeRequired
chainIdnumberYes
tokenAddressstringYes
senderAddressstringYes
amountToCheckstringYes

Success response#

Standard envelope: { "success": true, "data": <resource> }. See the linked guide for workflow-specific fields.

Errors and statuses#

HTTP statuses used by this route: 400, 500, 200.

Typical failures: 403 (API key/permissions), 401 (session/context), 400 (validation), 429 (rate limit).

GET /v1/otc/gating#

OTC Gating Preflight API Endpoint

AuthHeader context
PermissionsStandard API-key access (no extra permission flags).
GuideOTC requester guide

Requires x-api-key. Use Authorization: Bearer <session> or x-profile-id + x-team-id.

Headers#

HeaderRequired
x-api-keyYes
AuthorizationOptional (preferred)
x-profile-idRequired when no session
x-team-idRequired when no session

Path parameters#

None.

Query parameters#

None.

Body#

Not applicable.

Success response#

Standard envelope: { "success": true, "data": <resource> }. See the linked guide for workflow-specific fields.

Errors and statuses#

Typical failures: 403 (API key/permissions), 401 (session/context), 400 (validation), 429 (rate limit).

GET /v1/otc/proof/{requestId}#

Returns time-limited signed URLs for OTC proof files the caller is authorized to access.

AuthAPI key
PermissionsStandard API-key access (no extra permission flags).
GuideOTC requester guide

Requires x-api-key. No session required.

Headers#

HeaderRequired
x-api-keyYes

Path parameters#

ParamDescription
requestIdPath parameter.

Query parameters#

None.

Body#

Not applicable.

Success response#

{
	"success": true,
	"data": {
		"proofUrls": [
			{
				"filePath": "otc-proofs/otc-123/1234567890-receipt.pdf",
				"signedUrl": "https://storage.googleapis.com/...",
				"expiresAt": "2024-01-01T01:00:00Z"
			}
		]
	}
}

Errors and statuses#

HTTP statuses used by this route: 400, 403, 500, 404, 200.

Typical failures: 403 (API key/permissions), 401 (session/context), 400 (validation), 429 (rate limit).

POST /v1/otc/signatures/approve#

Approves ERC-20 tokens for the OTC escrow factory. With a session that can sign, the API may submit the approval; otherwise it returns transaction data for the client to sign and send.

AuthSession + WRITE
PermissionsWRITE
GuideOTC requester guide

Requires x-api-key and Authorization: Bearer <session>.

Headers#

HeaderRequired
x-api-keyYes
AuthorizationYes — Bearer <session>

Path parameters#

None.

Query parameters#

None.

Body#

FieldTypeRequired
chainIdnumberYes
tokenAddressstringYes
senderWalletstringYes
amount"max", positive number, or positive numeric stringYes
autoSignbooleanNo — defaults to false

Success response#

Standard envelope: { "success": true, "data": <resource> }. See the linked guide for workflow-specific fields.

Errors and statuses#

HTTP statuses used by this route: 400, 500, 200, 401.

Typical failures: 403 (API key/permissions), 401 (session/context), 400 (validation), 429 (rate limit).

POST /v1/otc/signatures/approve-split#

Generates EIP-712 data for approving escrow splits. With a session that can sign, the API may complete signing; otherwise it returns EIP-712 typed data for the client wallet.

AuthSession + WRITE
PermissionsWRITE
GuideOTC requester guide

Requires x-api-key and Authorization: Bearer <session>.

Headers#

HeaderRequired
x-api-keyYes
AuthorizationYes — Bearer <session>

Path parameters#

None.

Query parameters#

None.

Body#

FieldTypeRequired
otcRequestIdstringYes
splitIndexnumberYes
userWalletAddressstringYes

Success response#

Standard envelope: { "success": true, "data": <resource> }. See the linked guide for workflow-specific fields.

Errors and statuses#

HTTP statuses used by this route: 400, 403, 500, 200.

Typical failures: 403 (API key/permissions), 401 (session/context), 400 (validation), 429 (rate limit).

POST /v1/otc/signatures/create-escrow/user#

Generates EIP-712 data for user escrow approval. With a session that can sign, the API may complete signing; otherwise it returns EIP-712 typed data for the client wallet.

AuthSession + WRITE
PermissionsWRITE
GuideOTC requester guide

Requires x-api-key and Authorization: Bearer <session>.

Headers#

HeaderRequired
x-api-keyYes
AuthorizationYes — Bearer <session>

Path parameters#

None.

Query parameters#

None.

Body#

FieldTypeRequired
otcRequestIdstringYes
offerIdstringYes

Success response#

{
	"success": true,
	"data": {
		"signature": "0x123abc...",
		"signed": true
	}
}

Errors and statuses#

HTTP statuses used by this route: 400, 403, 500, 404, 200.

Typical failures: 403 (API key/permissions), 401 (session/context), 400 (validation), 429 (rate limit).

POST /v1/otc/signatures/deny-split#

Generates EIP-712 data for denying escrow splits. With a session that can sign, the API may complete signing; otherwise it returns EIP-712 typed data for the client wallet.

AuthSession + WRITE
PermissionsWRITE
GuideOTC requester guide

Requires x-api-key and Authorization: Bearer <session>.

Headers#

HeaderRequired
x-api-keyYes
AuthorizationYes — Bearer <session>

Path parameters#

None.

Query parameters#

None.

Body#

FieldTypeRequired
otcRequestIdstringYes
splitIndexnumberYes
userWalletAddressstringYes

Success response#

Standard envelope: { "success": true, "data": <resource> }. See the linked guide for workflow-specific fields.

Errors and statuses#

HTTP statuses used by this route: 400, 403, 500, 200.

Typical failures: 403 (API key/permissions), 401 (session/context), 400 (validation), 429 (rate limit).

GET /v1/otc/txs#

Retrieving OTC transactions with details and offers for profiles or teams.

AuthHeader context
PermissionsStandard API-key access (no extra permission flags).
GuideOTC requester guide

Requires x-api-key. Use Authorization: Bearer <session> or x-profile-id + x-team-id.

Headers#

HeaderRequired
x-api-keyYes
AuthorizationOptional (preferred)
x-profile-idRequired when no session
x-team-idRequired when no session

Path parameters#

None.

Query parameters#

FieldTypeRequired
typestringNo

Body#

Not applicable.

Success response#

Standard envelope: { "success": true, "data": <resource> }. See the linked guide for workflow-specific fields.

Errors and statuses#

HTTP statuses used by this route: 400, 500, 200.

Typical failures: 403 (API key/permissions), 401 (session/context), 400 (validation), 429 (rate limit).