InfiniSynapse Partner Silent Provisioning Guide

This guide is for third-party developers who want to silently embed InfiniSynapse capabilities into their own products. Unlike "Sign in with InfiniSynapse" (see the InfiniSynapse Partner SSO Integration Guide), this approach never requires your users to log in or be redirected: your backend calls a set of M2M (server-to-server) APIs to automatically provision a dedicated InfiniSynapse sub-account and API key for each of your users, then calls the InfiniSynapse open APIs on their behalf.

After completing this integration you can:

  • Silently provision an independent InfiniSynapse sub-account for each of your users (completely invisible to them — no InfiniSynapse sign-up or login required);
  • Obtain a dedicated API key (starting with sk-) per sub-account and call InfiniSynapse open APIs (e.g. launching data-analysis tasks) from your backend on the user's behalf;
  • Keep every sub-account's data and tasks isolated, while all usage is billed to your main account (the InfiniSynapse account that created the integration app) — you simply keep the main account topped up; there is no need to fund each sub-account separately;
  • Rotate keys, disable sub-accounts, and query usage and the main-account balance for reconciliation at any time.

All you need is a backend that can send HTTP requests. There is no SDK dependency — any language works.

1. How it works

Your backend                      InfiniSynapse
   │                                  │
   │ ① Provision (once per user)      │
   │ ──── POST /users/provision ────▶│  Idempotent on (clientId, externalUserId):
   │ ◀─── { infiniUserId, apiKey } ──│  creates account + issues dedicated API key
   │                                  │
   │ ② Call open APIs (day-to-day usage)
   │ ── Authorization: Bearer sk-xxx ▶│  usage billed to your main account's balance
   │ ◀────────── result ─────────────│
  1. Provision: the first time you need InfiniSynapse for one of your users, call the provisioning endpoint once with that user's unique ID in your system (externalUserId). InfiniSynapse creates an independent sub-account and issues a dedicated API key. Repeated calls with the same externalUserId are idempotent — you always get the same sub-account and the same valid key, so retries are safe.
  2. Call: with the sk- key in hand, call InfiniSynapse open APIs from your backend. All sub-account usage is billed to your main account's balance — just keep your main account topped up in InfiniSynapse, and its balance serves as the shared funding source for all sub-accounts.

Sub-accounts cannot log in to the InfiniSynapse App by default (no password is set). They are purely backend-managed accounts with no separate wallet and cannot be topped up individually. API key calls are unaffected.

Billing model: sub-accounts share the main account's balance

  • Main account = the account you (the developer) used to log in to InfiniSynapse and create the integration app (clientId).
  • Usage from all your sub-accounts is deducted from the main account's balance (in the same order the main account itself uses: gift balance → subscription quota → paid balance).
  • You do not top up sub-accounts individually, and there is no separate prepaid pool; just keep the main account's balance sufficient.
  • Usage records are still kept per sub-account, so you can tell which user generated which consumption (see 4.5 for reconciliation).

2. Prerequisites: integration credentials

This flow shares the same credentials as Partner SSO: clientId + clientSecret. If you have already integrated "Sign in with InfiniSynapse", reuse your existing credentials — no new application needed.

If you don't have credentials yet:

  1. Log in to https://app.infinisynapse.com/tasks with your InfiniSynapse account (this account is the paying main account for all sub-account usage, so keep its balance sufficient);
  2. Click the "Settings" gear icon at the bottom left and choose Third-party integrations;
  3. Click Create integration app and fill in the app name (the callback-domain whitelist is only used by the login flow; any value is fine for this guide);
  4. On success, a dialog shows your clientId / clientSecret. The secret is shown only once — store it safely right away.

clientSecret is effectively your app's password. Keep it on your backend only (environment variables, secret managers, etc.). Never put it in frontend code, mobile clients, or public repositories. If you suspect a leak, reset it on the page immediately.

3. API basics

ItemValue
API base URL (China)https://api.infinisynapse.cn/api
API base URL (Global)https://api.infinisynapse.com/api
Authenticationrequest headers X-Client-Id + X-Client-Secret
Content typeapplication/json

All endpoints return a unified envelope:

{
  "code": 200,
  "message": "success",
  "data": { }
}

code === 200 means success with the payload in data; on failure message describes the error. Examples below use the .com domain — replace with .cn for the China region.

4. Core endpoints

4.1 Provision / fetch a sub-account and API key (idempotent)

Call this once the first time you need a given user, then cache the returned apiKey in your user table — no need to call it on every request.

