Provisioning gives you an account. This is how you operate it.
An account you provisioned has no human attached, so there is nobody who can sign into our dashboard to configure a character or issue a conversation credential. The connected-app credential closes that: two headers on a FluidTalk call, and you act as the owner of that account.
POST https://api-talk.fluidvip.com/api/strategy/…
X-Partner-Key: fv_pk_… which app is asking
X-Partner-Account: 9c1f4b7e-… which account it is asking about
Both headers, every time. A partner key on its own does not say which of your accounts you mean, and there is no default. The account is the
owner_idyou were given at provision time.
Why two headers and not a token
Your key is the same one the account plane uses, and it stays on your server. The account id is not a secret — it is derived under a salt you do not hold and it names one of your own customers — so naming it in a header costs nothing and means there is no second credential to mint, store, rotate or leak.
FluidTalk does not decide whether you are allowed. It asks FluidAccount, on every request:
FluidTalk ──X-Service-Key──> POST /api/partner-grant/verify {partner_key, owner_id}
├─ {"authorised": true, "partner_id": "…", "partner_slug": "…"}
└─ {"authorised": false, "reason": "unknown_key|suspended|no_grant|revoked"}
The reason never reaches you — all four answer identically. FluidAccount owns the partner record and the grant, so it owns the answer; FluidTalk holds no copy of the grant table that could go stale against it.
::: warning There is no cached "last good" answer.
If FluidAccount cannot be reached, the request is refused — it does not fall back to a previous
yes. A cache of last-good answers would mean a revoked partner keeps access for the length of an
outage, and a revocation your customer just performed is exactly the thing that must not be
survivable. Expect 503 partner_auth_unavailable during an outage rather than degraded access.
:::
What you become
The context resolves to the owner of that one account. In practice:
| Every character, engine, binding and connector-token route | filters on that account |
| Usage you generate | billed to the customer's wallet, at their plan's rate — never yours |
| Your identity in that request | a synthetic partner:<id>, not a person |
That last row is what stops the credential drifting into things it was never meant to reach. Anything keyed on a real human's session cannot match a synthetic id — platform administration and team management both key that way, so neither is reachable, by construction rather than by a denylist someone has to remember to extend.
::: danger The customer pays, not you. Billing attribution is set to the account, not the partner. This is the commercial shape of the whole model — your customers' usage is billed to their own accounts at their own tier. If it were ever set to the partner, every one of your customers' inference bills would silently land on you. :::
The two things you will actually do
1. Configure a character
The ordinary character, engine and binding routes under /api/strategy/ work exactly as they do for
a signed-in owner. Nothing about their behaviour changes because a partner asked.
2. Issue a connector token
This is the one that unblocks conversations. A connector token is the credential the Characters API takes, and until now it could only be created by a human in the dashboard.
curl -X POST \
https://api-talk.fluidvip.com/api/strategy/characters/{character_id}/connector-token \
-H "X-Partner-Key: fv_pk_…" \
-H "X-Partner-Account: 9c1f4b7e-2a58-5d03-b6e1-77af0c9d3218"
The token is revealed once, exactly like your partner key — only its hash is stored. Calling again rotates it, which invalidates the previous one. Store it when you receive it.
::: tip Conversations do not use these headers.
Once you hold a connector token, you drive /api/v1/characters/* with X-Connector-Token and the
partner headers play no part. That separation is structural: the conversation routes do not resolve a
partner credential at all, so no message you send depends on FluidAccount being reachable.
:::
What you cannot do this way
Stated plainly, because two of these will look like bugs otherwise.
| You cannot | Why |
|---|---|
| Reach FluidCloud-backed features | The context carries no user assertion that could be replayed to Cloud, so anything requiring a Cloud tenant refuses. Photo features that depend on Cloud are not reachable through a partner context |
| Manage team members or invitations | Keyed on a real human's identity, which a synthetic partner id cannot match |
| Act as a platform administrator | The operator allowlist holds ordinary user ids; a partner id can never be one |
| Read or spend the account's balance | Balance lives behind a different credential — see Billing |
| Act for an account you did not provision, or one whose owner revoked you | 403, and the message never says which |
Errors
| Status | error |
Meaning |
|---|---|---|
403 |
— | Not authorised to act for that account: unknown key, suspended partner, revoked grant, or never connected. One opaque message for all four — the response can never be used to enumerate accounts or keys |
503 |
partner_plane_disabled |
The partner plane is off on this deployment, or this service is not wired to the authority. Permanent until an operator changes it — do not retry in a loop |
503 |
partner_auth_unavailable |
The authority could not be reached. Transient; retry |
429 |
— | Rate limited. Carries Retry-After |
Two independent rate limits protect this path: a local per-credential cap that refuses before any
cross-service call is made, and the authority's own cap, whose 429 and Retry-After are relayed to
you unchanged.
::: warning partner_plane_disabled is not something you can wait out.
It means PARTNER_PROVISIONING_ENABLED is off at FluidAccount, or ACCOUNT_API_BASE_URL is unset on
the FluidTalk deployment you are pointed at. Both are operator decisions and neither resolves on its
own. Ask your Fluid contact which environment you are on rather than retrying.
:::
Related
- Creating a customer account — where the
owner_idcomes from - The config panel — letting your customer configure it themselves
- Limits and failures — every cap in one place
- Characters API — what a connector token is for