Skip to main content
The Current API is versioned with dates. Breaking changes ship only inside a new dated version that you opt into. Pin a version and the request and response shapes you built against never change. Official SDKs automatically send the version used to generate them.
If you don’t pass an Api-Version-Date or have a stored API-key pin, the stable API model is used. Requests with neither are served by the pre-versioning behavior, so existing integrations keep working unchanged. Pin a dated version to opt into the latest API.

API key version pins

API keys carry their own API version pin. Requests authenticated with an API key use that pin when they omit Api-Version-Date. Existing keys without a stored pin use 2025-01-01. Newly created keys use the latest released version. An explicit Api-Version-Date header always takes precedence over the API key’s pin, so you can test an upgrade before changing the saved version. Every version automatically gets new endpoints and optional fields. Breaking changes create a new dated version, which the changelog below lists.

Plans to variants migration

Products and Variants are the current commerce resources. Use /variants and the variants SDK namespace for new integrations. The former /plans endpoints remain callable during the migration and return Deprecation and successor Link headers. This first step doesn’t rename fields used by other resources. Variant IDs still begin with plan_, and compatibility fields such as plan_type and plan_id, plan:* permission scopes, and plan.* webhook event names keep their existing wire values until their own versioned migrations ship.

Social accounts to external accounts migration

Use /external_accounts and the externalAccounts SDK namespace for new integrations. The former /social_accounts endpoints remain callable during the migration and return Deprecation and successor Link headers. External account IDs keep the sacc_ prefix, and social_account:* permission scopes keep their existing wire values. When upgrading, review every entry after your current pin through your target version, not just entries from the target month. In particular, upgrading from 2026-07-20 to September crosses the 2026-07-23 members and memberships migration.

Changelog