POST /api/auth/partner/users/provision
X-Client-Id: partner_xxxxxxxx
X-Client-Secret: psk_xxxxxxxx
Content-Type: application/json

Request body:

FieldRequiredDescription
externalUserIdYesThe user's unique ID in your system (≤128 chars). It is the sub-account's mapping key — never change it once used
withApiKeyNoDefaults to true, issuing/reusing a dedicated API key; pass false to create the account only
profileNoOptional profile info for the account: email, nickname, avatar, phone

Response example:

{
  "code": 200,
  "message": "success",
  "data": {
    "infiniUserId": "68d21916d6802ec254b46975",
    "externalUserId": "your-user-123",
    "apiKey": "sk-xxxxxxxxxxxxxxxxxxxxxxxx",
    "created": true
  }
}
  • infiniUserId: the sub-account's unique ID in InfiniSynapse; store it alongside externalUserId in your user table;
  • created: true means a new account was created this time; false means it already existed (idempotent reuse);
  • Repeated calls with the same (clientId, externalUserId) always return the same sub-account and the same valid key. If the key was deleted or invalidated, a new one is issued automatically — so "just call provision again" is always a safe fallback.

4.2 Rotate an API key (leak response)

POST /api/auth/partner/users/apikey/rotate
Body: { "externalUserId": "your-user-123" }

Response data: { "infiniUserId": "...", "apiKey": "sk-newkey" }. The old key becomes invalid immediately — overwrite your cached value with the new one.

4.3 Disable a sub-account

POST /api/auth/partner/users/revoke
Body: { "externalUserId": "your-user-123" }

Response data: { "infiniUserId": "...", "status": "disabled" }. After disabling:

  • The sub-account's API key is deleted and can no longer call any API;
  • The sub-account is flagged as disabled; subsequent provision / rotate calls for it are rejected;
  • Disabling only affects that sub-account's ability to call APIs; it does not affect the main account's balance or other sub-accounts.

4.4 Query sub-account status

GET /api/auth/partner/users/{externalUserId}

Response data:

{
  "infiniUserId": "...",
  "externalUserId": "your-user-123",
  "status": "active",
  "hasApiKey": true,
  "created": 1751443200000,
  "lastProvisionAt": 1751443200000,
  "disabledAt": null
}

4.5 Query balance (reconciliation)

Since sub-accounts share the main account's funds, this endpoint returns the main account's currently available balance (the shared pool used by all your sub-accounts).

GET /api/auth/partner/users/{externalUserId}/balance

Response data:

{
  "infiniUserId": "...",
  "billingUserId": "main-account userId",
  "shared": true,
  "orderBalance": 128.5,
  "totalBalance": 128.5
}
  • billingUserId: the actual billing account, i.e. your main account;
  • orderBalance / totalBalance: the main account's available balance (paid balance + unexpired gift balance; excludes the daily subscription quota);
  • No matter which externalUserId you query with, orderBalance points to the same main-account balance.

4.6 List all your sub-accounts (paginated)

GET /api/auth/partner/users?page=1&pageSize=50&status=active
ParameterDescription
pagePage number, default 1
pageSizeItems per page, default 50, max 100
statusOptional, active / disabled

Response data:

