Skip to main content
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.

Quick triage

API request errors

Whop returns standard HTTP status codes. When a request fails, the response body tells you why. Most errors include a code and a message:
Some OAuth endpoints return the OAuth-standard error and error_description fields instead. See OAuth errors for those cases.

Rate limits

For /api/v1 requests, Whop tracks request volume per API operation and API credential. The default limit is 600 requests per minute. When you exceed the limit, the API returns 429 with:
Wait for the delay in the message before retrying. For idempotent requests, retry with exponential backoff. Don’t retry validation, authentication, or permission errors without changing the request.

API authentication

Use the credential that matches where the code runs. If an API request fails:
  1. Confirm the environment matches the key: the SDK’s Production environment (the default) for production keys and Sandbox for sandbox keys, or https://api.whop.com/api/v1 and https://sandbox-api.whop.com/api/v1 when you call the API directly.
  2. Confirm IDs use Whop tag prefixes like biz_, user_, mem_, plan_, prod_, app_, pay_, or ch_, not internal numeric IDs.
  3. Log the HTTP status, response body, endpoint, and request ID if Whop returns one.
  4. Retry only when the error is transient or rate-limited. Don’t retry 401, 403, or validation errors without changing the request.
Never expose Account 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.

Permissions and scopes

403 and insufficient_scope errors usually mean the credential is valid but can’t perform that action.
  • For Whop apps, confirm the app requests the required permissions in Permissions, then save the app settings and reinstall or reauthorize when needed.
  • For OAuth, request only the scopes your feature needs, then make sure the user completed the OAuth flow after you added those scopes.
  • For dashboard-created API keys, confirm the key belongs to the account whose ID you pass (company_id or account_id, depending on the endpoint).
  • For connected accounts, confirm whether the parent or child account should own the action before choosing the account you pass.

OAuth errors

OAuth errors return a standard payload or redirect query string with error and error_description.
Redirect URIs must match exactly. If you configured https://example.com/oauth/callback, https://example.com/oauth/callback/ is a different URI.

Checkout errors

The Checkout element and iOS checkout can fail for different reasons. Debug them the same way: check the variant or checkout configuration, inspect the error callback, and confirm fulfillment on your server.

Checkout element

  • Attach onError. It runs when the element fails to load or crashes, with a message and a code for programmatic handling.
  • If you pass the compatibility property plan, confirm the variant exists, is active, and belongs to the account you expect.
  • If you pass checkoutConfiguration, confirm your server created it and that you passed its ch_ ID.
  • Every option is set at creation. To change the order, mount a new checkout instead of calling update().
  • A failed payment reopens the same checkout with the reason shown, so the buyer can pay again without a remount.
  • Provide a returnUrl on a route that can render success and retry states. An off-site step such as 3DS or a bank page returns the buyer there.
  • Use webhooks for fulfillment. The redirect is useful for UI, but your server should rely on payment.succeeded.

iOS checkout

Handle expected and unexpected failures with different paths:

Webhook delivery

verifyUserToken isn’t available in the current @whop/sdk. Guidance on this page that names it stays for reference.
Common webhook issues:
  • No event received: confirm the webhook URL is publicly reachable, uses https, and belongs to the right account and environment.
  • Signature verification fails: pass the raw request body to unwrapWebhook. Don’t parse JSON before verification.
  • Retries keep happening: return a 2xx response quickly after verification, before starting long-running work in a background job.
  • Duplicate fulfillment: Whop delivers webhooks at least once. Store webhook-id or another event identifier and make the handler idempotent.
  • Unexpected order: don’t assume events arrive in chronological order. Fetch the current resource state when ordering matters.
For local development, forward a public URL to your machine with a tunnel and use that URL in the dashboard webhook settings.

Element errors

Every Whop Element accepts an onError callback. It runs when the element fails to load or crashes, and the value carries a message, an optional code for programmatic handling, and a sourceKey when a host-state source failed. Always attach it while developing:
If an element fails to load:
  1. Confirm the access token was minted for the account you expect and carries the scopes the element’s reference page lists.
  2. On your own domain, always pass an accessToken. The viewer’s session only works on whop.com.
  3. Confirm the container exists before calling mount. React components mount themselves.
  4. Listen for onReady so you know whether the element initialized.
  5. If the element enters an unrecoverable state, call destroy() and create a new one.
The Elements troubleshooting table lists the common symptoms and their causes.

Sandbox and production

Sandbox data and production data are separate. When switching from sandbox to production:
  • Create new production API keys.
  • Switch the SDK environment from Sandbox to Production, or remove a 1.x baseUrl / base_url / WithBaseURL sandbox override.
  • Recreate sandbox-only products, checkout links, webhooks, and connected-account records in production.
  • Confirm webhook URLs point to production infrastructure, not a local tunnel.

What to include when asking for help

Include as much of the following as you can:
  • The endpoint, SDK method, or element name that failed.
  • The environment: sandbox or production.
  • The status code, error body, OAuth error_description, or element onError value.
  • The Whop IDs involved, with secrets removed.
  • The webhook event ID or webhook-id header for webhook issues.
  • A short code snippet showing how you create the client, checkout, OAuth URL, webhook handler, or element.

OAuth

Build the OAuth 2.1 + PKCE flow and handle token refresh.

Webhooks

Verify signatures before processing events, and handle retries.

Permissions

Choose app permissions and explain them to creators.

Test in sandbox

Test API calls and checkout flows without touching production.