Prerequisites
- Payward Services API credentials (see Authentication Guide)
- A verified user with at least one account
Deposit addresses are issued by Payward and managed under
/v1/accounts/{account_id}/funds/deposits/addresses.
Withdrawals use user-added funding addresses managed under /v1/accounts/{account_id}/funds/addresses; register a
destination once and pass its address_id when creating a withdrawal.Deposits
Deposit workflow
1
List deposit methods
Query available deposit methods for the receiving account and asset.
GET /v1/accounts/{account_id}/funds/deposits/methods/{asset_symbol}2
Prepare the selected method
Fiat and crypto deposits use different preparation steps.
Fiat deposits
Bank transfer: If
activation_status is needed, request activation once.
If it is pending, wait and list the methods again. When it is completed, not_needed, or omitted,
retrieve the bank-transfer instructions. Display every returned field so the
user can make the transfer from their bank.Linked bank account: Methods with bank_link in requirements use a linked account instead of bank-transfer
instructions. Link the bank account or reuse an active link,
then create the deposit to request the funds. Linking alone does not move funds.Crypto deposits
Deposit address: List existing addresses and reuse a suitable one.
If none is available, claim an address. Display the address and any
required tag or memo so the user can send the deposit.Bitcoin Lightning: Create an invoice for the exact BTC amount instead of
claiming an address. The user must pay it before it expires.
3
Track the deposit
Reconcile deposits on the receiving account through
GET /v1/accounts/{account_id}/portfolio/transactions?types=deposit.The examples below use the signing helpers from the Authentication
Guide. For GET requests, sign the same ordered query
parameters that you send.
Bank-link deposit flow
Use Create deposit to pull funds from a linked bank account through a supported deposit method. Currently supported: Plaid US (USD). Discover methods for the receiving account and asset before initiating a deposit.- List deposit methods for the receiving account and asset. Select a supported method whose
requirementscontainsbank_link. - Complete the Bank links flow, or reuse an existing link. The account link must have
status: active, and its bank link must havestatus: linked. - Submit the method’s
idand the linked account’saccount_link_idtoPOST /v1/accounts/{account_id}/funds/deposits. Use the same receiving account throughout the flow.
202:
GET /v1/accounts/{account_id}/portfolio/transactions?types=deposit and match the returned reference to the transaction’s reference.id. The Portfolio transaction id is a separate identifier. Bank-link deposits return a reference.
Step 1: list deposit methods
Query available deposit methods for an asset. Use the method’sid as method_id when listing deposit destinations or claiming a crypto address.
Check requirements on the selected method:
[]: no additional requirements are reported. Follow the applicable activation and deposit-instructions steps.["bank_link"]: a linked bank account is required. If you do not already have a suitable link, use Create bank link with the returned methodidasmethod_id, then send the user through the hosted linking flow.
bank_link even when the user already has a linked account. Do not infer the requirement from the method name or supports_virtual_accounts.
Example USD method excerpts:
Most cryptocurrency deposits are free, with minimum deposit amounts varying by asset. A few cryptocurrencies are
charged an
address_setup_fee (a one-time fee on the user’s first deposit to a new address) or a per-deposit fee.page_token from next_page_token to request the next page. Omit it for the first page.
Response example
network, method when present, fee, minimum, activation_status, and
network_info.est_confirmation_time. Pass the method’s id back as method_id when activating a method, listing
deposit instructions, or claiming a crypto address. Optional fee, limit, and network fields are omitted when they do
not apply.
For fiat methods,
supports_virtual_accounts: true means Funding can provide dedicated virtual-account instructions.
false does not identify a particular alternative flow, and omission means Funding did not return deposit metadata
for the method. Use the deposit-instructions response, not this boolean, to determine which banking fields and payment
reference are available.Crypto assets can have a maximum of five deposit addresses. Some crypto funding methods share an address space, so the
same address can be returned for different assets or networks.
method_id selects a context in which the returned
address is valid; it does not say how the address was originally claimed. List and reuse an existing address before
claiming another.Step 2: activate a deposit method when required
If the selected method’sactivation_status is needed, request activation using its id as method_id. A 204
response means Funding accepted the request; it does not mean activation has necessarily completed, and it does not
contain deposit instructions.
completed. If it reports pending, wait and list the methods again later.
Activation returns
400 Bad Request when the selected account is missing verification information or documents
required by the funding method. The error is associated with account_id; when available, its message names the
missing requirement, such as address.Step 3: list deposit addresses
Retrieve the crypto addresses or fiat bank-transfer instructions available for the selected funding method. Reuse a returned crypto address instead of creating a new one each time.Response example
address_details variant:
crypto.addressis required for crypto destinations.crypto.tagandcrypto.memoare present only when the network requires them.- The
fiatobject contains only the banking fields that apply to the selected method. Fields such asiban,account_number,routing_number,sort_code,bic,swift,name_on_account, andreferenceare optional individually. Whenreferenceis present, include it with the fiat deposit. expire_timeis present only when the destination expires.
page_token from next_page_token to retrieve the next page.
Completed deposits appear in
GET /v1/accounts/{account_id}/portfolio/transactions?types=deposit. Portfolio
visibility is asynchronous.Step 4: claim a crypto deposit address
If Step 3 returns no suitable crypto address, claim one using the methodid from Step 1 as method_id. Fiat deposit
methods return their instructions from Step 3 and cannot be claimed with this operation.
You can claim a maximum of five deposit addresses per asset. List the account’s existing addresses before claiming
another one.
Some networks (e.g., XRP, XLM) require a tag or memo in addition to the address. If
tag or memo is present in the
response, your UI must display it and instruct the user to include it when sending funds. Deposits sent without the
required tag/memo may be lost.Bitcoin Lightning invoice flow
For the Bitcoin Lightning deposit method, create a BOLT11 invoice for the exact BTC amount the user intends to deposit. Use the limits from the deposit-methods response to validate the amount before requesting the invoice. The selectedaccount_id is the account that receives the completed deposit.
Reusable-address UI flow
Best practices
- Always display tag/memo: For networks that require a tag or memo (XRP, XLM, etc.), prominently display it alongside the address. Missing tags/memos can result in lost funds.
- Set expectations: Show
minimumamounts andest_confirmation_timefrom the methods response so users know what to expect before sending funds. - Use fresh responses: Available methods, addresses and limits are user-specific and may change based on account standing, remaining limits, or regional regulations. Fetch fresh data before displaying options rather than relying on cached results.
Deposit webhook events
Register a webhook throughPOST /v1/webhooks and subscribe to the deposit lifecycle events your integration needs:
All deposit lifecycle events contain
type, transaction_id, user_id, and account_id. They can also contain
amount and fee:
amount is the total deposit amount, inclusive of the fee. PWS includes it when both the source value and its asset can
be resolved.
fee is optional. PWS includes it only when the source provides both the fee value and its asset and the asset can be
resolved. This includes an explicitly provided zero fee. If the fee or its asset is unavailable, PWS omits fee rather
than assuming that it is zero or that it uses the deposit amount’s asset.
The availability of amount and fee is independent of the lifecycle event type. Treat absent fields as unavailable;
PWS does not return them as null.
Returned and failed deposits also contain a required reason field. PWS normalizes it to one of
account_details_mismatch, limit_exceeded, duplicate, account_restricted, or other. Other deposit lifecycle
events do not contain reason.
A deposit can produce multiple lifecycle events as it progresses. Treat each webhook as a notification and use the
Portfolio Transactions endpoint for reconciliation. Deliveries can be repeated, so use the svix-id header as the
deduplication key and return a 2xx response after accepting the event.
These events describe the lifecycle of a deposit. They are distinct from conversion.deposit_* events, which describe
the inbound funding leg of a conversion.
Crypto withdrawals
Create a normal crypto withdrawal to a saved funding address. Funding calculates the fee and validates the method, network, destination, limits, activation, account state, and Travel Rule requirements. Quote the fee first when you need to show it to a user before they commit.Withdrawal workflow
1
List withdrawal methods
Choose a method or network and inspect its required
address_fields.GET /v1/accounts/{account_id}/funds/withdrawals/methods/{asset_symbol}2
Check withdrawal limits
Retrieve the current maximum and rolling limits for each available method.
GET /v1/accounts/{account_id}/funds/withdrawals/limits/{asset_symbol}3
Select a funding address
List and reuse a compatible
address_id. Register a destination first when no suitable address exists.GET /v1/accounts/{account_id}/funds/addressesPOST /v1/accounts/{account_id}/funds/addresses4
Quote the withdrawal fee before you display it
Get the fee for a gross
amount, plus the short-lived fee_token you carry into the next step.POST /v1/accounts/{account_id}/funds/fees5
Create the withdrawal
Submit the selected scope, saved
address_id, public asset symbol, and gross amount.POST /v1/accounts/{account_id}/funds/withdrawals6
Handle address-ownership verification
If the request returns
withdrawal_verification_required, complete a supported Travel Rule verification method.7
Reconcile through Portfolio
Use the returned
withdrawal_id as reference.id with reference.kind=funding.Step 1: list withdrawal methods
Use each method’sid as scope.method_id, or its network_id as scope.network_id. Network scope succeeds only when
Funding can resolve exactly one eligible method for the requested asset. Otherwise, retry with a specific method ID.
fee and minimum are informational and can change before submission. To get fee terms for a specific amount that you
can carry into withdrawal creation, quote them in Step 4.
Step 2: check withdrawal limits
Retrieve the account-specific limits for the asset after choosing a method. Use only entries whosemethod_id appears
in the withdrawal-methods response for the same account and asset.
Compare your intended amount against maximum_amount, and check period_limits too: count-based limits do not reduce
maximum_amount, so a withdrawal can still be rejected when maximum_amount looks sufficient. All values are
point-in-time and can change before submission.
See List withdrawal limits for the full field reference.
Step 3: select or create a funding address
List the account’s funding addresses and reuse a compatible destination. Register a new address only when no suitable address exists.List existing funding addresses
The first request can includepage_size. To continue, send the returned page_token and the same method_id when
filtering. Omit page_size; the token preserves it. The token is bound to the selected account and method filter.
Pass method_id to filter by that method’s scope; omitting it returns every funding address on the account. Because
scopes nest (method → network → network group), a matching address may be registered more broadly and report a
network_id or network_group_id in scope instead of the method_id you filtered on. An empty method_id is
rejected as a validation error, not treated as no filter.
Create a funding address
Set exactly one scope:- Use
method_idwhen the destination should be registered for one withdrawal method. - Use
network_idwhen the destination should be valid for methods on that network.
address_fields in the withdrawal-method
response. Do not add local address-validation rules.
200:
name must be unique per account and is limited to 64 characters.
A create request can return these 409 codes:
Address limits vary by account and scope and are not exposed by this API. Reuse an existing address or contact support
when the limit is reached.
Get, rename, or delete a funding address
Use the stableaddress_id in the member path:
GET /v1/accounts/{account_id}/funds/addresses/{address_id}returns the saved scope, name, and address details.PATCH /v1/accounts/{account_id}/funds/addresses/{address_id}renames the address and returns204.DELETE /v1/accounts/{account_id}/funds/addresses/{address_id}deletes the address and returns204.
404 when the address is absent or unavailable to the selected account. Update can return 403
when the caller is not allowed to change the address. Always enforce account-to-address ownership in your integration.
Step 4: quote the withdrawal fee before you display it
Quote the fee for the gross amount you intend to withdraw. Use a methodid from Step 1 as method_id. Fiat methods
succeed but omit fee_token, since their fees don’t change between quote and withdrawal. Skip this step when you do
not need to show a fee before submitting.
amount is the gross amount, inclusive of the fee.
201:
net_amount is what reaches the destination, and for same-asset crypto fees net_amount + fee equals gross_amount.
Each request returns a new quote and moves no funds.
Pass fee_token to Step 5 to reuse this quote’s fee terms. Treat the token as opaque and sensitive: do not parse or
modify it, do not log it, and do not reuse it across users or accounts.
The quote checks the method and the amount only. Funding still checks balance, method minimums, address compatibility,
and Travel Rule requirements when you create the withdrawal.
Step 5: create the withdrawal
amount is the gross amount debited from the account, inclusive of the fee. For same-asset crypto fees,
net_amount + fee equals gross_amount.
To reuse the fee terms from Step 4, send its fee_token and set scope.method_id to the id of the method you quoted.
Fee tokens cannot be used with network scope. Omit fee_token to have Funding calculate the fee when the withdrawal is
created.
Funding recalculates the absolute fee from the token’s pinned terms and this request’s amount. Submit the same amount
as the quote to reproduce the fee you displayed.
A 400 on fee_token means no withdrawal was created. Request a new quote and resubmit with its token. Do not resend
a rejected token.
201:
Address-ownership verification
When the response is409 withdrawal_verification_required, read verification_methods. Funding can return
self_attestation, satoshi_test, or digital_signature. The PWS Travel Rule verification endpoint currently accepts
self_attestation from this list. Complete it through POST /v1/users/{user_id}/travel-rule/verifications, then submit a
new withdrawal request. Contact support when the response does not include a method that the endpoint supports.
Reconcile the withdrawal
ListGET /v1/accounts/{account_id}/portfolio/transactions?types=withdrawal. Match the transaction whose
reference.kind is funding and whose reference.id equals the returned withdrawal_id.
Portfolio is the canonical status and history surface. Do not wait for a withdrawal lifecycle webhook; this API does not
publish one.
Withdrawal best practices
- Reuse saved addresses: List funding addresses before creating another destination.
- Use the exact scope: Prefer
method_idwhen multiple methods exist on the same network. - Quote the fee before you display it: Method-list fees are estimates. Quote the fee for the amount you intend to
withdraw, then send that quote’s
fee_tokenwith the same amount. - Reuse idempotency keys for retries: Generate a UUIDv4 key before creating a withdrawal. Reuse it after an unknown outcome. If you omit the header, reconcile through Portfolio before submitting another withdrawal.
- Protect routing fields: Preserve required tags and memos, and do not log complete destination details.