Guest Checkout users start with conservative spending limits. The Limits Upgrade API lets eligible users increase those limits permanently by verifying their identity with just two pieces of information — the last 4 digits of their SSN and their date of birth.
Limits Upgrade is only available for Guest Checkout (Headless Onramp) users. Authenticated Coinbase users have separate limit management through their Coinbase account.
Default and upgraded limits
Limit Default After upgrade Weekly spending $500 USD (rolling 7-day window) $2,500 USD Lifetime transactions 15 total purchases Unlimited
Once approved, the upgrade is permanent. Users never need to re-verify.
Integration flow
1. Check limits and upgrade eligibility
Call POST /v2/onramp/limits before or during the onramp flow to retrieve the user’s current limits and determine whether an upgrade is available.
cdpcurl -X POST 'https://api.cdp.coinbase.com/platform/v2/onramp/limits' \
-k ~/Downloads/cdp_api_key.json \
-d '{
"paymentMethodType": "GUEST_CHECKOUT_APPLE_PAY",
"userIdType": "phone_number",
"userId": "+14155551234"
}'
Both GUEST_CHECKOUT_APPLE_PAY and GUEST_CHECKOUT_GOOGLE_PAY are supported and yield identical limits.
Response — upgrade available:
{
"limits" : [
{ "limitType" : "weekly_spending" , "limit" : "500" , "remaining" : "400" , "currency" : "USD" },
{ "limitType" : "lifetime_transactions" , "limit" : "15" , "remaining" : "12" }
],
"limitUpgradeOptions" : [
{
"status" : "unrequested" ,
"fields" : [ "ssnLast4" , "dateOfBirth" ],
"limitUpgrades" : [
{ "limitType" : "weekly_spending" , "maxUpgrade" : "2500" },
{ "limitType" : "lifetime_transactions" , "maxUpgrade" : "-1" }
]
}
]
}
Response — upgrade not available:
{
"limits" : [
{ "limitType" : "weekly_spending" , "limit" : "500" , "remaining" : "500" , "currency" : "USD" },
{ "limitType" : "lifetime_transactions" , "limit" : "15" , "remaining" : "15" }
]
}
When limitUpgradeOptions is absent from the response, the user does not yet meet the eligibility criteria. This is not an error — limits is always present and accurate.
Upgrade status values
limitUpgradeOptions is a single-element array. Check limitUpgradeOptions[0].status to determine what to do next:
Status Meaning Action unrequestedUser has never submitted. fields lists what to collect. Show upgrade prompt and call /limits/upgrade. resubmitPrevious submission was rejected but can be retried. fields is populated. Show corrected-entry prompt and call /limits/upgrade again. pendingSubmission is under review by Coinbase. Show a “pending” state. Poll /limits until a terminal status appears. activeTerminal. Upgrade approved — user has higher limits. Show upgraded limits. No further action. inactiveTerminal. Upgrade permanently blocked. Do not retry. Do not show the upgrade prompt again.
Only show the upgrade prompt when limitUpgradeOptions is present and status is unrequested or resubmit.
2. Submit identity fields
When status is unrequested or resubmit, collect the required fields and submit them to POST /v2/onramp/limits/upgrade . The endpoint returns HTTP 202 immediately — processing is asynchronous.
cdpcurl -X POST 'https://api.cdp.coinbase.com/platform/v2/onramp/limits/upgrade' \
-k ~/Downloads/cdp_api_key.json \
-d '{
"userIdType": "phone_number",
"userId": "+14155551234",
"fields": {
"ssnLast4": "1234",
"dateOfBirth": {
"day": "15",
"month": "08",
"year": "1990"
}
}
}'
After receiving 202, re-poll /limits — the status immediately advances to pending.
Do not store ssnLast4 on your servers. Collect it, submit it, and discard it immediately.
Field validation
Field Requirements ssnLast4Exactly 4 numeric digits. No dashes, spaces, or letters. dateOfBirth.day2-digit zero-padded day string (e.g., "05", "15"). dateOfBirth.month2-digit zero-padded month string (e.g., "01", "08"). dateOfBirth.year4-digit year string (e.g., "1990").
Validate client-side before submitting to avoid unnecessary round trips. The API rejects invalid dates (e.g., February 30) and non-numeric SSN values.
3. Poll until terminal status
Poll POST /v2/onramp/limits after the 202 response until limitUpgradeOptions[0].status reaches a terminal state.
cdpcurl -X POST 'https://api.cdp.coinbase.com/platform/v2/onramp/limits' \
-k ~/Downloads/cdp_api_key.json \
-d '{
"paymentMethodType": "GUEST_CHECKOUT_APPLE_PAY",
"userIdType": "phone_number",
"userId": "+14155551234"
}'
Response when upgrade is approved:
{
"limits" : [
{ "limitType" : "weekly_spending" , "limit" : "2500" , "remaining" : "2500" , "currency" : "USD" },
{ "limitType" : "lifetime_transactions" , "limit" : "-1" , "remaining" : "-1" }
],
"limitUpgradeOptions" : [
{
"status" : "active" ,
"limitUpgrades" : [
{ "limitType" : "weekly_spending" , "maxUpgrade" : "2500" },
{ "limitType" : "lifetime_transactions" , "maxUpgrade" : "-1" }
]
}
]
}
A limit or remaining value of "-1" means unlimited. Display this to users as “Unlimited” rather than a raw number.
Polling guide:
Start polling immediately after receiving the 202 response
Poll every 1–2 seconds — verification typically completes within ~3 seconds
Set a timeout (e.g., 30 seconds) and show a “still processing” message if it expires
Stop polling once status is active, inactive, or resubmit
Resubmission and rate limits
If status returns to resubmit, Coinbase reviewed the submission and couldn’t verify the information. fields is re-populated — collect the corrected fields and call /limits/upgrade again. The flow is identical to the initial submission.
Users are limited to 5 upgrade submissions over a rolling 5-day window . A submission only counts when it enters Coinbase’s verification pipeline — meaning the status transitions to pending. Input validation errors, transient failures, and other non-verification errors do not count against this limit.
Calling /limits/upgrade when status is already pending or active is safe — the endpoint returns 202 and nothing changes.
UI recommendations
Status Suggested UI unrequested”Increase your weekly limit to $2,500 and unlock unlimited lifetime transactions.” pending”Your limit increase request is under review. You can still transact at your current limits.” resubmit”We couldn’t verify your information. Please check your SSN and date of birth and try again.” active”Your limits have been increased to $2,500/week with unlimited lifetime transactions.” inactive”Your account is not eligible for a limit increase at this time.”
For the inactive status, do not expose the underlying reason and do not show the upgrade prompt again.
Input field guidance:
SSN : Use a masked input (****). Validate exactly 4 numeric digits client-side.
Date of birth : Use a date picker or separate day/month/year fields. Validate that the date is a real calendar date.
Error reference
POST /v2/onramp/limits errors
HTTP Cause Resolution 400 Missing or invalid field Check errorMessage for the specific field. 401 Missing or invalid API key Verify your API key and JWT generation. 429 App-level rate limit exceeded Back off and retry with exponential backoff.
POST /v2/onramp/limits/upgrade errors
HTTP Message Cause Resolution 400 fields.ssnLast4 is requiredssnLast4 missing Include fields.ssnLast4. 400 ssnLast4 must be exactly 4 digitsWrong length Validate length client-side. 400 ssnLast4 must be numericNon-digit characters Strip dashes and spaces before submitting. 400 fields.dateOfBirth is requireddateOfBirth missing Include fields.dateOfBirth. 400 invalid dateOfBirthInvalid date Validate the date client-side. 400 account does not meet requirements for a limit upgradeApp not on allowlist or user ineligible Do not retry. Contact us if your app should be eligible. 400 limit upgrade is not available for this userUpgrade permanently blocked Do not retry. Do not show the upgrade prompt again. 401 unauthorizedMissing or invalid API key Verify your API key. 403 We couldn't verify your details. Please try again later.Identity verification failed Do not retry immediately. Wait for status to return to resubmit before prompting again. 429 rate_limit_exceededApp-level rate limit exceeded Back off and retry with exponential backoff.
Error response shape:
{
"errorType" : "invalid_request" ,
"errorMessage" : "InvalidRequest: ssnLast4 must be exactly 4 digits" ,
"errorLink" : "https://docs.cdp.coinbase.com/api-reference/v2/errors#invalid_request" ,
"correlationId" : "966fe3870ecf2368"
}
Include correlationId when contacting Coinbase support.
Sandbox testing
Use phone numbers prefixed with +0 to test all scenarios without real verification. Only the last digit determines the scenario.
POST /v2/onramp/limits sandbox responses
Phone number Status Limits +00000000000unrequestedBase ($500/week, 15 transactions) +00000000001pendingBase +00000000002resubmitBase +00000000003activeUpgraded ($2,500/week, unlimited transactions) +00000000004inactiveBase +00000000005— Dependency error (503) +00000000006— Rate limit exceeded (429) +00000000007— Invalid request (400) Any other +0 number unrequestedBase
POST /v2/onramp/limits/upgrade sandbox responses
Phone number Response +00000000000 to +00000000003202 Accepted +00000000004422 LimitsUpgradeBlocked +00000000005503 Dependency error +00000000006429 Rate limit exceeded +00000000007400 Invalid request Any other +0 number 202 Accepted
In sandbox, ssnLast4 and dateOfBirth values are not validated — pass any well-formed values.
POST /v2/onramp/limits Full API reference for checking user limits.
POST /v2/onramp/limits/upgrade Full API reference for submitting an upgrade request.