The TypeScript SDK releases listed below use the API version in that entry by default. Overriding apiVersionDate changes the response version, but not the SDK types.
Latest
Apps no longer list previous hosted URLs
TypeScript SDK: @whop/sdk@2.4.0.Apps no longer include previous_hosted_urls. An app’s addresses are the domains that serve it: list them with GET /domains, or read domains on the app.
Transfer profiles, amounts, and creation types
Transfers return origin and destination profiles with name and logo_url. The amount and fee money objects contain the recipient credit and all transfer fees. Responses also include available failure timestamps and a tracking URL. Unknown historical money and transition times are null.Without account filters, GET /transfers lists transfers across the caller’s permitted accounts and personal wallet. Account-scoped credentials remain limited to their account.POST /transfers requires type, either balance or claim_link. Requests without it return 400. The ledger type is renamed balance, and wallet_send is removed. Earlier versions accept ledger and wallet_send, and create a balance transfer when type is left out.
Generate a payment's receipt PDF
Payments no longer include pdf_url. To get a payment’s receipt as a PDF, call POST /payments/{id}/generate_pdf. It returns a url to download the file and the expires_at when that link stops working.
Pending funds can be awaiting a compliance review
TypeScript SDK: @whop/sdk@2.3.0.An account’s payment_controls.undated_pending_reason can be compliance_review. It means a verification the merchant already submitted is under review, so pending funds stay pending until it clears. Callers pinned earlier see null for this state.
Economic Intelligence can renew every week
economic_intelligence_offers includes a weekly offer that renews every week until it’s turned off. Each offer has auto_renew, and weekly is the recommended offer. To turn it on, send economic_intelligence_duration_key: "weekly" to PATCH /accounts/{account_id}/preferences.economic_intelligence_offers lists only what the account can pick now. It’s no longer null while Economic Intelligence is on: during a committed period it lists only weekly, as an upgrade, and while weekly is renewing it’s empty. Earlier versions keep null while Economic Intelligence is on, leave out weekly, and recommend 1_day.
Saved-card payments are buyer-present by default
A saved payment method charge (member_id and payment_method_id) with a return_url now treats the buyer as present. This applies when you leave out off_session. If the issuer asks the buyer to authenticate, the payment is requires_action with a next_action. When you charge the card without the buyer, such as a renewal on your own schedule, pass off_session: true.
Bill pay recipients no longer need Whop accounts
Creating a payout method with recipient creates a non-default recipient payout account linked to the sender’s ledger. It creates no Whop user, company, or recipient ledger. The recipient response contains first_name, last_name, and country. It no longer contains user_id. Earlier API versions omit recipient details when there is no Whop user. Earlier versions retain the user ID for existing recipients.
App builds no longer take an AI prompt
Creating an app build no longer accepts ai_prompt_id.
A metric's time series has its own path
Retrieve a metric’s time series from GET /stats/time_series/{metric}. GET /stats/{metric} still serves it and names the successor in a Deprecation header.
Social accounts are external accounts
Social accounts are now external accounts. Use /external_accounts and the externalAccounts SDK namespace. The former /social_accounts endpoints still respond on every version, with Deprecation and successor Link headers. External account IDs keep their sacc_ prefix, and the social_account:* permission scopes are unchanged.Ads name their accounts external_accounts instead of social_accounts in both requests and responses. Audience engagement rules name their account external_account_id instead of social_account_id. On /external_accounts, an Instagram account’s owning page is parent_external_account instead of parent_social_account. Ad webhooks without a pinned API version receive external_accounts.
Users no longer include social accounts
Users no longer return social_accounts.
Setup intents are saved in the background
Creating a setup intent now returns it as processing and saves the payment method in the background. Creating a payment already works this way. To learn the outcome, poll the setup intent or pass its client_secret to handleNextAction. It ends up saved, refused, or waiting on a step from the buyer. Earlier versions keep saving it during the request.
Prevented disputes report prevented
TypeScript SDK: @whop/sdk@2.1.0, @whop/sdk@2.2.0.A dispute the customer was refunded for before any ruling now has status: prevented instead of closed. The refund came from the card network (Visa RDR) or an earlier refund.
Economic Intelligence runs have their own statuses
A recommendation Whop AI is carrying out has status: running. When the run ends it becomes executed, or incomplete if it ended without carrying the recommendation out. Earlier versions show a running recommendation as ready and an incomplete one as superseded.Recommendations also return run_started_at, run_ended_at, run_by_user_id, result_url, and acknowledged_at. To run a recommendation yourself, send status: running to PATCH /economic_intelligence/{id}, then status: executed (with an optional result_url) or status: incomplete. Send status: acknowledged to mark an executed run as seen. The recommendation stays executed and records acknowledged_at.
Economic Intelligence durations are chosen by key
To turn on Economic Intelligence, send economic_intelligence_duration_key to PATCH /accounts/{account_id}/preferences instead of economic_intelligence_duration_days. Use the key of an entry in economic_intelligence_offers.Each entry in economic_intelligence_offers has key, duration, and duration_unit instead of duration_days. A duration can be counted in hours or days.
Ads copy is language-tagged, and Meta ads can run in other languages
An ad’s primary_texts, headlines, and descriptions are arrays of { language, text } objects on requests and responses. On an ad without translations, leave language out. The API rejects plain strings, so send [{ "text": "…" }] instead.A Meta ad can also run in other languages. Set translations: { source_language, automatic_languages } to the language of the ad’s own copy and the languages Meta translates into automatically. Every copy and creatives entry on that ad then names its language. The ad’s own copy and creative use source_language, and each language you write yourself gets a primary_texts and a headlines entry, plus optional descriptions and creatives entries. translations: null turns the other languages off.Earlier API versions can’t update an ad that has translations. They get a 400 that names this version.
Economic Intelligence turns on for a chosen duration
To turn on Economic Intelligence, send economic_intelligence_duration_days to PATCH /accounts/{account_id}/preferences. Pick a duration from economic_intelligence_offers, which lists each duration’s fee. Economic Intelligence can’t be changed or turned off until economic_intelligence_ends_at, and it turns off automatically then. It can’t be turned on during a free trial, and economic_intelligence_offers is null until the trial ends.economic_intelligence is read-only. Sending it returns a 400 error.
Trading access appears in permission checks
TypeScript SDK: @whop/sdk@2.0.0.GET /permissions includes crypto_wallet:trade and crypto_wallet:trade:read when listing or checking permission actions for an account.
Economic Intelligence operation descriptions
Economic Intelligence recommendations return expected_tool_calls as an ordered array of objects with tool_name and description. Descriptions identify the planned action and affected resource. Older recommendations have a null description.
Partner referral links use one request type
Partner referral requests use request_type: "link" for links with or without rewards. Use link when creating or filtering links. Only authorized staff can configure rewards.
Account rewards show partner reward progress
Retrieve Account returns partner reward milestones in rewards. Each milestone includes qualification progress and payout status for that account. The field contains an empty array when there are no matching rewards or the caller lacks balance or stats read access.The legacy onboarding reward format is retired. Earlier API versions omit rewards from account responses.
Setup intents become a native resource
The native Payments API now serves POST /setup_intents, GET /setup_intents, and GET /setup_intents/{id}. The Setup Intent object takes the shape of every other native resource.
  • Related records are foreign-key ids instead of embedded objects: account_id (was company), member_id (was member), payment_method_id (was payment_method), and checkout_configuration_id (was checkout_configuration). The buyer is a user summary (id, username, name, profile_picture).
  • error_message moves into last_setup_error, the same { code, message } block Retrieve setup status returns. It stays null until something fails, and drops once the setup succeeds.
  • return_url, payment_method_type, and updated_at are new. created_at and updated_at are ISO 8601 timestamps.
  • payment_instrument, the display-shaped method the Payment object already carries, is on the Setup Intent too, so a saved card renders without a second request. Its card gains exp_month and exp_year on both resources. card.brand can be null: a saved card whose network the vault didn’t record keeps its last four and expiry instead of losing the whole card object.
  • Creating a setup intent answers 201 Created (was 200), honors Idempotency-Key, and requires exactly one of confirmation_token or payment_method_id. A confirmation token from another account is a 404.
  • client_secret comes back on create and retrieve, and only for setups created through this API. It requires a caller who may act on the setup: the account’s payment:charge credential or the buyer’s own token. List rows always carry null.
  • setup_intent.requires_action, setup_intent.succeeded, and setup_intent.canceled webhooks pinned at or after this version deliver this same Setup Intent object as their data. Webhooks pinned earlier, and webhooks without a pin, keep the previous payload.
  • GET /setup_intents lists with the standard { data, page_info } envelope and cursor pagination. account_id is optional: an account API key lists its own account, and a user token lists every account it can read. status is a new filter, and an invalid value is a 400. created_before and created_after work as before.
