Halliday Payments API
Core payment operations including quotes, confirmation, and status tracking
Core payment operations including quotes, confirmation, and status tracking
openapi: 3.1.0
info:
title: Halliday API V2 Assets Payments API
description: 'API V2 for Halliday''s payment infrastructure, supporting onramps, swaps, and offramps.
This API provides a unified interface for cryptocurrency payments, allowing developers to:
- Quote payments across multiple providers
- Execute payments with onramps, swaps, and offramps
- Track payment status and history
## Authentication
API key authentication is required for all endpoints.
'
version: 2.0.0
contact:
name: Contact Halliday
url: https://halliday.xyz
email: support@halliday.xyz
servers:
- url: https://v2.prod.halliday.xyz
description: Base domain
security:
- ApiKeyAuth: []
tags:
- name: Payments
description: Core payment operations including quotes, confirmation, and status tracking
paths:
/payments:
get:
summary: Get payment status
description: 'Get the current status of a payment, including progress through onramp/swap/offramp stages.
'
operationId: getPaymentStatus
tags:
- Payments
parameters:
- name: payment_id
in: query
required: true
description: Payment identifier to check
schema:
type: string
responses:
'200':
description: Payment status retrieved successfully!
content:
application/json:
schema:
$ref: '#/components/schemas/PaymentStatus'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: 'Missing required parameter: payment_id'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Invalid API key
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: You do not have permission to view this payment
'404':
description: Payment not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Payment with payment_id 'pay_abc123' not found
/payments/history:
get:
summary: Get payment history
description: 'Retrieve a paginated list of payment statuses filtered by owner.
Returns an array of payment status objects and a pagination key for fetching the next page.
'
operationId: getPaymentHistory
tags:
- Payments
parameters:
- name: owner_address
in: query
required: false
description: Owner address to filter payments by
schema:
type: string
- name: pagination_key
in: query
required: false
description: Pagination key from previous response to fetch next page
schema:
type: string
- name: limit
in: query
required: false
description: Maximum number of results to return
schema:
type: number
- name: id_query
in: query
required: false
description: Filter payments by ID
schema:
type: string
- name: dest_address
in: query
required: false
description: Filter payments by destination address
schema:
type: string
- name: category
in: query
required: false
description: Filter payments by category
schema:
type: string
enum:
- ALL
- NEW_OR_FUNDED
default: NEW_OR_FUNDED
- name: label
in: query
required: false
description: Filter payments by label
schema:
type: string
responses:
'200':
description: Payment history retrieved successfully
content:
application/json:
schema:
type: object
required:
- payment_statuses
- next_pagination_key
properties:
payment_statuses:
type: array
items:
$ref: '#/components/schemas/PaymentStatus'
description: Array of payment status objects
next_pagination_key:
anyOf:
- type: string
- type: 'null'
description: Pagination key to fetch the next page of results
example: 42ff9b02-037f-4a90-87fb-a4d2ca128565_2025-11-12T22:08:52.517Z
example:
payment_statuses:
- payment_id: <string>
status: COMPLETE
funded: true
created_at: '2025-11-12T20:15:30.000Z'
updated_at: '2025-11-12T20:25:45.000Z'
initiate_fund_by: '2025-11-12T21:15:30.000Z'
completed_at: '2025-11-12T20:25:45.000Z'
quoted:
output_amount:
asset: ethereum:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
amount: '100.00'
fees:
total_fees: '3.50'
conversion_fees: '2.00'
network_fees: '1.00'
business_fees: '0.50'
currency_symbol: USD
onramp: stripe
onramp_method: credit_card
route:
- type: ONRAMP
net_effect:
consume:
- account: USER
resource:
asset: usd
property: BALANCE
amount:
amount: '103.50'
produce:
- account: PROCESSING_ADDRESS
resource:
asset: ethereum:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
property: BALANCE
amount:
amount: '100.00'
pieces_info:
- type: onramp
step_index: 0
fulfilled:
output_amount:
asset: ethereum:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
amount: '100.00'
fees:
total_fees: '3.50'
conversion_fees: '2.00'
network_fees: '1.00'
business_fees: '0.50'
currency_symbol: USD
onramp: stripe
onramp_method: credit_card
route:
- status: COMPLETE
type: ONRAMP
net_effect:
consume:
- account: USER
resource:
asset: usd
property: BALANCE
amount:
amount: '103.50'
produce:
- account: PROCESSING_ADDRESS
resource:
asset: ethereum:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
property: BALANCE
amount:
amount: '100.00'
pieces_info:
- type: onramp
step_index: 0
transaction_hash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
current_prices:
USD: '1.00'
ethereum:0x: '4200.00'
ethereum:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48: '1.00'
price_currency: USD
processing_addresses:
- chain: ethereum
address: 0xaddress...
owner_address: 0xowner...
destination_address: 0xdest...
next_pagination_key: 42ff9b02-037f-4a90-87fb-a4d2ca128565_2025-11-12T22:08:52.517Z
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: 'Missing required parameter: owner_address'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Invalid API key
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: You do not have permission to access payment history for this address
/payments/quotes:
post:
summary: Get payment quotes
description: 'Request quotes for payments, supporting both fixed input and fixed output scenarios.
Returns multiple quote options with pricing, fees, and routing information.
This endpoint can also be used to requote from an existing payment by providing a payment_id.
When requoting, input amounts are automatically derived from
the payment''s current state, but you can optionally override the output asset.
'
operationId: getPaymentQuotes
tags:
- Payments
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/QuoteRequest'
responses:
'200':
description: Successful quote response
content:
application/json:
schema:
$ref: '#/components/schemas/QuoteResponse'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: amount
given: '5'
limits:
min: '10'
max: '10000'
source: moonpay
message: Amount too low. Minimum amount is $10 USD
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: API key missing or invalid
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Your API key does not have permission to create quotes
/payments/confirm:
post:
summary: Confirm a payment
description: 'Confirm a previously quoted payment and receive deposit instructions.
Returns information on how to fund the payment (widget URL, contract address, etc.).
If a payment output is >= $300 USD, the owner address will need to produce a EVM_OWNER
signature. The response will include a USER_VERIFY next_instruction instead of funding
details. In this case, prompt the user to sign the verification payloads via signTypedData,
then submit a ContinueConfirmPaymentRequest to this same endpoint to complete confirmation.
Once an owner address has produced an EVM_OWNER signature, subsequent payments with that
owner address will not require the signature again.
'
operationId: confirmPayment
tags:
- Payments
requestBody:
required: true
content:
application/json:
schema:
oneOf:
- title: ConfirmPaymentRequest
description: Initial payment confirmation request.
type: object
required:
- payment_id
- state_token
- owner_address
- destination_address
properties:
payment_id:
type: string
description: ID of the payment from the quote to confirm
state_token:
type: string
description: State token from the quote response
owner_address:
type: string
description: Owner address for the payment. This is the address that the payment will be sent from.
destination_address:
type: string
description: Destination address for the payment. This is the address that the payment will be sent to.
client_redirect_url:
type: string
format: uri
description: Optional URL to redirect users to after an onramp flow completes.
owner_chain:
type: string
description: Optional chain for the owner address, needed when the owner operates on a specific chain.
client_redirect_after:
type: string
enum:
- COMPLETED
- FUNDED
default: COMPLETED
description: When to redirect the user to the client_redirect_url. COMPLETED waits for the full payment to finish, FUNDED redirects after funding is confirmed.
- title: ContinueConfirmPaymentRequest
description: 'Continuation request after a USER_VERIFY instruction. Submit the signed verification
payloads to complete the confirmation process.
'
type: object
required:
- verification_token
- signatures
properties:
verification_token:
type: string
description: Opaque HMAC-signed token from the USER_VERIFY instruction. Pass back unmodified.
signatures:
type: array
description: User-signed payloads, one per verification entry from the USER_VERIFY instruction.
items:
type: object
required:
- reason
- signature_type
- signature
properties:
reason:
type: string
enum:
- EVM_OWNER
- EVM_WITHDRAWAL
description: Must match the reason from the corresponding verification entry.
signature_type:
type: string
enum:
- EIP712
description: Must match the signature_type from the corresponding verification entry.
signature:
type: string
description: The user's signature over the verification payload.
responses:
'200':
description: Payment confirmed successfully
content:
application/json:
schema:
$ref: '#/components/schemas/PaymentStatus'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Invalid state_token. The quote may have expired.
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Authentication failed. Invalid API key.
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Access denied. This payment belongs to a different account.
'404':
description: Payment not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Payment 'pay_xyz789' not found or has expired
/payments/withdraw:
post:
summary: Return funds to owner or retry payment
description: 'Request a withdrawal to return funds back to the owner or to a requoted processing address.
This endpoint should be used when a payment cannot be completed and funds need to be returned.
'
operationId: withdrawPayment
tags:
- Payments
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/WithdrawPaymentAuthorizationRequest'
responses:
'200':
description: Withdrawal initiated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/WithdrawPaymentAuthorizationResponse'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Missing field 'token_amounts'.
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Invalid or missing API key
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: You are not authorized to withdraw funds from this payment
'404':
description: Payment not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Payment 'pay_def456' not found
/payments/withdraw/confirm:
post:
summary: Confirm withdrawal request
description: 'Submit and execute the signed withdrawal request to return funds back to the owner or to a requoted processing address.
'
operationId: withdrawPaymentConfirm
tags:
- Payments
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/WithdrawPaymentRequest'
responses:
'200':
description: Withdrawal executed successfully
content:
application/json:
schema:
$ref: '#/components/schemas/WithdrawPaymentResponse'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Invalid request body
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Invalid API key
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: You are not authorized to withdraw funds from this payment
/payments/balances:
post:
summary: Get wallet balances
description: 'Retrieve balances for the wallets associated with a payment. You can optionally supply additional
wallet and token pairs to check alongside the payment''s primary wallet.
'
operationId: getPaymentBalances
tags:
- Payments
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RequestForPaymentBalances'
example:
payment_id: pay_abc123
custom_queries:
- address: '0xabc1234567890abcdef1234567890abcdef1234'
token: ethereum:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
- address: '0xdef1234567890abcdef1234567890abcdef5678'
token: arbitrum:0xfffFFFFFfFFfffFFfFffffFffFFfFFfFFfFFf
responses:
'200':
description: Wallet balances retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/PaymentBalancesResponse'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Invalid wallet address format
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Invalid API key
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: You do not have permission to query payment balances
'404':
description: Payment not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
errors:
- kind: other
message: Payment 'pay_abc123' not found
components:
schemas:
Token:
type: string
description: Token identifier in the format "chain:address"
pattern: ^[a-z]+:0x[a-fA-F0-9]+$
example: ethereum:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
ProviderIssue:
type: object
required:
- kind
- message
properties:
kind:
type: string
enum:
- provider
message:
type: string
Fees:
type: object
required:
- total_fees
- conversion_fees
- network_fees
- business_fees
- currency_symbol
properties:
total_fees:
type: string
description: Total fees amount
conversion_fees:
type: string
description: Ramps + bridge + DEX fees
network_fees:
type: string
description: Blockchain gas fees
business_fees:
type: string
description: Developer integration fees
currency_symbol:
type: string
pattern: ^[a-zA-Z]\w{1,7}$
description: Fiat currency symbol that the fees are denominated in (e.g., "USD")
example: USD
Amount:
type: string
description: A decimal amount string.
Limits:
type: object
properties:
min:
type: string
description: Minimum amount as a decimal string.
max:
type: string
description: Maximum amount as a decimal string.
GeolocationIssue:
type: object
required:
- kind
- message
properties:
kind:
type: string
enum:
- geolocation
message:
type: string
AmountIssue:
type: object
required:
- kind
- asset
- given
- limits
- source
- message
- reason
properties:
kind:
type: string
enum:
- amount
asset:
$ref: '#/components/schemas/Asset'
given:
$ref: '#/components/schemas/Amount'
limits:
$ref: '#/components/schemas/Limits'
downstream_limits:
$ref: '#/components/schemas/Limits'
source:
type: string
message:
type: string
reason:
type: string
enum:
- TOO_LOW
- TOO_HIGH
- NO_VALID_AMOUNT
- UNKNOWN
QuotedEntry:
type: object
required:
- fees
- output_amount
- route
properties:
output_amount:
$ref: '#/components/schemas/AssetAmount'
fees:
$ref: '#/components/schemas/Fees'
onramp:
type: string
description: Onramp provider name
onramp_method:
type: string
enum:
- CREDIT_CARD
- DEBIT_CARD
- ACH
- FIAT_BALANCE
- TOKEN_BALANCE
- APPLE_PAY
- PAYPAL
- VENMO
- REVOLUT
- GOOGLE_PAY
- SEPA
- FASTER_PAYMENTS
- PIX
- UPI
- WIRE
description: Payment method
example: CREDIT_CARD
route:
type: array
items:
$ref: '#/components/schemas/QuotedRouteItem'
description: Quoted workflow steps and their effects
PaymentStatus:
type: object
required:
- payment_id
- org_id
- status
- funded
- created_at
- updated_at
- initiate_fund_by
- quoted
- fulfilled
- current_prices
- price_currency
- processing_addresses
- owner_chain
- owner_address
- destination_address
- client_redirect_url
- declaration
properties:
payment_id:
type: string
org_id:
type: string
description: Organization identifier
status:
type: string
enum:
- PENDING
- COMPLETE
- FAILED
- EXPIRED
- WITHDRAW_PENDING
- WITHDRAWN
- TAINTED
- UNCONFIRMED
funded:
type: boolean
description: Whether the payment has been funded
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
initiate_fund_by:
type: string
format: date-time
description: Deadline for funding the payment.
completed_at:
type: string
format: date-time
quote_request:
$ref: '#/components/schemas/QuoteRequest'
description: The original quote request.
quoted:
$ref: '#/components/schemas/QuotedEntry'
fulfilled:
$ref: '#/components/schemas/FulfilledEntry'
current_prices:
type: object
additionalProperties:
type: string
description: Mapping of asset symbols to their unit prices
example:
USD: '1.00'
ethereum:0x: '4200'
ethereum:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48: '1.00'
price_currency:
$ref: '#/components/schemas/Asset'
description: Fiat asset used for pricing
customer_id:
type: string
description: ID of the customer who created the payment
label:
type: string
description: Optional payment label
maxLength: 255
processing_addresses:
type: array
items:
type: object
required:
- chain
- address
- factory
properties:
chain:
type: string
description: Blockchain network
example: ethereum
address:
type: string
description: Payment processing contract address
factory:
type: string
description: Factory contract address
owner_chain:
type: string
description: Chain identifier for the owner
owner_address:
type: string
description: Address of the owner of the payment
destination_address:
type: string
description: Address of the destination of the payment
next_instruction:
$ref: '#/components/schemas/NextInstruction'
nullable: true
issues:
type: array
items:
$ref: '#/components/schemas/Issue'
description: Payment validation issues
parent_payment_id:
type: string
format: uuid
description: Parent payment reference
client_redirect_url:
type: string
nullable: true
description: Client redirect URL
declaration:
type: object
nullable: true
description: Declaration object
Issue:
oneOf:
- $ref: '#/components/schemas/AmountIssue'
- $ref: '#/components/schemas/AmountDownstreamIssue'
- $ref: '#/components/schemas/FundingIssue'
- $ref: '#/components/schemas/OwnerIssue'
- $ref: '#/components/schemas/GeolocationIssue'
- $ref: '#/components/schemas/ProviderIssue'
- $ref: '#/components/schemas/PayinMethodIssue'
- $ref: '#/components/schemas/OtherIssue'
- $ref: '#/components/schemas/UnknownIssue'
discriminator:
propertyName: kind
Asset:
type: string
description: Identifier in the token format ("chain:address") or fiat currency code ("USD")
example: ethereum:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
PaymentBalancesResult:
type: object
required:
- address
- token
- account
- value
properties:
address:
type: string
description: Wallet address that was queried.
example: '0xabc1234567890abcdef1234567890abcdef1234'
token:
$ref: '#/components/schemas/Token'
description: Token identifier that was queried.
example: ethereum:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
account:
type: string
description: Account type for the balance.
enum:
- INTENT
- SPW
value:
oneOf:
- type: object
required:
- kind
- amount
- withdrawal_fee
properties:
kind:
type: string
# --- truncated at 32 KB (53 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/halliday/refs/heads/main/openapi/halliday-payments-api-openapi.yml