Skip to content
InfluToDocs

Reference

Limits and errors

Rate limits, request size, SDK error types and codes, HTTP status codes for the SDK API, webhooks and the agent API, and the rules for codes and app slugs.

This page collects every limit and error you can run into: how fast you can call InfluTo, what each SDK throws, what each status code means, and the format rules for codes and app slugs. For the endpoints themselves, see the HTTP API; for the methods, the SDK reference.

Rate limits

What Limit Over the limit
SDK API (/api/sdk/*) and referral links Per IP address, set well above what a real app or campaign produces — including many users behind one mobile-carrier address 429
MCP tool calls 240 per minute per connected account The tool call fails with an error that starts with 429
MCP sign-in and client registration Per IP address 429
  • If you get a 429, back off and retry; a script calling in a tight loop is the usual cause.
  • identify is de-duplicated on the server: the same SDK key and user ID within 60 seconds is answered without doing the work again ("deduplicated": true). Call it once per launch, never from a render loop.
  • The RevenueCat webhook and the agent REST API have no per-request limit; the agent API has invite limits instead.

Request size

  • Every request body is limited to 20 MB; larger requests get 413.
  • Asset uploads in the dashboard (Assets) are limited to 20 MB per file.

What throws and what fails soft

Only initialize and reportPurchase throw on network and server errors. The rest return a safe value, so a slow or failed request never crashes your app.

Method On failure
initialize Throws
reportPurchase Throws
checkAttribution { attributed: false, message: "Error checking attribution" }, not stored, retried next launch. Throws when called before initialize succeeded (iOS returns attributed: false instead).
identifyUser, trackEvent Nothing (logged when debug is on)
getActiveCampaigns []
validateCode { valid: false, error_code: "NETWORK_ERROR" }
setReferralCode { success: false, message: … }
applyCode The validation result with applied: false
checkAccess { hasAccess: false }
Automatic capture Failed reports are counted in failed and retried on a later back-sync. React Native's enableAutoPurchaseCapture and syncExistingPurchases throw when called before initialize.

SDK error types

Platform Thrown type What it carries
React Native Error Message API request failed: <status> - <body>, or InfluTo SDK not initialized. Call InfluTo.initialize() first.
iOS InfluToError .notInitialized; .notConfigured(String) for any 400; .retryable(status:) for any 5xx, including 503; .http(status:body:) for other statuses; .decoding(Error); .transport(Error)
Android InfluToError (sealed, an Exception) NotInitialized; Server(status, body) with retryable (status 500 or higher) and notConfigured (status 400); Transport(cause); Decoding(cause)
Flutter InfluToException statusCode, body, message; retryable (500 or higher), notConfigured (400). Network failures have no statusCode.
Web InfluToApiError status, body, message for any non-2xx answer. Other failures — not initialized, no apiKey, reportPurchase without platform in a browser — throw a plain Error.

notConfigured covers every 400 from /sdk/purchase: the platform isn't switched to store-direct yet, or the proof is missing or failed verification. A 503 means the exchange rate wasn't available; retry later.

TypeScript
try {
  await InfluTo.reportPurchase({ platform: 'android', purchaseToken });
} catch (e) {
  if (String(e).includes('failed: 503')) scheduleRetry();
}
Swift
do {
    _ = try await InfluTo.reportPurchase(jws: jws)
} catch InfluToError.retryable(let status) {
    scheduleRetry(after: status)
} catch {
    print("InfluTo:", error)
}
Kotlin
try {
    InfluTo.reportPurchase(purchaseToken = purchase.purchaseToken)
} catch (e: InfluToError.Server) {
    if (e.retryable) scheduleRetry()
}
Dart
try {
  await InfluTo.instance.reportPurchase(platform: 'android', purchaseToken: token);
} on InfluToException catch (e) {
  if (e.retryable) scheduleRetry();
}
TypeScript
import InfluTo, { InfluToApiError } from '@influto/web';

try {
  await InfluTo.reportPurchase({ platform: 'android', purchaseToken });
} catch (e) {
  if (e instanceof InfluToApiError && e.status === 503) scheduleRetry();
}

Code validation errors

validateCode and applyCode return these in error_code (React Native, web) or errorCode (iOS, Flutter as a string; Android as the CodeErrorCode enum, which adds UNKNOWN).

Code When Server text in error
INVALID_FORMAT Fewer than 4 or more than 20 characters after cleanup Code must be 4-20 characters
CODE_NOT_FOUND No active creator code in an active campaign, and no free-access code, matches Code not found or inactive
CODE_EXPIRED A free-access code that expired or has no seats left Code expired or usage limit reached
NETWORK_ERROR Set by the SDK: the request failed, or the SDK isn't initialized Network error or invalid response or SDK not initialized

/sdk/set-referral-code can also answer MISSING_USER_ID for a free-access code sent without a user ID. The SDKs' SetCodeResult doesn't expose the code; you get success: false and the message "Could not identify your account. Please try again."

HTTP status codes for /api/sdk/*

Status Meaning Endpoints
200 Success. "Not attributed", "invalid code" and "duplicate" are all 200 answers — read the body. All
400 Empty app_user_id; or, on /sdk/purchase, the platform isn't store-direct, credentials are missing, the proof is missing or failed verification, or the platform isn't ios/android identify, access, recent-conversions, purchase
401 Missing, malformed, unknown or deactivated SDK key All
404 Unknown or inactive code set-referral-code
409 Android one-time purchase not in the PURCHASED state purchase
413 Body larger than 20 MB All
422 A required field or query parameter is missing or has the wrong type All
429 Rate limit All
500 Unexpected server error All
503 Exchange rate unavailable — retry later purchase

The store-direct 400 is intentional: until you switch the platform to store-direct, and that switch needs a green credential check, the endpoint rejects reports. So it's safe to ship the SDK first.

RevenueCat webhook responses

Status Meaning
200 Accepted. If processing failed, the body also has "error"; the event isn't retried by RevenueCat or by InfluTo.
400 The body isn't valid JSON
401 Missing or wrong Authorization value. The body says how to fix it, and the Setup page shows a warning.
404 No app with the ID in the URL

A low wallet balance is not a webhook error: the conversion is still recorded. See RevenueCat and inbound webhooks.

Agent API and MCP

The agent REST API (/api/agent/*) and the MCP tools answer with these statuses; an MCP tool error's text starts with the status.

Status Meaning
400 Invalid input, for example a batch of more than 500 invites
401 Missing, invalid, expired or revoked agent key or token
402 Not enough unreserved wallet balance: activating a campaign and sending email invites need at least $50; marketplace invites need $20 per open invite
403 The key or token lacks the scope, or the action is closed to agents (money, payouts, credentials, admin)
404 Not found — also returned for anything outside the organizations you granted, so nothing leaks
429 More than 240 MCP tool calls in a minute, or an invite limit: 100 email invites per organization per 24 hours, or one open marketplace invite per $20 of unreserved balance

Details: MCP tools, scopes and REST API.

Code format

Creator referral codes (the code in influ.to/{app_slug}/{CODE}):

  • 4–20 characters: A–Z, 0–9, _ and -. Stored uppercase.
  • Not one of ADMIN, TEST, API, SYSTEM, NULL, ROOT, DELETE, REMOVE.
  • Can't start with INFLU-, which is reserved for creator access codes InfluTo issues itself.

Free-access codes you create on Free Access Codes: the same characters and length, uppercase, unique across InfluTo, and also never starting with INFLU-.

When a user types a code, the SDK trims and uppercases it. The server then ignores spaces and any other character outside the alphabet when it looks the code up, and checks creator codes before free-access codes. The SDK stores and sends to RevenueCat the code it was given, so clean the input in your field — see building your own field.

App slug

The slug is the first part of your referral links, influ.to/{app_slug}/{CODE}.

  • 3–20 characters: lowercase letters, digits and - (the dashboard enforces this as you type).
  • Unique across InfluTo, and not one of the names the site itself uses (such as api, dashboard or a language code). My Apps → Add App checks availability as you type.