Ads payment retries use the account endpoint
POST /ad_campaigns/{id}/retry_payment returns 410 Gone. Use POST /accounts/{id}/retry_ads_payment with the account’s biz_ ID to queue one payment retry for all its campaigns. An accepted retry doesn’t confirm payment success. Check campaign delivery_status and issues for the outcome.
Three distinct 3D Secure policies
TypeScript SDK: @whop/sdk@1.1.5.Accounts, variants, checkout configurations, and checkout sessions expose three 3D Secure choices:
  • mandate_challenge requests a challenge before processing a supported on-session card payment.
  • mandate_if_required mandates a challenge only when the payment processor requires it.
  • frictionless_if_required uses the regular frictionless 3DS flow.
Payments of $1,000 or more use at least mandate_if_required. Risk and authentication recovery requirements can override the preference. Explicit mandatory challenges are rejected until enabled on the platform.Older API versions keep their existing values: new mandate_challenge selections remain conditional, existing mandatory preferences are preserved, and frictionless remains frictionless. Accounts on older versions represent frictionless as null.
Trading transfers have distinct financial-report categories
Financial-report rows distinguish trading_account_deposit, trading_account_withdrawal, and their _offset entries from other on-chain transfers. Amounts and balances are unchanged.Earlier versions keep the existing categories: topup for account deposits and onchain_withdrawal for account withdrawals. Global reports use the corresponding onchain_deposit, onchain_withdrawal, and _offset categories. Matching rows are combined without dropping transferred amounts.
Triple Whale status renamed for white-label merchants
Account preferences ads_triple_whale_integration.status reports requires_shop_domain instead of requires_shopify_store. A shop_domain can now be set explicitly on the integration, so a connected Shopify store is no longer the only way to supply one.
Business categories come from one table
TypeScript SDK: @whop/sdk@1.1.4.Account business_type, industry_group, and industry_type are strings drawn from Whop’s business categories table instead of fixed enums. New categories appear without a new API version. The business types and industries glossary lists the current values.
  • coaching_and_courses is now education, physical_product is now ecommerce, and marketplace is now platform.
  • Industry groups and types were reorganized under the eight business types. PATCH /accounts/{id} accepts glossary slugs only. Unknown values return 400.
