FAQ / Getting Started
Getting Started: Questions and Answers
Accounts, environments, keys, rate limits, registering a title, tiers and fees, and platform partners. 169 questions, grouped by the documentation page each one is about. Where a response or webhook carries a figure, read it there rather than recomputing it.
Introduction
What is INVO Network, and how is it different from a single-title payment system?
INVO Network is a payments and ledger platform for games and apps: it sells your branded currency for real money, records every balance, and lets value move between titles on the network. A single-title payment system stops at your own storefront; INVO keeps one ledger across every participating title, so a player can move currency to another title they play, send it to another player, and keep its value when they switch titles.
What are the core capabilities?
Cross-game self-transfers (a player moves their own balance to another title), player-to-player sends (by phone number, same title or another title), currency purchases through hosted checkout, player balance reads (single, batch of up to 100,000 players, and a streaming export), item purchases, subscriptions, loyalty programs and developer payouts. Security covers passkey and QR device approval for money movement, idempotent writes, rate limiting and fraud screening on every card payment.
What is the difference between a cross-game self-transfer and a player-to-player send?
A self-transfer moves a player's own currency from your title to a different title where the same person plays; the sender approves it and the destination title collects it. A send goes to another player, identified by phone number, in the same title or a different one; the recipient collects it in their title with their player token, or through an emailed claim link when INVO already has their email for that phone. Both carry the same 10% network fee, deducted from the amount moved, so the recipient receives 90%.
Can a player self-transfer currency to the same title?
No. POST /api/transfers/initiate-transfer refuses a destination equal to the source title with 400 ("Self-transfers are not allowed."). The destination must be a different title that is Live; a destination in Testing is refused with TARGET_GAME_NOT_LIVE. To move currency to another player in the same title, use a send.
What fees apply to each flow?
Transfers and sends: 10% of the amount moved (3.5% to the sending title, 3.5% to the receiving title, 3% to INVO). Item purchases paid with coins: 5% (95% to you). Platform Commerce items paid from a balance: 3.5%. Every INVO card charge (coin purchases, Platform Commerce card sales, subscription charges): 3.5% + $0.15 on Open, 5.0% + $0.15 on Merchant of Record, plus 1.5% on cards issued outside the US. Your live rates are returned by GET /api/dev/fee-schedule.
Who pays the card fee, the player or the developer, and is it ever added to the player's price?
You do. The player pays your listed price (plus tax where INVO collects it on Merchant of Record) and receives every coin or item listed. On a coin purchase the fee is charged against your earnings balance (taken_from: "partner_balance"); on Platform Commerce card sales and subscription charges it comes out of your proceeds (taken_from: "partner").
What extra fee applies to cards issued outside the US?
1.5% of the listed price (before tax), added to your card fee on every INVO card charge on both tiers. It is reported as international_card_fee_usd. INVO charges in USD, so there is no separate currency conversion fee.
What does a payout to my bank cost?
Nothing, if INVO pays you on its schedule: on the 1st and 16th of each month (UTC) INVO pays out your full available balance, free, when it is at least $10 and you have a verified bank account. A payout you request yourself (a developer withdrawal or a partner payout to your own bank) is on demand and costs 1% of the payout, capped at $500, deducted from the amount sent, with a $10 minimum: a $2,000.00 on-demand payout sends $1,980.00. Each creator payout carries the same 1% fee, capped at $500, with no minimum. A negotiated rate, if your account has one, shows in GET /api/dev/fee-schedule under offboarding.
Is fraud screening included on every card payment, and when is the fraud chargeback guarantee included?
Fraud screening is included on every INVO card payment on both tiers. The chargeback guarantee (INVO absorbs a fraud chargeback, reason fraudulent or unrecognized, where the cardholder says they did not authorize the payment) is included on Merchant of Record, for card payments on INVO's hosted checkout. On Open, card payments made before 2026-10-21 keep the guarantee for fraud disputes; from that date a chargeback on an Open card payment is yours whatever the reason. A dispute that is not coded as fraud is yours on both tiers. Coverage follows the tier and date of the sale, not of the dispute.
Which game engines have examples or SDKs?
There are SDKs for web/TypeScript (npm @invonetwork/web-sdk), Python (PyPI invonetwork), Unity and Unreal, each with its own docs page. Godot is covered by code examples in the docs, not by a packaged SDK. Every SDK wraps the same REST API, so any language that can send HTTPS requests can integrate directly.
How does INVO help reduce churn and increase lifetime value across a portfolio of titles?
A player's spent money does not stay stranded in one title: they can move balance to another title on the network, gift it to friends, and keep its value when they move between your titles, so leaving one game does not mean leaving your portfolio. Each title also earns 3.5% of every transfer it sends or receives, and loyalty programs can reward play across titles.
What does a minimal balance lookup look like, and what fields come back?
GET /api/player-balances/player/by-email/{email} with the X-Game-Secret-Key header. A 200 returns player (player_id, player_name, player_email, date_joined), balances[] (currency_id, currency_name, available_balance, reserved_balance, total_balance, all decimal strings), summary (total_value, currency_count, has_funds) and last_updated. A player who has never used your title returns 404 "Player not found".
How do I get dedicated support, custom rate limits or contract terms for production?
Email partners@invo.network. Per-game rate limits are sized at or above what the platform can process, so most titles never need a change, but if you expect to approach one, or need negotiated fees or contract terms, that address handles it.
Quick Start
How long does a basic integration take, and what are the four Quick Start steps?
A first working call typically takes about 30 minutes. The steps are: register a title (sandbox first), copy its SDK key, make a first balance read with X-Game-Secret-Key, and go live by getting the title into production and swapping the key and base URL.
Why should I start in sandbox at dev.console.invo.network, and what does it use instead of real money?
Sandbox is a fully separate environment (its own database, keys and game IDs) running the same code and fees as production, so you can test every flow without risk. Card payments use test cards only and no real money moves at any amount.
What does the registration wizard collect?
Title information (name, icon, cover image, developer and publisher, genre, platforms, URL, transfer policy and payment route), an auto-generated SDK key, the default currency (name, symbol, symbol image, starting amount, transferable flag, minimum and maximum transfer amounts) and, optionally, payout details.
What is the SDK key format, and which header carries it?
ivsdk_ followed by a random URL-safe string (60 characters for keys INVO generates). Send it as X-Game-Secret-Key on every server-to-server call.
Is there a login flow, token refresh or cookie involved in server-to-server authentication?
No. Server-to-server calls carry only the X-Game-Secret-Key header. The only token in an integration is the short-lived player token your server mints for browser or device calls to /api/sdk/*.
Why does my first balance call return 404, and which writing endpoints create the player automatically?
The player has no record in your title yet; 404 "Player not found" is normal for a new player. A player record is created the first time they go through a writing flow, such as a currency purchase or hosted checkout, an item purchase, an incoming transfer or send claim, POST /api/sdk/players, or POST /api/sdk/player-token when you pass player_phone.
What are the sandbox and production base URLs, and do all endpoints share the same path suffix?
Production is https://invo.network with paths under /api/...; sandbox is https://sandbox.invo.network with the same paths prefixed by /sandbox (for example /sandbox/api/player-balances/...). Apart from that prefix, every endpoint path is identical.
What must I set up on day one if my title receives transfers or sends?
Create a webhook on the console's Webhooks page and subscribe to ["*"] (or at least transfer.claim_pending), and poll GET /api/transfers/inbound-pending to list what is waiting for your players so you can badge it. Do both before going live.
Why must I act on direction "inbound", and how do I dedupe?
When both players are in your own title, one move produces two transfer.claim_pending copies to the same endpoint, one with direction: "outbound" and one with direction: "inbound"; only the inbound copy means "a player of yours has money waiting". Dedupe deliveries on the X-Invo-Idempotency-Key header, which stays the same across retries and replays; never dedupe on transaction_id, because both copies share it, and not on X-Invo-Event-Id, which changes on every replay.
What happens if I skip the inbound webhook setup?
Incoming transfers and sends still arrive and wait for collection, but nothing tells your title they exist, so your players never see them and the money eventually expires and returns to the sender.
How does client_request_id idempotency work, and what does a duplicate return?
Send a fresh UUID as client_request_id for each logical action and reuse the same value when you retry it. A repeat of an id INVO has already accepted for your title is refused with 409 and a "Duplicate client_request_id" message; nothing is processed twice. On item purchases, transfers and sends the 409 body carries only that message, so look the original up with the status or history reads. Partner payouts are the exception: a repeat returns 200 with the payout already created.
Are plain-HTTP requests accepted?
No. A request sent over http:// is refused with 403 HTTPS_REQUIRED (header X-Invo-Refused: HTTPS_REQUIRED) before it is processed; it is not redirected. If you sent a key over plain HTTP, rotate it.
Why should I store identity_id from player records?
identity_id is the opaque identifier for the same person across every title on the network, so it is the right key for joining a player across your titles. It is derived from the email and phone together, so it changes when either changes: store the new value when a response says identity_rekeyed: true or on player.phone_changed (which also carries previous_identity_id). It is returned by POST /api/sdk/player-token, player registration and webhook payloads, not by the balance lookup.
Is it safe to retry a 5xx on an idempotency-keyed write?
Yes, if you resend the same body with the same client_request_id. If the first attempt did not commit, the retry processes normally; if it did, the retry is refused with 409 and nothing happens twice, so check the order or transaction status to get the result.
How do I go live?
Your sandbox titles are copied into production for you once your sandbox account is linked (or with Copy to production in the sandbox console), arriving with new keys of their own in Testing. Then use the production SDK key from console.invo.network, switch the base URL to https://invo.network without the /sandbox prefix, and set the title to Live from its settings in the production console.
For player-to-player sends, why must my server mint the player token with player_email and player_phone, and what do I do on phone_mismatch: true?
Sends are addressed by phone and the phone is part of the player's network identity, so POST /api/sdk/player-token with player_phone creates a missing player (without it, a new player gets 404 player_not_found) and checks the number on file. phone_mismatch: true means the player exists with a different phone; update it with POST /api/sdk/players/phone, and if that answers 409 PHONE_CHANGE_REQUIRES_VERIFICATION, start a player-confirmed change with POST /api/sdk/players/phone/change-requests (the player confirms on INVO's hosted page with an emailed code plus a passkey or enrolled device, and you receive player.phone_changed).
API Overview
What are the two environments, and are their databases and SDK keys fully isolated?
Production (https://invo.network, /api/...) and sandbox (https://sandbox.invo.network, /sandbox/api/...). They have separate databases, separate keys and separate game IDs; a sandbox key never works in production or the reverse.
What differs between sandbox and production?
Same code and the same fees. Sandbox adds test-only tools that settle approvals without a real device or passkey and subscription time travel; it lets you claim platform status without identity verification; it lets you set a title Live yourself; and it is sized for integration testing, not load tests. Only test cards are accepted.
Which endpoints cover player balances, currency purchase, item purchase, self-transfers, sends, withdrawals and player history?
Balances: GET /api/player-balances/player/by-email/{email}, POST /api/player-balances/batch, GET /api/player-balances/stream-all. Currency purchase: POST /api/checkout/sessions, POST /api/currency-purchases/quote, /purchase-currency, /confirm-payment. Item purchase: POST /api/item-purchases/purchase-item. Transfers: /api/transfers/available-destinations, /initiate-transfer, /claim-transfer; sends: /api/currency-sends/initiate-send, /claim-currency. Withdrawals: GET /api/withdrawals/available-balance, POST /api/withdrawals/request, GET /api/withdrawals/history. Partner and creator payouts: POST /api/partner-payouts/request, GET /api/partner-payouts, POST /api/partner-payees, GET /api/partner-payees, POST /api/partner-payees/{payee_id}/resend-invite. History: GET /api/sdk/players/activity plus the per-type history reads.
What does GET /api/sdk/players/activity return, and which types can I filter on?
One player's money activity in your title, newest first: activity[] entries with id, type, direction, amount, amount_unit, currency, status, status_detail, expiry_reason, counterparty_game, created_at, completed_at and order_id, plus has_more and next_cursor. Filter with types, a comma list of currency_purchase, item_purchase, platform_commerce, send, transfer (default all five); an unknown type is 400 INVALID_INPUT.
What are the limit and cursor rules on the activity feed, and what returns 400 INVALID_CURSOR?
limit is 1 to 100, default 50; out-of-range values are clamped, and a non-integer is 400 INVALID_INPUT. While has_more is true, pass next_cursor back as cursor. A cursor is opaque and valid only for the same player and the same types; a mismatched or malformed one is 400 INVALID_CURSOR.
Why does the activity feed use direction values in, out and self, while send and transfer history use incoming and outgoing?
The feed describes the effect on this player's balance: in credits it, out debits it, and self is a send or transfer where this player is both sender and recipient in your title. Currency purchases are always in; item and Platform Commerce purchases are always out. The older send and transfer history reads keep incoming/outgoing so existing integrations do not break; map them if you merge the two.
Why must I check status and status_detail before showing an inbound activity row as received?
An inbound send or transfer appears as soon as it names this player as the recipient, in any state: waiting to be collected, completed, expired or refunded. Only the status tells you whether the money actually reached the player's balance.
Does the activity feed ever reveal the other player's email, phone or name?
No. counterparty_game names only the other title (game_id and game_name) on a send or transfer with another title, and is null otherwise.
Which SDK versions add getPlayerActivity and platformCommerce.getPurchaseHistory?
Web SDK 3.22.0 (getPlayerActivity/iteratePlayerActivity, platformCommerce.getPurchaseHistory/iteratePurchaseHistory) and Python SDK 3.20.0 (get_player_activity/iterate_player_activity, platform_commerce.get_purchase_history/iterate_purchase_history).
Can I submit a withdrawal before identity verification is approved, and what does a held request do and not do?
Yes, in production the request is accepted (201) and held. A held request reserves the amount against your available balance, occupies one of your pending-request slots, cannot be approved by anyone until verification passes, can still be rejected (which releases the amount), and never expires; once verification is approved it joins the normal review queue on its own.
What do kyc_hold, kyc_hold_reason and next_steps mean on POST /api/withdrawals/request?
kyc_hold: true means accepted and held until identity verification is approved. kyc_hold_reason says why: KYC_REQUIRED (not submitted), KYC_IN_REVIEW, KYC_REJECTED, KYC_REVOKED or KYC_EXPIRED. next_steps is a sentence you can show the developer saying what clears the hold; both are null when the request is not held. status is still "pending_review".
What should my code do when kyc_hold is null?
Treat it as unknown: the verification state could not be read on that request. Do not show it as held or as clear. The approval step enforces verification regardless.
My integration used to handle a 403 on withdrawals without verification. What does it receive now?
A 201 with the request created, status: "pending_review" and kyc_hold: true. Show it as on hold, not as success or failure. All other checks still refuse as before (insufficient balance, too many pending requests, an unverified bank account).
Why is my withdrawable balance lower than expected?
Three things are subtracted before you see it: partner payouts INVO has approved and is sending (in_flight_payouts_usd, any tier), amounts held for open disputes you are responsible for (dispute_holds_usd and disputes_on_hold on GET /api/withdrawals/available-balance, any tier) and, on Merchant of Record, the chargeback reserve (reserve_held_usd). balance_before_reserve_usd shows the balance with nothing held, and reserve_next_release_at and reserve_release_schedule show when held amounts come back. These appear on GET /api/withdrawals/available-balance and GET /api/dev/withdrawals/summary.
Why should I show nothing rather than $0.00 when the reserve fields are null?
Null means the reserve could not be read on that request, not that nothing is held. Showing $0.00 would state something INVO did not confirm.
Does sandbox ever hold a withdrawal for identity verification?
No. The hold applies only in production; in sandbox kyc_hold is never true.
What is the standard error envelope, and why should I capture error_id?
Errors from the shared handler carry error (human-readable), error_code (machine-readable), error_id and timestamp. error_id lets INVO find the exact server log entry for your report. Some endpoints return a shorter body (for example message, or code on the /api/sdk/* routes), so branch on error_code or code and the HTTP status, never on message text.
What do Retry-After and retry_after mean on a 429?
Both give the number of seconds until the limit you hit resets; when several limits fired, it is the longest of their resets. Wait that long before retrying.
Authentication
Which single header authenticates every server-to-server call?
X-Game-Secret-Key, carrying your title's ivsdk_... key.
Do platform tenants use the same X-Game-Secret-Key header as games?
Yes. A platform is addressed exactly like a game: the same header, the same game_id, the same endpoints.
Why must the SDK key never be embedded in a Unity, Unreal, mobile or browser build?
Anything shipped to a client can be extracted, and the key authorizes every call as your title, including moving your players' balances. Client code should use a short-lived player token your server mints with POST /api/sdk/player-token.
Where should I store the SDK key, and what should I never do with it?
Keep it in your server's environment or secrets manager and call INVO only from your backend. Never commit it to source control, bundle it into a client build, serve it to a browser, or paste it into chat or tickets.
Does each title get its own key, and does a title on several storefronts get one key per storefront?
Yes to both. Every title has its own secret_key, and every title is also given a separate key for each distribution channel (the game-platform store, ios, android, web, console); the channel a key belongs to decides which payment route that purchase uses.
How is console login different from API authentication?
The console at console.invo.network uses a personal sign-in session for people (email code or remembered device as a second step). Your servers never use that session; they authenticate with X-Game-Secret-Key. A few developer-account endpoints, such as key rotation and the sandbox clock key, accept only the dashboard session.
What does 401 INVALID_GAME_SECRET mean, and what should I check first?
The key is missing or does not match an active key for any title. Check that the header name is exactly X-Game-Secret-Key, that the value is the full ivsdk_... string with no whitespace, and that you are using the key for the right environment (sandbox keys fail in production and vice versa). After a rotation, the old key stops working when its grace period ends.
What does a 403 "title inactive" mean, and which title statuses are allowed?
The key is valid but the title's status is not live or testing (for example suspended). Only those two statuses can make API calls.
What does a 429 mean on authentication, and how do I back off?
You exceeded a rate limit for that endpoint (per game, per player or per calling IP). Wait the number of seconds in the Retry-After header (also retry_after in the body) before retrying.
How do I rotate my SDK key, and is the new key shown only once?
Rotate from Platform & Keys in the console (API: POST /api/dev/partner/games/{game_id}/rotate-secret with your dashboard session). By default the old key keeps working for 7 days; send {"immediate": true} to revoke it at once. The rotation response shows the new key, and the key remains visible on Platform & Keys afterwards while the title is active.
Partner Credentials & Key Handling
Read the Partner Credentials & Key Handling page
What are the three credentials every integration needs, and which are secret?
game_id (your tenant id, not secret), the SDK secret_key (ivsdk_..., server-side only) and the webhook signing secret (server-side only, used to verify webhooks INVO sends you and never sent to INVO).
Where do I find game_id and the SDK key in the dashboard?
On the Platform & Keys page: open the user menu at the top right, choose Platform & Keys, then pick the title. The key can be revealed, copied and rotated there.
When is the webhook signing secret shown, and can I retrieve it later?
It is returned once when you create the webhook subscription and once on each rotation. It cannot be retrieved later; if you lose it, rotate it.
Why must the browser never hold the SDK key, and how does a player token replace it?
A browser bundle is readable by anyone. Your server calls POST /api/sdk/player-token with X-Game-Secret-Key and player_email, receives token, expires_at and identity_id, and the browser sends Authorization: Bearer <token> on /api/sdk/* calls. The token is scoped to that one player.
How long does a player token last, can it be refreshed, and what do I do on a 401?
15 minutes, with no refresh. On a 401 from any /api/sdk/* call, have your server mint a fresh token and retry.
How do I verify X-Invo-Signature, and what is the timestamp window?
The header is t=<timestamp>,v1=<hex>. Compute HMAC-SHA256 with your signing secret over the literal string <timestamp>.<raw request body>, compare it to v1 in constant time, and reject the delivery if the timestamp is more than 5 minutes from now. Then dedupe on X-Invo-Idempotency-Key.
Do web platforms need to configure a domain or keys for passkey step-up?
No. Passkey approval runs on INVO's hosted approval page for every title, so there is no domain or key to set up; partners cannot register their own passkey domain. Players without a passkey use QR device approval or hosted approval.
What is the sandbox clock key, when do I need it, and why is it a separate credential?
It is a sandbox-only credential (ivclk_...) sent as X-Sandbox-Clock-Key, in addition to X-Game-Secret-Key, on the four subscription time-travel endpoints. One of them really charges a test card on demand, so a leaked SDK key alone must not be enough to trigger it.
How do I get a sandbox clock key, and why does it use my dashboard session instead of the SDK key?
Call GET /sandbox/api/dev/games/{game_id}/sandbox-clock-key with Authorization: Bearer <dashboard session token>; the first call mints it (newly_issued: true) and later calls return the same value. It uses your signed-in session because if the SDK key could fetch it, the SDK key would again be sufficient on its own.
How long does an old key keep working after rotation?
7 days by default for the SDK key, the webhook signing secret and the sandbox clock key. The SDK key and the clock key can instead be revoked immediately with {"immediate": true}.
During signing secret rotation, how are deliveries dual-signed, and what does X-Invo-Secret-Version tell me?
During the grace window X-Invo-Signature carries two v1= values, one per secret, so a delivery verifies against either the old or the new secret while you deploy. X-Invo-Secret-Version gives the version number of the current secret.
If a key leaks, does rotating it revoke the old value immediately, and when must I pass {"immediate": true}?
Not by default: a routine rotation keeps the old value working for 7 days. For a leaked SDK key or sandbox clock key, rotate with {"immediate": true} (a strict JSON boolean; a string is 400 INVALID_IMMEDIATE) to revoke it now. The webhook signing secret rotates only with the 7-day grace, so cut over as soon as possible.
Is there a production version of the clock key?
No. The endpoints it unlocks do not exist in production, and the issuing endpoints answer 409 SANDBOX_ONLY there.
Sandbox Testing
Why does a sandbox API call without the /sandbox prefix return 404?
Sandbox serves its API under https://sandbox.invo.network/sandbox/...; without the prefix the path does not exist, and the 404 looks exactly like an unknown endpoint.
Why do hosted checkout and card setup links come back without /sandbox in them, and should I build those URLs myself?
Pages for a person to open are served at the host root (https://sandbox.invo.network/checkout?session=..., /card-setup?session=...), unlike API calls. Always use the URL exactly as INVO returns it; never assemble one from your base URL.
Does sandbox have the same fees and code as production?
Yes. Sandbox runs the same release, and the fees in its responses and webhooks are the production fees.
Which title features need a Live title in sandbox, and how do I switch a title to Live there?
A title in Testing cannot be a cross-game transfer destination (TARGET_GAME_NOT_LIVE), cannot receive a currency send and cannot sell subscriptions. In sandbox, change the title's status to Live yourself in its settings.
How is going live different in sandbox versus production?
Today both are self-serve: you set the title to Live from its settings. Production additionally requires that the title can perform passkey step-up, which every title can on the hosted approval page. A go-live request endpoint still exists, but nothing requires it.
Do sandbox and production share game IDs or keys?
No. Each environment mints its own game_id, SDK key, signing secret and channel keys, so a value from one can never work in the other, and an ID in a log or ticket names exactly one environment.
How do I open sandbox from my INVO account, and is there a second password?
Press Open sandbox in the production console; your sandbox account is created or linked and you are signed in. There is no second password to manage for an account reached that way.
I made a sandbox account before linking. How do I link it?
If it uses the same email as your production account and both addresses were verified at signup (emailed code, or a provider-verified sign-in), INVO links them automatically, keeping your sandbox password and sessions. Otherwise sign in to sandbox and link it to your production account from there. Accounts whose email was not proven this way are not joined automatically, because sandbox signup is open to anyone.
Does each production title get a sandbox copy, and do later setting changes sync?
Yes, each production title gets a sandbox twin with its own game ID and keys, and a sandbox title of a linked developer is copied into production once. Settings are copied once when the copy is made; after that the two are independent and nothing syncs in either direction.
What does copying to production carry across, and what never crosses?
It carries the name, developer and publisher names, description, genre, platform, title URL, transfer policy, tenant type, artwork (copied into production storage) and the default currency's name, starting amount, symbol, type, transferable flag and transfer minimum and maximum. It never carries keys, secrets, IDs, fees, the currency rate, linked titles, per-title flags, identity, verification or bank data, players, balances, items, webhooks, subscriptions or ledger history.
What status does a copied title land in, and can I copy the same title twice?
It lands in Testing, like a title created by hand. Each sandbox title is copied only once: a second request is refused rather than creating a second production title.
Which test cards produce success, a generic decline, insufficient funds and a 3D Secure challenge?
4242 4242 4242 4242 succeeds, 4000 0000 0000 0002 declines, 4000 0000 0000 9995 declines for insufficient funds and 4000 0025 0000 3155 triggers a 3D Secure challenge. Use any future expiry date and any CVC.
Which two headers do the subscription time-travel endpoints need, and why is one separate from the SDK key?
X-Game-Secret-Key and X-Sandbox-Clock-Key, both on every call. The clock key is separate because force-renewal really charges a test card, so a leaked SDK key alone must not be a charge-on-demand button.
Why do the time-travel routes sit at /sandbox/subscriptions/ with no /api segment?
They are registered on their own blueprint (/subscriptions) outside the /api tree, and only on the sandbox service. Other subscription calls are under /sandbox/api/subscriptions/..., so a missing or extra /api is the usual cause of a first 404.
What does advance-clock do with intervals 0 versus 1 or more, and does it move money?
intervals is 0 to 60, default 1. 1 or more simulates that many billing intervals passing and makes the next period due; 0 makes the subscription due now without touching its period window (useful for a first charge or an early retry). It never moves money; the charge happens at the next scheduled renewal or when you call force-renewal.
Why does calling force-renewal repeatedly without advance-clock fail with 409 PERIOD_TOO_FAR_AHEAD?
Each successful renewal moves the subscription onto the next, not-yet-due period, and billing ahead is capped at one period. Call advance-clock between renewals; the loop advance-then-renew can run for as many periods as you want.
Does force-renewal charge a real test card, and which webhooks should I expect?
Yes, it runs the real renewal against the subscription's sandbox test card (never the balance). Expect the same webhooks as production: subscription.renewed on success, subscription.payment_failed on a decline, and subscription.authentication_required when the card needs 3D Secure.
What do the engine_stats counters on force-renewal mean?
Exactly one outcome counter is set: renewed (charged), declined, insufficient (insufficient funds), auth_required (step-up needed), containment (held under the origin-containment rule, not retried), ambiguous (the processor result was unclear; settled later), settle_failed (charged but not settled yet), errors, abandoned (cancelled or ended during the run, nothing charged, no retry used) or refused_over_ceiling (price above the per-renewal ceiling; held, not dunned). periods_forgiven may appear alongside. Treat any unexpected counter as a real outcome.
How do I walk a subscription to expired with force-failure, and what do the retry fields show?
Call force-failure repeatedly (body outcome: card_declined default, insufficient_funds or error). Each call runs the real dunning ladder without touching a card: retry_budget_used is how many retries are spent, retry_schedule_days is the spacing in days, and retries_remaining is what is left; when it reaches 0 the subscription moves from past_due to expired.
Why does force-auth-challenge not send subscription.authentication_required or return a link, and how do I test step-up end to end?
It only drives the state machine (status awaiting_authentication, dunning paused, no retry budget used). The confirmation link and the event are minted only for a challenge with a real payment behind it, and a synthesized challenge has none. For the full flow, attach the 3D Secure test card and run force-renewal.
What happens after max_auth_challenges is reached, and why shouldn't I assert on downgraded_to_decline?
Further challenges are treated as declines: auth_challenges_used stays at max_auth_challenges, retry_budget_used starts rising, and the status moves to past_due and then expired. downgraded_to_decline is read after the downgrade has rewritten the attempt, so it stays false in practice; assert on the status and retry_budget_used instead.
What do the 409 codes on the clock tools mean?
WINDOW_ALREADY_PAID: advancing would bill a period already paid, so nothing changed. ATTEMPT_IN_FLIGHT: a previous attempt on this period has not resolved. AUTH_CHALLENGE_OPEN: a step-up challenge is still open for the member. AMOUNT_OVER_CEILING: the price exceeds the per-renewal ceiling (refused, no retry spent). NO_CHARGEABLE_PERIOD: no billable period can be derived. SUBSCRIPTION_NOT_LIVE: already canceled or expired.
Why do three different clock-key problems all return 401 SANDBOX_CLOCK_UNAUTHORIZED?
A missing header, a wrong key and a title that never issued a key get one identical answer so the response cannot reveal which titles have set up the second credential. If you have not issued a key, call the issuing endpoint before debugging anything else. A bad X-Game-Secret-Key is reported separately.
What are the time-travel rate limits, and what does 503 FLOW_PAUSED mean?
10 calls per minute per subscription and 60 per minute per calling IP (429 RATE_LIMITED). 503 FLOW_PAUSED means subscription billing is paused platform-wide for maintenance; all four endpoints honor it, so retry shortly.
Can time travel un-bill a period or be called in production?
No to both. A forced renewal is a real renewal with real ledger entries and webhooks, so reverse it with an ordinary refund. The routes are not registered in production at all and return 404 there.
Rate Limits
How are limits counted?
Per game (the bucket of the X-Game-Secret-Key you send, shared by all your servers), per player (the player_email in the request, or the player a token was minted for on player-side calls) and per calling IP, depending on the endpoint.
When a row lists several limits, which one answers the 429?
All of them apply at once; the first one reached returns the 429.
What do Retry-After and retry_after mean, and what changed on 2026-10-09 for hourly limits?
Both are the seconds until the window of the limit you hit resets (the longest reset when several fired). Before 2026-10-09 an hourly limit always answered 300 seconds however much of the hour remained; it now reports the real time left.
Should I match on error_code or on the message of a 429?
On error_code (RATE_LIMITED for rate limits), never the message. Some endpoints return their own 429 body (for example a temporarily locked approval or claim); always honor the Retry-After header whatever the body says.
How should my code handle a 429?
Every rate-limit refusal is HTTP 429 with error_code "RATE_LIMITED", retry_after (seconds) in the body and a Retry-After header. Some send-safety checks also return 429 with their own error value. In every case, wait Retry-After (or retry_after) seconds and retry the same request. Never hard-code the published limits in your client: they can change, and the 429 always says how long to wait.
What are the limits on POST /api/currency-purchases/purchase-currency?
50 per hour per player and 20,000 per minute per game.
What are the limits on POST /api/item-purchases/purchase-item?
Per player: 50 per minute and 200 per hour. Per game: 12,000 per minute and 200 per second.
What are the limits on initiate-send, initiate-transfer and claims?
initiate-send and initiate-transfer: 100 per hour per sending player, plus per-game ceilings of 120,000 per hour and 3,000 per minute. Claims: claim-currency 25 per hour per player and claim-transfer 30 per hour per player, each with a 120,000 per hour per-game ceiling.
What are the limits on balance lookups, batch and stream-all?
Single lookup: 2,000 per minute per game and 100 per minute per IP. Batch: 50 per minute per game and 10 per minute per IP. stream-all: 5 per hour per game and 2 per hour per IP.
What are the limits on player-side SDK calls such as approve and confirm-receipt, and device poll?
Approve and confirm-receipt (transfers and sends) and phone-change approve: 12 per minute per player. Device approval begin: 10 per minute; device poll: 40 per minute per player (honor the interval in the response).
Is sandbox suitable for load testing?
No. Sandbox has smaller capacity than production and is sized for integration testing.
Are there business limits separate from rate limits, and where are they listed?
Yes. Money flows also enforce per-player amount, count and velocity limits, which return their own error codes rather than a rate-limit 429. They are listed on the money-flow error reference pages.
Who do I contact if my game expects to approach a per-game limit?
partners@invo.network.
Game Registration
Read the Game Registration page
What are the four steps of the registration wizard, and which one is optional?
1) Title information and assets, 2) SDK key generation, 3) default currency setup, 4) payout setup. Step 4 is optional.
What image assets are required, and are there size or format limits?
A square icon and a cover image (1920x1080 recommended) are required. The API does not enforce a file size or format on upload, but keep each image under 5 MB: larger images are skipped when a sandbox title is copied to production, and you would have to re-upload them.
What do universalTransfers "yes" and "no" do, and when must linkedGameIds be filled in?
"yes" (the default) allows transfers with any Live title on the network. "no" allows only the titles in linkedGameIds, so fill it in whenever you choose "no"; with an empty list, every transfer is refused with TRANSFER_POLICY_VIOLATION.
Should a franchise use Universal Transfers or Manual Linking?
Use Manual Linking ("no" plus linkedGameIds) if you want currency to move only among your own titles; use Universal Transfers if you want players to bring value in from, and take it to, any title on the network.
Can I block transfers with a specific game, even with universal transfers on?
Yes. In the INVO console, open your game's transfer settings and use "Exclude games" (or call POST /api/dev/games/{game_id}/transfer-exclusions with excluded_game_id). An exclusion blocks transfers and sends in both directions between the two games, in universal and linked mode alike, and the excluded game no longer appears in your destination lists. A transfer that already started still finishes. A blocked attempt is refused with 403 TRANSFER_GAME_EXCLUDED and the message "Transfers between these games aren't available.", which never tells your players which game set the exclusion. Developers can work it out, though: you know your own list, so if a game you did not exclude refuses with this code, that game has excluded yours, and the other developer can see the same about you. Set exclusions separately in sandbox and production.
What does paymentRail set at registration control, and can it be changed later?
It sets the title's default payment route so you never pass a rail per call: platform (INVO card checkout, the default), game (the game storefront rail, for games sold outside the game-platform store), or the game-platform store value (for games whose players pay with their platform store wallet; see Payment Methods for the exact value). An unknown value is 400. You can change it later in the title's settings; a platform tenant can use only the card route.
What is the SDK key format, and is it shown in the console, emailed, or both?
ivsdk_ followed by a random string. It is shown in the console (Platform & Keys) and also included in the "title registered" email sent when the title is created.
What do the currency fields control?
currency_name (required) and currency_symbol (up to 10 characters) brand the currency; currency_amount is a legacy display number stored with it; currency_type must be "default currency"; transferable decides whether it can be transferred; minimum_transfer_amount (default 1.00) and maximum_transfer_amount (optional, must exceed the minimum) bound each transfer.
In Step 4, what is the difference between payoutMethod "bank" and "mail"?
"bank" records bank payout details for electronic payment; "mail" records a mailing address for payment by check. Payouts are sent only to a bank account added and verified in the console.
How much bank detail does INVO store?
From the wizard, INVO stores the holder name, bank name, routing number, account type and only the last four digits of the account number. Verified bank accounts added in the console have their account numbers encrypted at rest, and API responses and webhooks show only the last four digits.
What revenue does a registered title earn on item sales and on transfers?
95% of each item purchase paid with coins, and 3.5% of the amount of every transfer or send it sends or receives (7% when both players are in the same title).
Does a new production title start in Testing or Live, and how do I go live?
Testing by default. Change it to Live yourself from the title's settings in the production console.
Does registering at console.invo.network create a sandbox or production title?
A production title. Sandbox titles are registered at dev.console.invo.network.
What should I have ready before starting the wizard?
A developer account, a square icon and a 1920x1080 cover image, a unique title name, your currency name and symbol, your transfer policy, your payment route, and bank details if you want to set up payouts now.
If my title sells on the game-platform store and on the web, which paymentRail should I choose?
Set the default to the route most of your sales use, and use the per-storefront channel keys: each title gets one key per channel, and a purchase made with a channel's key routes to that channel's rail, so store purchases and web purchases each go the right way.
Tiers: Open and Merchant of Record
Read the Tiers: Open and Merchant of Record page
Which tier is my account on by default, and is Merchant of Record approved per account or per game?
Every account starts on Open. Merchant of Record is approved per developer account and covers every game on it; it is never per game.
On each tier, who is the seller of record, and who handles sales tax, VAT and GST?
On Open your business is the seller and you are responsible for any tax; INVO does not calculate, collect or remit it. On Merchant of Record INVO is the seller and calculates, collects and remits consumption tax where INVO is registered.
What do the tax_treatment values mean, and what should my code do with an unknown value?
partner_responsible: Open, you are the seller and INVO charged no tax. collected: Merchant of Record, INVO collected tax and remits it. not_registered: Merchant of Record, INVO has no registration for that place so no tax was charged. external_mor: the sale went through a storefront rail that is the seller. Treat any value you do not recognise as informational, never as an error.
On a $10.00 coin pack, what card fee do I pay on each tier?
$0.50 on Open (3.5% + $0.15) and $0.65 on Merchant of Record (5.0% + $0.15), on a US card.
On a $100.00 sale with a non-US card, what is the fee on each tier?
$5.15 on Open (3.5% + $0.15 + 1.5%) and $6.65 on Merchant of Record (5.0% + $0.15 + 1.5%).
How is the card fee rounded, and which field reports the international part?
The percentage of the listed price (before tax) plus the fixed amount, rounded half up to the nearest cent. The international part is international_card_fee_usd.
From 2026-10-27, does the $2.99 minimum card purchase apply to coin purchases, Platform Commerce card sales and subscriptions?
It applies to coin purchases and Platform Commerce card sales, not to subscriptions (you set plan prices). It applies only to INVO card payments.
How does the Open-tier fraud chargeback guarantee change from 2026-10-21, and does coverage follow the sale date?
Open card payments made before 2026-10-21 keep the guarantee for fraud disputes (reason fraudulent or unrecognized); payments made on or after it are not covered, and every chargeback on them is yours whatever the reason. A non-fraud dispute is yours at any date. Coverage follows the tier and creation date of the sale, not your tier when the dispute arrives.
Which chargebacks does INVO cover?
Fraud chargebacks only (reason fraudulent or unrecognized), on card payments on INVO's hosted checkout. On Merchant of Record INVO absorbs them. On Open, INVO absorbs them only on card payments made before October 21, 2026; on card payments made on or after that date every chargeback is yours, fraud included. A dispute that is not coded as fraud (for example product not received) is always yours, on both tiers. Purchases through a third-party storefront or payment rail are not covered.
Why is part of my balance held?
While a dispute you are responsible for is open, the disputed amount is held from your earnings so it cannot be paid out: your share of a Platform Commerce card sale or subscription charge, or on a coin purchase the price paid before tax, less anything already refunded and never more than the disputed amount. Your withdrawable balance already excludes it. GET /api/withdrawals/available-balance reports the total as dispute_holds_usd and the number of disputes as disputes_on_hold. If the dispute is won the hold is released; if it is lost the hold is released at the same moment the loss is booked, so the amount is taken only once. On Merchant of Record, the chargeback reserve (reserve_held_usd) is held separately.
What do I owe on a lost chargeback the guarantee does not cover, and when is the network dispute fee charged or credited back?
While the dispute is open the disputed amount is held from your earnings. A lost chargeback costs what a full refund of that charge would: your share is reversed and INVO's card fee stays charged. On a coin purchase, the coins the player still holds are taken back, and the value of coins already spent is charged to you at the price paid per coin, before tax (spent_coins_charged_usd); INVO's card fee is not returned. From October 21, 2026, on both the Open and Merchant of Record tiers, the card network's dispute fee is passed through to you at cost on every card dispute opened from that date, whatever the date of the sale. INVO adds no administrative fee. If the dispute is won and the network returns the fee, it is credited back to you. INVO's own card fees are not returned on a chargeback. No dispute fee is charged on a dispute covered by the chargeback guarantee. The closing purchase.disputed carries dispute_fee_usd and dispute_fee_charged_to_partner.
How is the Merchant of Record 0.75% monthly chargeback threshold calculated, and what happens if I exceed it?
Disputes opened in a calendar month (UTC, excluding inquiries) divided by card charges completed on your account that month. If last month's rate was above 0.75%, INVO reviews your Merchant of Record approval.
If a $100 card charge is refunded in full, why am I left at -$3.65 on Open?
You received $96.35 (the $100 less the $3.65 card fee), the refund takes back the full $100, and the card fee is not returned. On Merchant of Record the same refund leaves -$5.15 on a US card; a non-US card adds the 1.5%, which is not reversed either.
How is the 10% transfer fee split, and what does a same-title move earn?
3.5% to the sending title, 3.5% to the receiving title and 3% to INVO; on 100.00 sent, the recipient receives 90.00. When both players are in the same title (a send), that title keeps both shares, 7%.
How is the payout fee calculated, and why do its fields use "offboarding" names?
1% of the amount paid out, capped at $500 per payout, deducted from the amount, on on-demand payouts and creator payouts. Scheduled payouts carry no fee (offboarding_fee_pct is 0 and fee_reason is scheduled). "Offboarding" is INVO's internal name for money leaving the platform to your bank; the fields are offboarding_fee_pct, offboarding_fee_cap_usd and offboarding_fee_usd, and the rate and cap are fixed on each request when it is made. Creator payouts use the same rate and cap; the creator receives the net.
What does GET /api/dev/fee-schedule return?
The rates in force for your account: coin_card, platform_commerce_card, platform_commerce_balance, item_purchase, subscription and transfer, each with taken_from, plus international_card, chargeback_guarantee (included, covers, applies_to_rails, ends_at), min_card_purchase and offboarding. Negotiated rates appear here too. Fields are additive.
How do I apply for Merchant of Record, what does INVO check, and how long before I can reapply after a decline?
Apply from the Selling & Tax page in the console; you need at least one game (otherwise 409 NO_GAMES). Identity verification is not needed to apply but must be approved before INVO approves, and INVO may run a sanctions screen, a risk review and a tax readiness check. After a decline or revocation you can reapply after a waiting period, 7 days by default (409 TIER_REAPPLY_COOLDOWN with retry_after until then).
If Merchant of Record is suspended or revoked, what happens to new charges, past refunds and renewing subscriptions?
Every new charge from that moment is on Open terms. Charges already made keep the terms they were made on, including their refunds and their chargeback coverage. Subscriptions keep running, and each renewal from then on is billed on Open terms.
What do receipt numbers look like, which webhooks carry receipt_url, and can anyone open a receipt link?
IR- in production and IRS- in sandbox (for example IR-2026-00000123), on Merchant of Record card sales only. receipt_number and receipt_url are added to purchase.completed, platform_commerce.purchased, subscription.renewed and the refund webhooks purchase.refunded, platform_commerce.refunded, subscription.refunded. The receipt page needs no login, so anyone with the link can read it.
How does the Merchant of Record chargeback reserve work, and which sales are not held?
By default 10% of your share of each card-funded Platform Commerce sale and card-paid subscription charge is held for 90 days, then released automatically; terms can differ per account or be waived. Card purchases of coins, balance-paid purchases, storefront-rail sales and transfers are not held, and Open accounts have no reserve.
What do the reserve fields mean?
reserve_held_usd is held now across the account; reserve_next_release_at is when the next amount is released (null when nothing is held); reserve_release_schedule lists up to 10 upcoming release days with amounts; balance_before_reserve_usd is your balance with nothing held; reserve_terms is the percent and days your next card sale is held at (null on Open, when waived or set to zero).
Do card fees, the $2.99 minimum and the chargeback guarantee apply on the game-platform store or game storefront rails?
No. On those rails the storefront is the seller and handles tax; INVO adds no card fee or tax, and the minimum and the guarantee apply to INVO card payments only.
How do I respond to disputes, and what is the evidence size limit?
List them with GET /api/dev/disputes, read one with GET /api/dev/disputes/{dispute_id}, and add evidence before evidence_due_by with POST /api/dev/disputes/{dispute_id}/evidence, all with your developer sign-in (not the game key). Evidence is multipart/form-data with a Content-Length header: a note of up to 4,000 characters, the named text fields of up to 20,000 characters each and 150,000 in total, and up to 5 PDF, JPEG or PNG files of up to 4.5 MB each. INVO decides what to include and files the response with the card network. Send evidence at least 3 business days before evidence_due_by.
Platform Partners
Read the Platform Partners page
Who is the platform partner program for, and what do I need to claim platform status?
Non-game consumer apps such as video, microdrama, social and creator platforms that want a branded currency, in-app purchases, subscriptions and payouts. Claim it on the Platform & Keys page: the title must be live or testing. No identity verification is needed for platform status; that is asked for only before a withdrawal. The change is instant.
Can I switch between game and platform, and what does 409 TENANT_TYPE_LOCKED_AFTER_LIVE_TRANSACTION mean?
Yes, in either direction, on the Platform & Keys page or with POST /api/dev/games/{game_id}/tenant-type, until the title's first live transaction. After that, a switch between game and platform returns 409 TENANT_TYPE_LOCKED_AFTER_LIVE_TRANSACTION and INVO makes the change after review. Changing between platform kinds (video, creator, social) is always allowed. Switching to a platform resets a game-only storefront payment rail to the card rail.
Once I claim platform status, can currency still move between my platform and games, and which payment routes do I lose?
Yes. Currency moves between games and platforms in both directions, the same as between two games. You lose the storefront payment routes (RAIL_NOT_AVAILABLE_TO_PLATFORM) and keep the card route, and you gain Platform Commerce.
Can a partner set its own exchange rate, or is it fixed at 1 USD = 10 units?
The network rate is 10 units per USD. Partners cannot set it; INVO can configure a different rate for a currency, but only before any money exists on it.
What PCI scope am I in with hosted checkout, and who handles sales tax on Open?
Card data never touches your servers, which places you in SAQ-A scope. On Open your business is the seller and handles its own sales tax.
What does a partner pay for item purchases, Platform Commerce balance purchases, card charges and non-US cards?
Item purchases: 5%. Platform Commerce paid from a balance: 3.5%. Card charges: 3.5% + $0.15 on Open, 5.0% + $0.15 on Merchant of Record. Non-US cards: plus 1.5% of the listed price. The same rates apply whether the tenant is a game or a platform.
What do allows_outgoing_transfers, allows_incoming_transfers, universal_transfers and linked_game_ids control?
Whether your users can send out, whether other tenants' users can send in, whether any active tenant is allowed ('yes') or only those listed in linked_game_ids ('no'). Always call POST /api/transfers/available-destinations to see what is reachable instead of hardcoding ids.
Can I send to a recipient with no INVO account yet, and when do they get an emailed claim link?
Yes, sends go by phone number and the recipient's player record is created when they collect. INVO emails a claim link only when it already has an email on file for that phone; otherwise the recipient collects in the receiving title.
What happens at each integration stage?
Kickoff (scope, terms and contacts); sandbox (register, claim platform status, copy the sandbox key, set up the webhook); build against the same REST API games use; a soak, typically 2 to 4 weeks of real flows in sandbox with nightly reconciliation; and production cutover (your sandbox title is copied to production with new keys, then you set up production keys and webhooks, swap the base URL and run a small live set).
What should my nightly reconciliation diffs match?
Your internal ledger should match INVO's balances (from GET /api/player-balances/stream-all or batch reads) and the transactions you recorded from webhooks and responses, with no unexplained differences.
What does POST /api/partner-payouts/request require, and what happens on a retry with the same client_request_id?
X-Game-Secret-Key, amount_usd (positive, not above your owed balance), contact_email, and a destination bank account; client_request_id is recommended. A repeat with the same client_request_id returns 200 with the payout already created.
Should I send bank_account_id, selected_bank_account_id, or a typed bank_account block, and what if they disagree?
Prefer bank_account_id (selected_bank_account_id is an alias), the id of a bank account verified in the console by the account that owns the game. A typed bank_account block is still accepted but must match one of those accounts. If you send both and they name different accounts, the request is 400 PAYOUT_BANK_ACCOUNT_DETAILS_MISMATCH.
What do the payout error codes mean?
PAYOUT_BANK_ACCOUNT_NOT_ON_FILE: no active bank account of the game's owning account matches. PAYOUT_BANK_ACCOUNT_NOT_VERIFIED: it exists but is not yet verified. PAYOUT_BANK_ACCOUNT_DETAILS_MISMATCH: the id and the details name different accounts. INSUFFICIENT_OWED_BALANCE: the amount is above what you are owed (the body carries owed_balance_usd and requested_amount_usd). All are 400 and nothing is created.
How is the owed balance calculated?
Your accrued revenue, less money already paid or claimed, less the account's pending withdrawals, other requested payouts and approved payouts in flight, and less any Merchant of Record reserve held.
In what order do payout.status_changed events move, and how do I handle skipped or repeated statuses?
Normally requested, approved, processing, completed (or failed). A requested creator payout can become cancelled, a requested creator payout can also be declined (rejected) if INVO stops paying that creator, and a completed payout becomes returned if the receiving bank sends it back. Statuses can be skipped or arrive twice, so dedupe deliveries, apply a status only if it is later than the one you have, and ignore repeats; use previous_status only to drop an older event, never as a required match.
When a payout fails with a failure_reason, is the amount owed to me again?
Yes. A failed payout's amount returns to your owed balance and can be requested again; failure_reason is always "Payout could not be sent. INVO will contact you."
Can INVO pay our creators?
Yes. Register each creator with POST /api/partner-payees. INVO emails the creator a link to INVO's own page, verifies their identity, tax and bank details directly, and tells you the outcome through payee.status_changed. Once a creator is verified, send POST /api/partner-payouts/request with payee_id and INVO pays them directly, as INVO's own payee, from the earnings INVO owes you, at the standard payout fee. You never see the creator's documents, tax id or bank details. The account owner can do the same in the INVO console (Payouts). Keep the game secret key on your server: INVO emails the account owner when a creator is registered with it or verified, and the first payout to such a creator waits for the owner's confirmation in the console.
Why was a creator payout refused with PAYEE_NOT_PAYABLE?
The creator can't be paid right now. No action is needed from you or the creator; try again later. The other refusals say more: PAYEE_NOT_VERIFIED means the creator is not verified right now (check their status: they may still be finishing, or INVO may be reviewing them), PAYEE_VERIFICATION_EXPIRED and PAYEE_BANK_NOT_VERIFIED mean INVO has asked the creator to verify again or to add a bank account, PAYEE_CLOSED means the creator is no longer in your program, and PAYEE_TERMS_NOT_ACCEPTED means the creator hasn't accepted INVO's current Payee Terms yet. Before you ask, the creator's payable field tells you whether INVO can pay them now.
What happens if a creator's bank returns a payment?
Once INVO confirms the return, the payout moves to returned with return_reason_code returned, and what the bank sent back is owed to your game again; the payout fee is not refunded. INVO contacts the creator about a new bank account, and payouts to them are refused until INVO verifies it.
Who issues the creator's tax form?
INVO. Creators verify directly with INVO, and INVO issues their year-end tax form. A creator payout is not counted as your own income on your INVO earnings statement.
How do I remove a creator from our program?
POST /api/partner-payees/{payee_id}/remove, or remove them in the console (Payouts). The creator's status becomes closed, INVO tells the creator, and you receive payee.status_changed. It is refused with 409 PAYEE_HAS_PAYOUTS_IN_FLIGHT while a payout to them is still being processed: a requested payout can be cancelled; otherwise wait until it completes, fails or is declined. Removing is not a block: you can register the same person again under a new partner_reference. A creator can also ask INVO to close their record.
Can a creator payout be cancelled?
Yes, while it is still requested: POST /api/partner-payouts/{payout_id}/cancel, or cancel it in the console (Payouts). INVO emails your account owner about every creator payout request. Once it is past requested the cancel returns 409 PAYOUT_NOT_CANCELLABLE; a payout to your own bank returns 404 NOT_FOUND.
Who do I contact about negotiated fee splits or custom contracts?
partners@invo.network. Negotiated rates appear in GET /api/dev/fee-schedule and in every fee field, so an integration that reads those needs no change. The transfer split is a network standard and is not negotiable.
Back to the FAQ hub. Something not answered here? Email partners@invo.network.