Transaction Limits
Introduction
Transaction Limits provides a unified framework that allows Platforms to define and enforce configurable limits on an individual customer’s transaction activity. These limits can be applied across flexible time intervals (ie, daily, weekly, monthly) and tailored to the platform’s specific requirements, ensuring consistent, centralized, and compliant control over per-customer transactions.
You must be configured to use this feature by the zerohash team - please reach out if you are interested in enabling.
Roles
| Party | Role |
|---|---|
| Platform | Communicate default limits to zerohash pre-go live |
| zerohash | Set the default limit configuration |
| Platform | Override pre-configured limits |
| zerohash | Maintain and enforce the limits based on transaction activity |
Use Cases
Account Funding
Platforms that use the Account Funding SDK or API can use the Transaction Limits feature to programmatically and definitively prevent users funding more than the defined limit.
End to end example - Happy Path
Default, per-customer limit is defined
Platforms should work with their zerohash relationship manager to establish default transaction limits that apply to all customers. zerohash can quickly make this configuration on our end.
Query limits
Once default transaction limits have been defined, Platforms can fetch the limits using the GET /participants/{participant_code}/limits endpoint. Platforms should use this endpoint to ensure limits displayed on their UI are aligned with limits set with zerohash.
- where
"period" = 24, thelimitwill reset to the correspondingconfigured_limitevery day. - where
"period" = 720, thelimitwill reset to the correspondingconfigured_limitevery month.
Sample Response
{
"participant_code": "CUST01",
"limits": [
{
"type": [
"trades"
],
"period": 24, // 24 hours: 1 day
"configured_limit": "25000", // static value based on defined per-transaction limit
"limit": "25000", // this is a dynamic value that adjusts as activity occurs
"asset": "USD"
},
{
"type": [
"trades"
],
"period": 720, // 720 hours: 30 days
"configured_limit": "100000", // static value based on defined per-customer limit
"limit":"100000", // this is a dynamic value that adjusts as activity occurs
"asset": "USD"
}
]
}
Platform invokes the Account Funding SDK + the Customer makes a deposit
The Account Funding SDK is invoked with the POST /client_auth_token endpoint. The SDK will display transaction limits associated with the participant_code :
Once zerohash has received a deposit from the Customer, a webhook will be returned to the Platform.
Sample Success Webhook
{
"participant_code": "CUST01",
"fund_asset": "USDC.ETH",
"rate": "1",
"quoted_currency": "USD",
"source_address": "0x3A45a60c62EE6cD616B1C4510404Eba88116044I",
"deposit_address": "0x34f53Aea3ba8b60B0ed19106baF43A4f3F73f248",
"quantity": "5000",
"notional": "5000",
"fund_id": "5155f7c9-95cb-4556-ab89-c178943a7111",
"fund_timestamp": 1750404905186631445,
"deposit_timestamp": 1750404905037719568,
"transaction_id": "a07407e8f98c21b037b4aa0cbc852b8489c5e122fcc3d4b33b7827d0605ad8ff",
"account_label": "general",
"success": true,
"reference_id": "d098e59b-8023-4477-8b63-68fda3c53a30",
"raw_fee_bps": "30",
"raw_fee_notional": "15.00",
"deposit_fee_bps": "30",
"deposit_fee_notional": "15.00"
}
At this point, the Platform can choose to query the Customer's limits via the GET /participant/{participant_code}/limits endpoint to view the current limits.
configured_limitwill remain unchanged, as it represents the pre-defined transaction limitlimitwill adjust based on the amount the Customer has deposited.
Sample Response
{
"participant_code": "CUST01",
"limits": [
{
"type": [
"trades"
],
"period": 24, // 24 hours: 1 day
"configured_limit": "25000", // static
"limit": "20000", // adjusted down
"asset": "USD" //
},
{
"type": [
"trades"
],
"period": 720, // 720 hours: 30 days
"configured_limit": "100000", //static
"limit": "95000", // adjusted down
"asset": "USD"
}
],
"as_of_timestamp": 123456789
}
Platform overrides the default limit
The Platform can choose to override the default limit by making a request to the PATCH /participants/limits endpoint. In this request, the Platform is looking to further adjust down the Customer's 24 hour and monthly limit by an additional $5,000. Example request:
{
"participant_code": "CUST01",
"limits": [
{
"type": [
"trades"
],
"period": 24, // 24 hours: 1 day
"configured_limit": "15000", // 5,000 less than currently set limit
"asset": "USD"
},
{
"type": [
"trades" // enum: trade
],
"period": 720, // 720 hours: 30 days
"configured_limit": "90000", // 5,000 less than currently set limit
"asset": "USD"
}
]
Sample response
{
"participant_code": "CUST01",
"limits": [
{
"type": [
"trades"
],
"period": 24, // 24 hours: 1 day
"configured_limit": "25000", // static
"limit": "15000", // adjusted down
"asset": "USD" //
},
{
"type": [
"trades"
],
"period": 720, // 720 hours: 30 days
"configured_limit": "100000", //static
"limit": "90000", // adjusted down
"asset": "USD"
}
],
"as_of_timestamp": 123456789
}
This new limit will now be reflected in the GET /participants/{participant_code}/limits endpoint and will also be displayed on the SDK.
Please note that if you choose to omit an already-existing limit, zerohash will remove that limit all-together. For example if the PATCH /participants/limits request looked like this (with the monthly limit omitted):
{
"participant_code": "CUST01", // Max Howenstine's code for all IBKR activity
"limits": [
{
"type": [
"trades"
],
"period": 24, // 24 hours: 1 day
"configured_limit": "15000", // 5,000 less than currently set limit
"asset": "USD"
}
{
]
Then the monthly limit is removed and will not be enforced.
End to end example - Customer's deposit exceeds their limit
If a customer makes a deposit that exceeds their configured_limit, we will partially convert the funds to fiat up to the configured_limit amount.
The un-converted amount that was deposited will be redirected to a fund_failure account_label.
If the Platform is configured for zerohash to send email receipts, there will be a customized email per this scenario that clearly explains what took place, with instructions on how to recover the un-converted stablecoins or crypto (via the self-serve Secondary Portal).
If the Platform is not configured for zerohash to send email receipts, the Platform can treat the below webook as a trigger to send an email or otherwise notify the Customer that the next step is to recover the funds from the zerohash Secondary Portal
Sample webhook where the user sends 20,000 USDC despite their current configured 24 hour limit being 15,000
{
"participant_code": "CUST01",
"fund_asset": "USDC.ETH",
"rate": "1",
"quoted_currency": "USD",
"source_address": "0x3A45a60c62EE6cD616B1C4510404Eba88116044I",
"deposit_address": "0x34f53Aea3ba8b60B0ed19106baF43A4f3F73f248",
"quantity": "20000",
"notional": "15000",
"fund_id": "5155f7c9-95cb-4556-ab89-c178943a7111",
"fund_timestamp": 1750404905186631445,
"deposit_timestamp": 1750404905037719568,
"transaction_id": "a07407e8f98c21b037b4aa0cbc852b8489c5e122fcc3d4b33b7827d0605ad8ff",
"account_label": "general",
"success": true,
"reason" : "the deposit was partially converted up to the configured limit. 15,000 was converted and now 5,000 USDC.ETH has been placed in the customer's fund_failure account.",
"reference_id": "d098e59b-8023-4477-8b63-68fda3c53a30",
"raw_fee_bps": "30",
"raw_fee_notional": "45.00",
"deposit_fee_bps": "30",
"deposit_fee_notional": "45.00"
}
Updated about 5 hours ago