Pinned callers on an earlier version still receive the previous business type names, and industry values that didn’t exist before this version are returned as null.
Account-owned experiments
Experiments accept an owning account_id (biz_… or internal), optional resource references, and account-local flag keys. Creation requires explicit ownership. Evaluation identifies the subject through subject[account_id], subject[anonymous_id], and subject[user_id].Older versions retain internal experiment scope and their existing evaluation identity parameters. Reading and managing account experiments requires account permissions. Exposure accepts optional credentials and records their identity on the event. Account experiments don’t provision a reporting provider. Listing selects one account. Omitting account_id lists internal experiments after the internal access check. Team tags remain private and aren’t supported for account experiments.Evaluation accepts targeting properties as a JSON query value. Existing nested property query keys remain supported.
Named Whop withdrawal holds on pending funds
TypeScript SDK: @whop/sdk@1.1.3.Account payment_controls.undated_pending_reason can be withdrawals_disabled when Whop has blocked withdrawals, so those pending funds can’t become available.kyc_incomplete, pending_information_request, and null for funds that are still clearing are unchanged.
Engagement audience sources
POST /audiences supports engagement with videos, lead forms, Instagram profiles, and Facebook pages through a typed engagement definition.
  • Explicit source_type values validate that the required source fields are present and conflicting source fields are absent.
  • Audience responses include engagement, and source_type can be engagement. Engagement audiences can also be used as lookalike sources.
  • GET /social_accounts/{id}/posts includes video_id and caption to help select videos without manually finding their platform identifiers.
Ending an experiment requires findings
POST /experiments/{id}/end requires findings in the request body — a short explanation of what was learned and why the experiment ended the way it did.Pinned callers on an earlier version may still omit it. A placeholder findings value is recorded on their behalf instead of a 400.
Deposit destinations are an account ID
TypeScript SDK: @whop/sdk@1.1.1, @whop/sdk@1.1.2.POST /deposits takes a destination account ID string — biz_… or user_… — and nothing else.
  • Raw wallet addresses are no longer accepted. Fund an account and read its addresses from methods.crypto.
  • The object form of destination ({ account_id } / { address, network }) is removed. Send the account ID on its own.
  • The top-level network override is removed. It never changed the response: every deposit already returns an address for every supported network, so pick the one you want from methods.crypto.
  • metadata is removed from both the request and the response. It was echoed back and never stored, so it couldn’t be used to reconcile a later deposit.
  • account_id on the response is no longer null, because every destination now names an account.
Pinned callers on an earlier version keep sending the object form and the removed inputs, and their responses still carry metadata — as an empty object rather than the value they sent. A wallet address is refused at every version: it never identified an account, so there is no older shape to keep serving.
Payments become a native resource
TypeScript SDK: @whop/sdk@1.1.0.POST /payments, GET /payments and GET /payments/{id} are now served by the native Payments API, and the Payment object takes the shape of every other native resource.
  • Related records are foreign-key ids instead of embedded objects: account_id (was company), plan_id, product_id, membership_id, member_id, promo_code_id, shipment_id, payment_method_id. The buyer is a user summary (id, username, name, profile_picture).
  • Amounts are money objects ({ amount, currency, decimals, display_decimals }) instead of bare numbers: total, subtotal, tax_amount, refunded_amount, tax_refunded_amount, amount_after_fees, usd_total. settlement_amount, settlement_currency and settlement_exchange_rate are folded into total and currency. refunded_amount and tax_refunded_amount are stated as they settled, at the rate in force when each refund was issued, and tax_refunded_amount is now on list responses as well as retrieve.
  • Disputes, refunds and Resolution Center cases are no longer embedded — list them from their own endpoints with ?payment_id=. Embedded financing transactions and the application fee aren’t carried over to the native shape.
  • last_payment_attempt / next_payment_attempt are last_payment_attempt_at / next_payment_attempt_at. Card facts live on payment_instrument.
  • Creating a payment takes account_id (was company_id), answers 201 Created, honours Idempotency-Key, and accepts capture: false to place an authorization hold.
  • Native payment reads are account-scoped: the credential must be able to read the account’s payments (a team member’s token or the account’s API key). A buyer’s own user token, which the pinned proxy versions accept for reading their own payment, isn’t served natively yet — buyers keep working on their pinned version.
  • GET /payments/{id}/fees rows are { type, origin, label, description, amount, settlement_amount, collected_at } with money objects (were name/amount/currency/type).
  • GET /refunds and GET /refunds/{id} return the native Refund: payment_id and account_id instead of an embedded payment, amount as a money object in the payment’s settlement currency, original_amount in the processor’s currency. The company_id filter is account_id, and sending company_id is a 400.
  • POST /payments/{id}/refund, POST /payments/{id}/retry and POST /payments/{id}/void are native too, returning the same Payment object. Refund still takes an optional partial_amount.
  • GET /payments lists with the standard { data, page_info } envelope and cursor pagination. Filters are singular equality params (status, billing_reason, currency, plan_id, product_id, membership_id, member_id, user_id, account_id) instead of the proxy’s plural arrays. As on the proxy, billing_reason=subscription_cycle also matches renewals recorded as subscription_update. Zero-amount payments are included, so the proxy’s include_free is gone. An invalid status is a 400, as is any proxy-only filter (substatuses, updated_before/updated_after, checkout_configuration_ids, plural arrays), rather than an unfiltered page. The query buyer search works as before. The created_before/created_after window covers the payment’s creation time alone. The proxy filtered on paid-at where one existed. On list rows settlement_time_at is null — retrieve the payment for it.
Legacy ad reports endpoint retired
The legacy GET /ad_reports endpoint is deprecated in favor of the native Stats metrics and the ad entity endpoints. It’s no longer served at this version.
  • GET /ad_reports returns 410 Gone with an error.type of gone. Use GET /stats/ad_delivery for spend, impressions, and clicks over time, scoped with a source path such as whop:adcamp_xxx:*. Use GET /stats/events for attributed conversions.
  • Per-entity performance for a window is on the entity endpoints. GET /ad_campaigns, GET /ad_groups, and GET /ads accept stats_from and stats_to and return spend, results, and return_on_ad_spend on each row.
  • Every response from the legacy endpoint, at any version, now carries Deprecation and Link: <…/stats/ad_delivery>; rel="successor-version" headers. Requests pinned to earlier versions, and requests without a version, keep working unchanged until a Sunset header announces the date it stops responding for every version.
Financial report timestamp ranges
GET /financial_reports and GET /financial_reports/breakdown now use from and to ISO 8601 timestamps for report windows.
  • from_date and to_date are renamed to from and to.
  • Bare dates are no longer accepted. Include a time and offset in both timestamps.
Explicit app verification filtering
GET /apps now uses verified as an optional equality filter instead of treating its absence as verified=false for public website lists.
  • Omit verified to return publicly discoverable website blueprints from both verification states.
  • Set verified=true for Whop-verified blueprints or verified=false for community blueprints.
  • recommended=true filters recommended apps independently of verification status.
Legacy withdrawals endpoints retired
The legacy /withdrawals endpoints are deprecated in favour of the native Payouts API and are no longer served at this version.
  • GET /withdrawals and POST /withdrawals return 410 Gone with an error.type of gone. Use GET /payouts and POST /payouts instead. Payout ids are the same wdrl_ ids, so existing identifiers keep resolving.
  • GET /withdrawals/{id} still responds at this version. Use GET /payouts/{id} for new work.
  • Every response from the legacy endpoints, at any version, now carries Deprecation and Link: <…/payouts>; rel="successor-version" headers. A Sunset header will announce the date they stop responding for every version. Until then, requests pinned to earlier versions, and requests without a version, keep working unchanged.
Ad post IDs
An ad’s post_id now names the post the ad network serves, whichever way the ad was built.
  • post_id returns the network’s post for the ad — the one Meta created for an uploaded creative, or the post being promoted. It used to be null for every ad built from uploaded creatives.
  • The post you point an ad at moved to existing_post_id, on both the response and the create/update body. post_source and post_thumbnail_url describe that field.
Native Files API
TypeScript SDK: @whop/sdk@1.0.14.POST /files and GET /files/{id} are served natively with a redesigned file object, and multipart uploads finish through the new POST /files/{id}/complete.
  • File responses carry the standard envelope: object, visibility, and an ISO 8601 created_at. The size and url fields are null until the upload is ready.
  • GET /files/{id} only resolves files you created — other callers receive a 404.
Payouts status v2
TypeScript SDK: @whop/sdk@1.0.13.The payout object’s lifecycle vocabulary is rebuilt and its money fields become decimal strings.
  • status speaks eight words: requested, in_review, processing, completed, reversed, canceled, failed, denied. A settled payout the provider reverses reads reversed, with the return code and funds_returned_at in failure.
  • A new status_detail field carries the finest machine phase under the status word. Its values can grow without a version bump — status is the versioned contract.
  • amount, fee_amount, net_amount, markup_fee, and destination_amount are decimal strings. exchange_rate stays a number.
  • Payouts are created under their wdrl_ id: the id POST /payouts returns is the id GET /payouts lists, and a stablecoin payout’s conversion request survives as payout_request_id. Conversion requests created before this version keep answering under their cofr_ id.
  • The idempotency key is sent only in the Idempotency-Key header, and the idempotency_key body field is rejected.
Requests pinned to earlier versions keep the previous vocabulary, float money, and body-field idempotency keys. Webhook payloads follow the subscription’s api_version_date the same way: subscriptions pinned 2026-08-21 or later receive the new payout shape, earlier or unpinned subscriptions keep the previous one.
Webhook envelope account_id
The webhook envelope’s company_id field is renamed to account_id.
  • Webhook deliveries pinned to 2026-08-14 or later carry account_id in the envelope.
  • Webhooks pinned to earlier versions — and webhooks without an api_version_date pin — keep company_id.
In-transit balance breakdowns
TypeScript SDK: @whop/sdk@1.0.11.Account and personal balance breakdowns now expose in_transit alongside pending.
  • Add pending and in_transit to present the total amount awaiting settlement.
  • Callers pinned to earlier versions continue receiving the combined amount in pending.
Webhook API version input removed
The api_version input on POST /webhooks and PATCH /webhooks/{id} is removed.
  • New webhooks always use the v1 events and payloads. Requests passing api_version are rejected with a 400.
  • Pin a webhook’s payload shape with api_version_date instead.
  • Existing v2 and v5 webhooks keep delivering. You can no longer create or switch webhooks to these versions.
Native dispute alert endpoints
Dispute alerts are now a native REST resource and remain dual-served with the legacy proxy.
  • GET /dispute_alerts lists an account’s alerts with cursor pagination, and filters by account_id, payment_id, type, and a creation window.
  • type replaces alert_type and names the two kinds an issuer sends: early_fraud_warning (Visa TC40 / Mastercard SAFE fraud reports) and dispute_alert (pre-dispute notices).
  • fee_charged replaces charge_for_alert and reports whether Whop actually billed the account. Early fraud warnings are never billed.
  • actionable reports whether refunding the payment can still prevent a chargeback.
  • payment and dispute objects are replaced by the payment_id and account_id tags. Timestamps are ISO 8601, with reported_at for when the issuer filed the report.
Fiat currency conversion on swaps
Fiat-pair swaps (POST /swaps with two fiat currencies) now support free-form currency conversion, and amount matches crypto swap semantics.
  • amount is the amount of from_token to convert at the mid-market rate. No negative balance is required.
  • Sizing a partial repayment of a negative to_token balance moved to the new to_amount field (denominated in to_token, capped at the debt). amount and to_amount are mutually exclusive.
  • Omitting both still repays the full negative to_token balance.
  • Callers pinned to earlier versions keep the previous behavior: their fiat amount is treated as the to_token repayment amount.
Flat verification requirements
A verification’s requested_information is now a flat list: one requirement per entry, one write per answer.
  • Each entry names what’s needed in requirement: a document such as bank_statement, or a field key such as ssn, with a label to show the user.
  • Answer file entries with file (a direct upload ID). Answer text, date, phone, and select entries with value, and address entries with address. Nothing from the response is echoed back.
  • An entry marked multiple takes several files in one answer, in slot order, front first for a two-sided document.
  • An entry listing options also takes a value. For select entries, the options are the allowed answers. For identity documents, the options are the accepted ID types.
  • Keys that don’t apply are omitted, and rejected submissions carry structured errors with a stable code and a reason.
  • The nested requested_files/category form shape is gone from this version. Callers pinned to earlier versions keep it, and their answers are translated automatically.
Native promo code endpoints
Promo codes are now a complete top-level REST resource and remain dual-served with the legacy proxy.
  • GET /promo_codes lists an account’s promo codes and uses account_id instead of company_id.
  • POST /promo_codes creates promo codes. GET and DELETE /promo_codes/{id} retrieve and archive them.
  • POST /promo_codes/{id}/activate and POST /promo_codes/{id}/deactivate replace the legacy PATCH status write.
  • List responses use cursor pagination and support status, product, variant, timestamp, and sorting filters.
  • Callers pinned to earlier versions keep the legacy proxy contract unchanged.
Richer parent accounts
Account responses now expose a richer parent account relationship for connected accounts.
  • parent_account replaces parent_account_id.
  • The parent account includes its id, title, route, and logo_url.
Supported payout methods
Supported payout methods now have their own paginated endpoint.
  • GET /payouts/supported_methods lists the payout methods an account or user is eligible to add.
  • Supported methods use object: "supported_payout_method", and their podst_ IDs are passed as supported_payout_method_id.
  • Saved payout methods expose supported_payout_method. Payouts expose payout_method.supported_payout_method.
  • Use country to list supported methods for a country other than the payout account’s country.
  • GET /payouts/methods no longer accepts include_available or returns available_destinations.
  • Callers pinned to earlier versions keep destination_id, payout_destination, and payout_token.
Native card transactions, payout method arrival estimates
Card transactions now use native REST endpoints and remain dual-served with the legacy proxy.
  • GET /card_transactions lists an account’s card transactions, and GET /card_transactions/{id} retrieves one by its citx_ id. The list also takes a transaction_ids filter to fetch specific transactions in one request.
  • Card transactions are account-scoped: the owner is selected with account_id, defaulting to the account the credential belongs to.
  • Filters on transaction_ids, card_id, cardholder_id, status, created_after, and created_before. Timestamp filters are ISO 8601.
  • cardholder_id is new on the response: the user the card is assigned to.
Payout methods now carry amount-independent fee and delivery terms, and the quote no longer duplicates arrival estimates.
  • Each payout method returns fee_structure (percentage, fixed amount, and currency) and estimated_arrival (per-speed timestamps) without requiring an amount.
  • The quote’s standard and instant objects no longer include estimated_arrival. Read it from the method’s top-level estimated_arrival field.
Native Resolution Center endpoints
Resolution Center cases now use native REST endpoints and remain dual-served with the legacy proxy.
  • status, escalated, outcome, refund, reason, and available_actions expose case state and permitted actions.
  • Events are available from paginated GET /resolution_center_cases/{id}/events. Summaries are available from GET /resolution_center_cases/summary.
  • Writes use message and attachments. due_date is renamed response_due_at. Listing no longer requires account_id.
Native shipments endpoints
Shipments now use native REST endpoints and remain dual-served with the legacy proxy.
  • GET /shipments lists shipments. GET /shipments/{id} retrieves by shipment id or payment id.
  • POST /shipments creates a shipment, and PATCH /shipments/{id} updates its tracking number.
  • Responses use account_id and tracking_number, alongside carrier, tracking_url, order_id, and payment_id.
  • Callers pinned before this date keep the legacy proxy contract unchanged.
Native disputes endpoints
Disputes now use native REST endpoints and remain dual-served with the legacy proxy.
  • PATCH /disputes/{id} edits evidence, and POST /disputes/{id}/submit submits it. Evidence is nested under evidence.
  • GET /disputes/summary provides totals grouped by status and currency. List and retrieve return the same fields.
  • Responses use account_id, product_id, and plan_id, plus buyer alongside payment. Listing no longer requires account_id.
  • status and reason are normalized enums, and needs_response_by, rdr, and editable are replaced by their new fields.
  • Callers pinned before this date keep the legacy proxy contract unchanged.
Members and memberships
Members and memberships now use native resources with an account-oriented membership model and redesigned lifecycle actions.
  • Membership responses return the compatibility field plan_id and product_id instead of nested compatibility plan and product objects.
  • Listing memberships returns everything the caller can read (their own plus their managed accounts’) and account_id/user_id narrow that list instead of switching modes or erroring.
  • Set cancel_at_period_end to schedule cancellation. The cancel action ends access immediately.
  • The extend action replaces add_free_days.
REST response and timestamp consistency
The Current API now uses consistent delete responses, timestamp inputs, and Account naming.
  • Delete endpoints for products, variants, checkout configurations, ads, ad groups, ad campaigns, social accounts, and bounty submissions return { id, deleted: true } instead of a bare boolean.
  • Timestamp filters on products, variants, checkout configurations, transfers, and financial reports accept ISO 8601 only instead of also accepting epoch seconds.
  • Product responses return account instead of company.
Partner business payout percentages
Partner businesses now expose separate payout rates for every income source.
  • payout_percentage is replaced by payout_percentages.
  • The nested object includes sales, ad_spend, transfer, and card_interchange rates.
Products and checkout configurations
Products and checkout configurations now use the Account model consistently.
  • Product request parameters use account_id instead of company_id.
  • Checkout configuration requests use account_id at the top level and inside inline variant objects carried by the compatibility field plan.
  • Checkout configuration responses return account_id instead of company_id.
Checkout configuration timestamps
Checkout configuration timestamps now use the same format as the rest of the API.
  • created_at and updated_at are ISO 8601 strings instead of Unix epoch integers.
User balances
User balances now provide a complete, structured balance summary.
  • The flat total_usd and balances fields are replaced by a nested balance object.
  • The summary separates cash, crypto, in-flight treasury deposits, and balances for accounts the user owns.
Business referral earnings resources
Business referral earnings now identify the polymorphic resource that generated the earning.
  • receipt is replaced by resource.
  • access_pass is replaced by product.
  • Receipt-backed earnings return resource.object: "receipt" with receipt payment details.
  • The resource field can support additional earning resources in future versions without reusing receipt-specific fields.
Business referrals resource
Business referral volume and earnings are now reported as reconciling groups.
  • processing_volume, total_earnings, pending_payout, and completed_payout are replaced by nested volume_usd and earnings_usd objects.
  • Earnings rename base_amount/amount to transaction_amount_usd/commission_amount_usd and express payout_percentage as a fraction.
Variants resource (then named Plans)
Variants, which were then named Plans, now use the Account model consistently.
  • Request parameters and request bodies use account_id instead of company_id.
  • Variant responses return account instead of company.
Users resource
User access requests now use the Account model consistently.
  • Request parameters and request bodies use account_id instead of company_id.
  • Response shapes are unchanged.
Original version
The original Current API behavior before dated versioning existed.Requests without Api-Version-Date use this version so existing integrations keep working.