openapi: 3.2.0 info: title: Escrow Transfer Transfer Requests API description: Send funds to a recipient who may not yet have a Solana wallet. The recipient's wallet is attached after they sign up. Backs the legacy movemoney 'send to phone' flow. termsOfService: http://cfxlabs.com/terms/ contact: name: API Owner url: https://api.cfxlabs.net email: api@cfxlabs.com version: '@VERSION@' summary: CFX Escrow Transfer API servers: - url: https://api.dev.cfx.to description: Customer Sandbox - url: https://api.cfx.to description: Production security: - ApiKeyAuth: [] ApiSecretAuth: [] tags: - name: Transfer Requests description: Request-for-payment flow that precedes an escrow transfer (create, accept, reject, cancel). paths: /v1/escrow-transfers/requests: get: summary: List Escrow Transfer Requests tags: - Transfer Requests description: List escrow transfer requests the calling customer owns. Filter by `senderId` (requests this identity sent) or `recipientPhone` (requests addressed to this phone). Filters compose (AND) and the customer scope is enforced server-side. parameters: - schema: type: string in: query name: senderId required: false description: Filter to requests sent by this identity id - schema: type: string in: query name: recipientPhone required: false description: Filter to requests addressed to this E.164 phone - schema: type: string in: query name: statuses required: false description: Comma-separated statuses (CREATED,SENT,CANCELLED,REJECTED) - schema: type: integer minimum: 1 in: query name: page required: false - schema: type: integer minimum: 1 maximum: 500 in: query name: pageSize required: false responses: '200': description: Default Response content: application/json: schema: type: object required: - items - hasNext - total - page - pageSize properties: items: type: array items: type: object required: - id - senderId - senderPhone - recipientId - recipientPhone - tokenSymbol - amount - message - escrowTransferId - status - createdAt - updatedAt properties: id: type: string description: Escrow transfer request external id (etrq_…) example: etrq_RD2of9vs3XFodUSd8T5hW senderId: type: string description: Customer-scoped identity id of the requester (sender) senderPhone: type: string description: E.164 phone number of the requester pattern: ^\+[1-9]\d{1,14}$ minLength: 3 maxLength: 16 example: '+15551234567' recipientId: anyOf: - type: string - type: 'null' description: Customer-scoped identity id of the recipient — null when the recipient is not (yet) a known identity recipientPhone: type: string description: E.164 phone number the request is sent to pattern: ^\+[1-9]\d{1,14}$ minLength: 3 maxLength: 16 example: '+15551234567' tokenSymbol: type: string description: Token symbol the request is denominated in example: MOVEUSD amount: type: string description: Big-number string message: anyOf: - type: string - type: 'null' description: Optional human-readable note from the requester escrowTransferId: anyOf: - type: string - type: 'null' description: External id (etr_…) of the escrow transfer that fulfilled this request; null until status is SENT status: enum: - CREATED - SENT - CANCELLED - REJECTED type: string createdAt: type: string updatedAt: type: string title: EscrowTransferRequest hasNext: type: boolean total: type: integer minimum: 0 page: type: integer minimum: 1 pageSize: type: integer minimum: 1 '400': description: The service cannot understand the request content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - INVALID_REQUEST message: type: string errors: type: array items: type: object properties: {} additionalProperties: true title: INVALID_REQUEST description: The service cannot understand the request '401': description: The access to this resource has been denied content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - UNAUTHORIZED message: type: string title: UNAUTHORIZED description: The access to this resource has been denied '403': description: The credentials are valid but the caller is not permitted to transact content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - FORBIDDEN message: type: string title: FORBIDDEN description: The credentials are valid but the caller is not permitted to transact default: description: Catch-all error response for any unexpected internal errors content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - INTERNAL message: type: string enum: - An unexpected internal error has occurred title: INTERNAL description: Catch-all error response for any unexpected internal errors operationId: getV1EscrowTransfersRequests x-operation-id-source: derived post: summary: Create Escrow Transfer Request tags: - Transfer Requests description: 'Create a request for payment. A request is the intent that precedes an `escrow_transfer`: the recipient (addressed by phone, possibly before sign-up) is asked to be paid. When the sender later pays, call `/accept` with the resulting escrow transfer id to move the request to SENT.' requestBody: required: true content: application/json: schema: type: object required: - senderId - senderPhone - recipientPhone - tokenSymbol - amount properties: senderId: type: string description: Customer-scoped identity id of the requester (sender) senderPhone: type: string description: E.164 phone number of the requester pattern: ^\+[1-9]\d{1,14}$ minLength: 3 maxLength: 16 example: '+15551234567' recipientPhone: type: string description: E.164 phone number to request payment from pattern: ^\+[1-9]\d{1,14}$ minLength: 3 maxLength: 16 example: '+15551234567' tokenSymbol: type: string description: Token symbol the request is denominated in — e.g. MOVEUSD example: MOVEUSD amount: type: string description: Decimal token amount as a string (e.g. "1.31"), not raw base units example: '1.31' message: type: string maxLength: 280 description: Optional human-readable note from the requester payUrl: type: string maxLength: 2048 description: Optional 'tap to pay' link for the recipient SMS. Shortened via the short-URL service and embedded as the call-to-action. Not persisted on the request. example: https://app.example.com/pay/etrq_RD2of9vs3XFodUSd8T5hW parameters: - schema: type: string in: header name: Idempotency-Key required: false responses: '201': description: Default Response content: application/json: schema: type: object required: - id - senderId - senderPhone - recipientId - recipientPhone - tokenSymbol - amount - message - escrowTransferId - status - createdAt - updatedAt properties: id: type: string description: Escrow transfer request external id (etrq_…) example: etrq_RD2of9vs3XFodUSd8T5hW senderId: type: string description: Customer-scoped identity id of the requester (sender) senderPhone: type: string description: E.164 phone number of the requester pattern: ^\+[1-9]\d{1,14}$ minLength: 3 maxLength: 16 example: '+15551234567' recipientId: anyOf: - type: string - type: 'null' description: Customer-scoped identity id of the recipient — null when the recipient is not (yet) a known identity recipientPhone: type: string description: E.164 phone number the request is sent to pattern: ^\+[1-9]\d{1,14}$ minLength: 3 maxLength: 16 example: '+15551234567' tokenSymbol: type: string description: Token symbol the request is denominated in example: MOVEUSD amount: type: string description: Big-number string message: anyOf: - type: string - type: 'null' description: Optional human-readable note from the requester escrowTransferId: anyOf: - type: string - type: 'null' description: External id (etr_…) of the escrow transfer that fulfilled this request; null until status is SENT status: enum: - CREATED - SENT - CANCELLED - REJECTED type: string createdAt: type: string updatedAt: type: string title: EscrowTransferRequest '400': description: Default Response content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - INVALID_REQUEST - SELF_SEND description: '- `INVALID_REQUEST`: The service cannot understand the request - `SELF_SEND`' message: type: string errors: type: array items: type: object properties: {} additionalProperties: true '401': description: The access to this resource has been denied content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - UNAUTHORIZED message: type: string title: UNAUTHORIZED description: The access to this resource has been denied '403': description: The credentials are valid but the caller is not permitted to transact content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - FORBIDDEN message: type: string title: FORBIDDEN description: The credentials are valid but the caller is not permitted to transact '409': description: A duplicate request with this idempotency key is already in progress content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - IDEMPOTENCY_IN_PROGRESS message: type: string title: IDEMPOTENCY_IN_PROGRESS description: A duplicate request with this idempotency key is already in progress '422': description: Another request with this idempotency key was made using a different body content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - IDEMPOTENCY_KEY_REUSED message: type: string title: IDEMPOTENCY_KEY_REUSED description: Another request with this idempotency key was made using a different body default: description: Catch-all error response for any unexpected internal errors content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - INTERNAL message: type: string enum: - An unexpected internal error has occurred title: INTERNAL description: Catch-all error response for any unexpected internal errors operationId: postV1EscrowTransfersRequests x-operation-id-source: derived /v1/escrow-transfers/requests/{id}: get: summary: Get Escrow Transfer Request tags: - Transfer Requests parameters: - schema: type: string in: path name: id required: true responses: '200': description: Default Response content: application/json: schema: type: object required: - id - senderId - senderPhone - recipientId - recipientPhone - tokenSymbol - amount - message - escrowTransferId - status - createdAt - updatedAt properties: id: type: string description: Escrow transfer request external id (etrq_…) example: etrq_RD2of9vs3XFodUSd8T5hW senderId: type: string description: Customer-scoped identity id of the requester (sender) senderPhone: type: string description: E.164 phone number of the requester pattern: ^\+[1-9]\d{1,14}$ minLength: 3 maxLength: 16 example: '+15551234567' recipientId: anyOf: - type: string - type: 'null' description: Customer-scoped identity id of the recipient — null when the recipient is not (yet) a known identity recipientPhone: type: string description: E.164 phone number the request is sent to pattern: ^\+[1-9]\d{1,14}$ minLength: 3 maxLength: 16 example: '+15551234567' tokenSymbol: type: string description: Token symbol the request is denominated in example: MOVEUSD amount: type: string description: Big-number string message: anyOf: - type: string - type: 'null' description: Optional human-readable note from the requester escrowTransferId: anyOf: - type: string - type: 'null' description: External id (etr_…) of the escrow transfer that fulfilled this request; null until status is SENT status: enum: - CREATED - SENT - CANCELLED - REJECTED type: string createdAt: type: string updatedAt: type: string title: EscrowTransferRequest '400': description: The service cannot understand the request content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - INVALID_REQUEST message: type: string errors: type: array items: type: object properties: {} additionalProperties: true title: INVALID_REQUEST description: The service cannot understand the request '401': description: The access to this resource has been denied content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - UNAUTHORIZED message: type: string title: UNAUTHORIZED description: The access to this resource has been denied '403': description: The credentials are valid but the caller is not permitted to transact content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - FORBIDDEN message: type: string title: FORBIDDEN description: The credentials are valid but the caller is not permitted to transact '404': description: The resource was not found content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - NOT_FOUND message: type: string title: NOT_FOUND description: The resource was not found default: description: Catch-all error response for any unexpected internal errors content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - INTERNAL message: type: string enum: - An unexpected internal error has occurred title: INTERNAL description: Catch-all error response for any unexpected internal errors operationId: getV1EscrowTransfersRequestsById x-operation-id-source: derived /v1/escrow-transfers/requests/{id}/cancel: post: summary: Cancel Escrow Transfer Request tags: - Transfer Requests description: Mark the request CANCELLED. Only CREATED requests can be cancelled. The caller is responsible for authorizing that the actor is the request's sender — the API enforces customer-scope only. parameters: - schema: type: string in: path name: id required: true - schema: type: string in: header name: Idempotency-Key required: false responses: '200': description: Default Response content: application/json: schema: type: object required: - id - status properties: id: type: string status: enum: - CREATED - SENT - CANCELLED - REJECTED type: string '400': description: The service cannot understand the request content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - INVALID_REQUEST message: type: string errors: type: array items: type: object properties: {} additionalProperties: true title: INVALID_REQUEST description: The service cannot understand the request '401': description: The access to this resource has been denied content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - UNAUTHORIZED message: type: string title: UNAUTHORIZED description: The access to this resource has been denied '403': description: The credentials are valid but the caller is not permitted to transact content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - FORBIDDEN message: type: string title: FORBIDDEN description: The credentials are valid but the caller is not permitted to transact '404': description: The resource was not found content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - NOT_FOUND message: type: string title: NOT_FOUND description: The resource was not found '409': description: Default Response content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - IDEMPOTENCY_IN_PROGRESS - INVALID_STATUS_TRANSITION description: '- `IDEMPOTENCY_IN_PROGRESS`: A duplicate request with this idempotency key is already in progress - `INVALID_STATUS_TRANSITION`: The request is not in a status the action is allowed from — only CREATED requests can be cancelled, rejected, or accepted' message: type: string '422': description: Another request with this idempotency key was made using a different body content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - IDEMPOTENCY_KEY_REUSED message: type: string title: IDEMPOTENCY_KEY_REUSED description: Another request with this idempotency key was made using a different body default: description: Catch-all error response for any unexpected internal errors content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - INTERNAL message: type: string enum: - An unexpected internal error has occurred title: INTERNAL description: Catch-all error response for any unexpected internal errors operationId: postV1EscrowTransfersRequestsByIdCancel x-operation-id-source: derived /v1/escrow-transfers/requests/{id}/reject: post: summary: Reject Escrow Transfer Request tags: - Transfer Requests description: Mark the request REJECTED. Only CREATED requests can be rejected. The caller is responsible for authorizing that the actor is the request's recipient — the API enforces customer-scope only. parameters: - schema: type: string in: path name: id required: true - schema: type: string in: header name: Idempotency-Key required: false responses: '200': description: Default Response content: application/json: schema: type: object required: - id - status properties: id: type: string status: enum: - CREATED - SENT - CANCELLED - REJECTED type: string '400': description: The service cannot understand the request content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - INVALID_REQUEST message: type: string errors: type: array items: type: object properties: {} additionalProperties: true title: INVALID_REQUEST description: The service cannot understand the request '401': description: The access to this resource has been denied content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - UNAUTHORIZED message: type: string title: UNAUTHORIZED description: The access to this resource has been denied '403': description: The credentials are valid but the caller is not permitted to transact content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - FORBIDDEN message: type: string title: FORBIDDEN description: The credentials are valid but the caller is not permitted to transact '404': description: The resource was not found content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - NOT_FOUND message: type: string title: NOT_FOUND description: The resource was not found '409': description: Default Response content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - IDEMPOTENCY_IN_PROGRESS - INVALID_STATUS_TRANSITION description: '- `IDEMPOTENCY_IN_PROGRESS`: A duplicate request with this idempotency key is already in progress - `INVALID_STATUS_TRANSITION`: The request is not in a status the action is allowed from — only CREATED requests can be cancelled, rejected, or accepted' message: type: string '422': description: Another request with this idempotency key was made using a different body content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - IDEMPOTENCY_KEY_REUSED message: type: string title: IDEMPOTENCY_KEY_REUSED description: Another request with this idempotency key was made using a different body default: description: Catch-all error response for any unexpected internal errors content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - INTERNAL message: type: string enum: - An unexpected internal error has occurred title: INTERNAL description: Catch-all error response for any unexpected internal errors operationId: postV1EscrowTransfersRequestsByIdReject x-operation-id-source: derived /v1/escrow-transfers/requests/{id}/accept: post: summary: Accept Escrow Transfer Request tags: - Transfer Requests description: 'Record that the recipient accepted the request and was paid: links the fulfilling escrow transfer id and moves the request to SENT. Only CREATED requests can be accepted; an escrow transfer id already linked to another request is rejected.' requestBody: required: true content: application/json: schema: type: object required: - escrowTransferId properties: escrowTransferId: type: string description: External id (etr_…) of the escrow transfer that paid this request. Recorded on the request as it transitions to SENT. example: etr_RD2of9vs3XFodUSd8T5hW parameters: - schema: type: string in: path name: id required: true - schema: type: string in: header name: Idempotency-Key required: false responses: '200': description: Default Response content: application/json: schema: type: object required: - id - status properties: id: type: string status: enum: - CREATED - SENT - CANCELLED - REJECTED type: string '400': description: The service cannot understand the request content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - INVALID_REQUEST message: type: string errors: type: array items: type: object properties: {} additionalProperties: true title: INVALID_REQUEST description: The service cannot understand the request '401': description: The access to this resource has been denied content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - UNAUTHORIZED message: type: string title: UNAUTHORIZED description: The access to this resource has been denied '403': description: The credentials are valid but the caller is not permitted to transact content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - FORBIDDEN message: type: string title: FORBIDDEN description: The credentials are valid but the caller is not permitted to transact '404': description: The resource was not found content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - NOT_FOUND message: type: string title: NOT_FOUND description: The resource was not found '409': description: Default Response content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - IDEMPOTENCY_IN_PROGRESS - INVALID_STATUS_TRANSITION - ESCROW_TRANSFER_ALREADY_LINKED description: '- `IDEMPOTENCY_IN_PROGRESS`: A duplicate request with this idempotency key is already in progress - `INVALID_STATUS_TRANSITION` - `ESCROW_TRANSFER_ALREADY_LINKED`' message: type: string '422': description: Another request with this idempotency key was made using a different body content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - IDEMPOTENCY_KEY_REUSED message: type: string title: IDEMPOTENCY_KEY_REUSED description: Another request with this idempotency key was made using a different body default: description: Catch-all error response for any unexpected internal errors content: application/json: schema: type: object required: - code - message properties: code: type: string enum: - INTERNAL message: type: string enum: - An unexpected internal error has occurred title: INTERNAL description: Catch-all error response for any unexpected internal errors operationId: postV1EscrowTransfersRequestsByIdAccept x-operation-id-source: derived components: securitySchemes: ApiKeyAuth: name: x-api-key type: apiKey in: header ApiSecretAuth: name: x-api-secret type: apiKey in: header externalDocs: description: Find out more about CFX url: https://www.cfxlabs.com/