{
  "list": [
    {
      "externalUserId": "your-user-123",
      "infiniUserId": "...",
      "status": "active",
      "hasApiKey": true,
      "createTime": 1751443200000,
      "lastProvisionAt": 1751443200000,
      "disabledAt": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 50
}

4.7 Query credit usage (per sub-account / per task, for reconciliation)

Even though deductions all land on the main account, usage records are still kept per sub-account, so you can see exactly "which user, on which task, consumed how many credits" — useful for internal cost allocation, metering, or risk control. Three query endpoints are provided.

The startTime / endTime parameters are millisecond timestamps; pass either, both, or neither (omit to query everything).

4.7.1 Sub-account usage details / grouped by task

GET /api/auth/partner/users/{externalUserId}/costs?page=1&pageSize=20&startTime=&endTime=&groupByTask=false
ParameterDescription
pagePage number, default 1
pageSizeItems per page, default 20, max 200
startTime / endTimeOptional, millisecond timestamp range
groupByTaskOptional; true aggregates by task (a parent task automatically merges its sub-agent usage); defaults to per-record details

By default (groupByTask=false), returns per-record details:

{
  "infiniUserId": "...",
  "externalUserId": "your-user-123",
  "groupByTask": false,
  "list": [
    { "taskId": "c3a2f9d0-...", "chatId": "...", "cost": 1.2, "model": "gpt-x", "createTime": 1751443200000 }
  ],
  "total": 37,
  "page": 1,
  "pageSize": 20
}

With groupByTask=true, each row is one task's total usage:

{
  "groupByTask": true,
  "list": [
    { "taskId": "c3a2f9d0-...", "totalCost": 5.8, "count": 6, "models": ["gpt-x"], "firstTime": 1751443200000, "lastTime": 1751443800000 }
  ],
  "total": 12,
  "page": 1,
  "pageSize": 20
}

4.7.2 Sub-account usage summary (total + per-model)

GET /api/auth/partner/users/{externalUserId}/cost-stats?startTime=&endTime=

Response data:

{
  "infiniUserId": "...",
  "externalUserId": "your-user-123",
  "totalCost": 42.6,
  "recordCount": 37,
  "modelStats": [
    { "model": "gpt-x", "cost": 30.1, "count": 20 },
    { "model": "gpt-y", "cost": 12.5, "count": 17 }
  ]
}

4.7.3 Client-level usage summary (all your sub-accounts)

Get a consumption ranking across all your sub-accounts in one call, for overall reconciliation:

GET /api/auth/partner/costs?page=1&pageSize=50&startTime=&endTime=
ParameterDescription
pagePage number, default 1
pageSizeItems per page, default 50, max 200
startTime / endTimeOptional, millisecond timestamp range

Response data (sorted by totalCost descending):

{
  "clientId": "partner_xxxxxxxx",
  "grandTotalCost": 128.9,
  "subAccountCount": 25,
  "list": [
    { "externalUserId": "your-user-123", "infiniUserId": "...", "totalCost": 42.6, "recordCount": 37 },
    { "externalUserId": "your-user-456", "infiniUserId": "...", "totalCost": 30.2, "recordCount": 21 }
  ],
  "total": 18,
  "page": 1,
  "pageSize": 50
}
  • grandTotalCost: total usage of all your sub-accounts within the time range (matches what was deducted from the main account);
  • subAccountCount: total number of your sub-accounts;
  • total: number of sub-accounts with usage (those with none are not included in the paginated list).

5. Calling InfiniSynapse open APIs with the key

With a sub-account's sk- key you can call open APIs on the user's behalf from your backend. Task-related open APIs live on the App service domain (note: different from the api. domain used by the M2M endpoints above): https://app.infinisynapse.cn in China, https://app.infinisynapse.com globally.

Example: launch a data-analysis task on behalf of a user

POST https://app.infinisynapse.com/api/ai/message
Authorization: Bearer sk-xxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

{
  "type": "newTask",
  "taskId": "c3a2f9d0-a-uuid-you-generate-for-idempotency",
  "text": "Analyze the last 7 days of sales data and produce a chart report",
  "images": []
}

Generate taskId on your backend (UUID recommended); resubmitting the same taskId will not create duplicate tasks. The task belongs to this sub-account (data/task isolation), while its usage is deducted from your main account's balance.

Tip: set up a low-watermark alert on your main account's balance (poll the 4.5 endpoint periodically). An empty balance will limit calls for all sub-accounts.

6. Security notes

  1. Keep clientSecret and all sk- keys on the backend only. They are long-lived credentials and must never reach browsers, mobile clients, or public repositories.
  2. One key maps to exactly one sub-account, so a leak's blast radius is limited to that sub-account's own data. On any anomaly, call rotate immediately, or revoke to disable the account.
  3. The main account's balance is a shared pool used by all your sub-accounts. Implement your own usage monitoring and quota controls so that one abnormal user cannot drain the whole balance.
  4. Never change an externalUserId once used — it is the sub-account's unique mapping key; a new ID means a new account.
  5. Silent provisioning means you create accounts on your users' behalf: you are responsible for your users' data authorization and compliance. Collect the minimum necessary profile fields.
  6. The provisioning endpoint is rate-limited and each app has a sub-account cap; normal business volume won't hit them, but contact us in advance for bulk imports.
  7. If a secret may have leaked, reset clientSecret right away on the Settings → Third-party integrations page (the old secret becomes invalid immediately).

7. Endpoint quick reference

EndpointMethodPurpose
/api/auth/partner/users/provisionPOSTProvision / fetch a sub-account and API key (idempotent)
/api/auth/partner/users/apikey/rotatePOSTRotate a sub-account's API key (old key invalidated immediately)
/api/auth/partner/users/revokePOSTDisable a sub-account (delete key + flag disabled)
/api/auth/partner/users/{externalUserId}GETQuery sub-account status
/api/auth/partner/users/{externalUserId}/balanceGETQuery main-account available balance (reconciliation)
/api/auth/partner/usersGETList your sub-accounts (paginated)
/api/auth/partner/users/{externalUserId}/costsGETQuery sub-account usage details (optionally grouped by task)
/api/auth/partner/users/{externalUserId}/cost-statsGETQuery sub-account usage summary (total + per-model)
/api/auth/partner/costsGETClient-level usage summary (ranking across all sub-accounts)

All endpoints authenticate via the X-Client-Id + X-Client-Secret request headers.

8. Complete example (Node.js)

A minimal runnable example covering the full chain "provision → launch a task on the user's behalf" (funded automatically by the main account's balance):

const PROXY_API = 'https://api.infinisynapse.com/api'
const APP_API = 'https://app.infinisynapse.com/api'
const partnerHeaders = {
  'Content-Type': 'application/json',
  'X-Client-Id': process.env.INFINI_CLIENT_ID,
  'X-Client-Secret': process.env.INFINI_CLIENT_SECRET,
}

async function callPartner(path, options = {}) {
  const resp = await fetch(`${PROXY_API}${path}`, { headers: partnerHeaders, ...options })
  const json = await resp.json()
  if (json.code !== 200) throw new Error(`${path} failed: ${json.message}`)
  return json.data
}

// 1. First time you need a user: provision the sub-account and cache the apiKey
//    (idempotent, safe to retry)
async function ensureInfiniAccount(user) {
  const data = await callPartner('/auth/partner/users/provision', {
    method: 'POST',
    body: JSON.stringify({
      externalUserId: user.id,
      profile: { nickname: user.nickname, email: user.email },
    }),
  })
  // Persist data.infiniUserId / data.apiKey in your user table
  return data
}

// 2. Launch an analysis task on the user's behalf (billed to the main account)
async function createTask(apiKey, text) {
  const resp = await fetch(`${APP_API}/ai/message`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${apiKey}`,
    },
    body: JSON.stringify({ type: 'newTask', taskId: crypto.randomUUID(), text, images: [] }),
  })
  return resp.json()
}

// Putting it together
const { apiKey } = await ensureInfiniAccount({ id: 'your-user-123', nickname: 'Alice' })
await createTask(apiKey, 'Analyze the last 7 days of sales data and produce a chart report')

9. Relationship with "Sign in with InfiniSynapse"

The two integration paths coexist and complement each other, sharing the same clientId / clientSecret:

Partner SSO loginSilent provisioning (this guide)
Does the user log in to InfiniSynapse?Yes (one authorization-code login)No — completely invisible
Account ownershipThe user's own InfiniSynapse accountAn independent sub-account managed by you
BillingThe user's own balance / subscriptionBilled entirely to your main account's balance
Best forUsers who have or are willing to create an InfiniSynapse accountBundling InfiniSynapse capabilities into your product without users ever noticing

10. FAQ

Q: Whose account is sub-account usage billed to? Your main account (the InfiniSynapse account you used to create the integration app). All your sub-accounts share this single funding pool; you just keep the main account topped up.

Q: Do I need to top up each sub-account individually? No. Sub-accounts have no separate wallet and cannot be topped up individually; all funds come from the main account's balance.

Q: Will repeated provision calls create duplicate accounts or multiple keys? No. The same externalUserId always maps to the same sub-account and the same valid key. The endpoint is idempotent and safe to retry; if you lose a cached key, just call provision again to recover it.

Q: Can a sub-account log in to the InfiniSynapse App? Not by default (no password is set). It is a purely backend-managed account; API key calls are unaffected.

Q: What happens when the main account's balance runs out? Calls from all your sub-accounts become limited by balance/quota. Combine the balance endpoint in 4.5 with low-watermark monitoring to top up the main account in time.

Q: How do I know how much each user consumed? Usage records are kept per sub-account (infiniUserId), while the deduction always lands on the main account. Use the usage-query endpoints in 4.7 for precise reconciliation: per-sub-account details / grouped by task (4.7.1), a per-sub-account summary (4.7.2), or a one-shot consumption ranking across all your sub-accounts (4.7.3).

Q: What should I use as externalUserId? A stable, immutable primary key from your system (e.g. a database ID). Avoid emails or phone numbers that may change.

InfiniSynapse Partner Silent Provisioning Guide