Fix common Whop API, OAuth, checkout, webhook, and embedded element errors.
When something breaks, figure out what’s failing, check you’re hitting the right environment, and look at the error response. Most issues come down to: wrong credential, sandbox/production mismatch, missing permission, or a webhook handler that isn’t responding correctly.
Some OAuth endpoints return the OAuth-standard error and error_description fields instead. See OAuth errors for those cases.
Status
Meaning
What to do
400
The request is malformed or missing a required field.
Check required parameters, enum values, IDs, and nested object shape.
401
The request is missing valid authentication.
Confirm the API key or access token is present, valid, and sent from your server.
403
The credential is valid but cannot perform the action.
Check app permissions, OAuth scopes, company ownership, and connected-account context.
404
The resource or endpoint was not found.
Confirm the route, API version, and Whop tag ID such as biz_, plan_, mem_, or user_.
409
The request conflicts with the current resource state.
Fetch the latest resource state and retry only if the action still applies.
422
The request is valid JSON but fails validation.
Show the validation message to the user so they can fix their input.
429
Too many requests were sent in a short window.
For /api/v1 requests, authenticated API calls are limited to 600 requests per minute per operation and API credential. Back off until the retry window in the error message has passed.
5xx
Whop could not complete the request.
Retry with backoff for idempotent operations, then contact support if it persists.
For /api/v1 requests, Whop tracks request volume per API operation and API credential. The default limit is 600 requests per minute.When the limit is exceeded, the API returns 429 with:
{ "error": { "type": "rate_limit_exceeded", "message": "Try again in 12 seconds." }}
Wait for the delay in the message before retrying. For idempotent requests, retry with exponential backoff. Do not retry validation, authentication, or permission errors without changing the request.
Use the credential that matches where the code runs.
Credential
Use it when
Common mistake
Company API key
Your server acts for your own company.
Putting the key in browser, mobile, or public client code.
App API key
Your app server acts for companies that installed your app.
Calling endpoints for a company that has not installed or authorized the app.
OAuth access token
A signed-in user grants your app access to their account.
Treating a user-scoped token like a company-wide API key.
iframe user token
A Whop app verifies the user inside an iframe request.
Skipping verifyUserToken or forwarding the token to unrelated clients.
If an API request fails:
Confirm the base URL matches the key: use https://api.whop.com/api/v1 for production keys and https://sandbox-api.whop.com/api/v1 for sandbox keys.
Confirm IDs use Whop tag prefixes like biz_, user_, mem_, plan_, prod_, app_, pay_, or ch_, not internal numeric IDs.
Log the HTTP status, response body, endpoint, and request ID if one is returned.
Retry only when the error is transient or rate-limited. Do not retry 401, 403, or validation errors without changing the request.
Never expose Company API keys or App API keys in client-side code. Browser, mobile, and iframe code should call your server, and your server should call Whop.
Embedded checkout and iOS checkout can fail for different reasons, but you debug them the same way: check the plan or checkout configuration, inspect the callback, and confirm fulfillment on your server.
Handle expected failures separately from unexpected failures:
do { let result = try await checkout.purchase(planId) print("Receipt ID: \(result.receiptId)")} catch WhopCheckoutError.notConfigured { // SDK was not set up. Call WhopCheckout.configure() first.} catch WhopCheckoutError.cancelled { // The user dismissed checkout. This is not a payment failure.} catch WhopCheckoutError.paymentFailed(let message) { showError(message)} catch { showError("Something went wrong. Please try again.")}
SDK elements such as VerifyElement and ResetAccountElement emit error when initialization or operation fails.Always attach an error handler while developing: