Re-invite a user
Re-sends or corrects an open invitation (users:manage) under If-Match, the version the re-invite replaces. A fresh deadline opens and the platform withdraws the outstanding invitation and sends anew; the body may restate the capabilities, name, address or lifetime, absent fields keeping the row’s. A row that is not INVITED refuses 409 ILLEGAL_TRANSITION.
Authentication
Bearer authentication of the form Bearer <token>, where token is your auth token.
Path parameters
The record’s id — a positive 32-bit integer the platform minted.
Headers
Required on every write: a URL-safe string of 1 to 64 characters from [A-Za-z0-9._~-] (a UUID fits), scoped to you. It names one operation on one record, ever: a retry replays the stored outcome (Idempotent-Replay: true) or attaches to the live one, and reuse on another record refuses 409 IDEMPOTENCY_KEY_REUSED. Missing or malformed, 400.
Required on every entity write: the ETag the read minted, quoted or bare — the version this write was computed against — or * to write unconditionally on purpose. Absent is refused 428 PRECONDITION_REQUIRED; a weak validator 400 INVALID_IF_MATCH; a stale value 412 VERSION_CONFLICT (CONFIG_SEQ_CONFLICT on an algo’s config write) with currentVersion and a fresh ETag: re-read, reapply, retry. Every write restates the whole record: a * write overwrites every field from your copy, a colleague’s amend since your read included. State the version unless you mean the overwrite.
Your own id for the request: 8 to 128 of [A-Za-z0-9._-]. It becomes the request’s id and is echoed on the response. A value off that grammar is replaced with a fresh id, never refused.
Request
0 = a new invitation; else the INVITED user to re-invite or resend to.
The capabilities the invitee holds from the moment they accept. a set (SBE bit-set) served as the array of its scope strings — each choice spelled <route family>:<verb> (the schema’s camel-cased choice name de-camelled: accountAddressesApprove is account-addresses:approve) — in declared order; empty = none set, never null. The choice set is append-only: a consumer READING this field skips an unknown name, never errors; as input an unknown or repeated name refuses 400 — the parse is strict
The platform name, unique among the organisation’s live users. Optional in this body: absent restates the row’s.
The address to invite, lowercased: ASCII, one @, at most 254 characters. Unique among the organisation’s invited and active users. Optional in this body: absent restates the row’s.
A named capability bundle the edge expands to its scope strings and never forwards — the row records bits, never a preset name: INITIATOR (the six maker-checker families’ propose bits), APPROVER (initiator plus their approve bits), ADMIN (approver plus users:manage and portfolios:manage), TRADER (orders:trade), TREASURY (the account, address and asset/chain policy families, both verbs), PLATFORM (orgs:propose and orgs:approve, inside the internal platform org only). Either preset or capabilities names the set; both stated must agree, else 400. x-immix-preset-capabilities is the expansion.
How long the fresh invitation stays claimable, in hours: 1 to 720, default 72.
Response
The user as the platform now holds it after the write — the same row the read serves, with the answering change’s position, the row’s ETag and, on a replayed key, Idempotent-Replay.
The user’s capabilities — what they may do; empty on a discovered row, and on an invited first administrator until the organisation is activated. a set (SBE bit-set) served as the array of its scope strings — each choice spelled <route family>:<verb> (the schema’s camel-cased choice name de-camelled: accountAddressesApprove is account-addresses:approve) — in declared order; empty = none set, never null. The choice set is append-only: a consumer READING this field skips an unknown name, never errors; as input an unknown or repeated name refuses 400 — the parse is strict
What the IdP stated at discovery (the name, else email, else nickname claim); informational, never a key.
The position as a decimal string — the last change this member had applied, orders, balance readings and algo instances included.
UNKNOWN is the unset sentinel: outputs only — as input, omit the field instead; explicit UNKNOWN refuses 400. The value set is append-only: a consumer READING this field treats an unknown name as UNKNOWN, never as an error; as input an unknown name refuses 400 — the parse is strict
Platform name — per-org unique among live users with a non-empty name; empty until admission.
Membership — stamped by the owner from the actor’s org, or from the discovery’s parent ref.
UNKNOWN is the unset sentinel: outputs only — as input, omit the field instead; explicit UNKNOWN refuses 400. The value set is append-only: a consumer READING this field treats an unknown name as UNKNOWN, never as an error; as input an unknown name refuses 400 — the parse is strict
The address the user was invited at, lowercased — the address a first login must have verified to claim the row, kept afterwards as the address the user was registered by. Empty on a row no invitation created. Unique among the organisation’s invited and active users (EMAIL_TAKEN).
The identity provider’s id for the invitation the platform created, as the platform reported it; informational, never a key; empty until reported.
The identity provider’s subject, opaque, never parsed: a token’s sub resolves to this row inside the token’s organisation. Empty = unbound (a locally authenticated user). Unique among all the organisation’s users, disabled included — a subject binds for the life of its row, and a second binding is refused IDP_REF_TAKEN.
Where the invitation stands: PENDING until the platform has created it with the identity provider, then SENT, ALREADY_MEMBER or FAILED; ACCEPTED once the invitee has signed in; NONE where none was created (a first administrator before activation). Kept after a cancel — an invitation is open while status is INVITED. NONE is the unset sentinel: outputs only — as input, omit the field instead; explicit NONE refuses 400. The value set is append-only: a consumer READING this field treats an unknown name as NONE, never as an error; as input an unknown name refuses 400 — the parse is strict
The deadline the row was last invited under: the inviting command’s position time plus its stated lifetime; absent — null in the API, 0 on the wire — on a row never invited. Kept after the claim and after a cancel — status and invitationState say whether an invitation is open. A first login after it is refused INVITATION_EXPIRED and a re-invite opens a fresh deadline. int64 as a decimal JSON string
Who proposed or invited this user: the maker on an organisation’s first administrator — stamped at the proposal, whether or not an email follows — and the inviter on an invited member; absent — null in the API, 0 on the wire — on a row created directly or discovered.
Never present since 0.3.3: every money value on this API states its own scale on the wire — a policy amount or cap since 0.3.3, an order’s and an execution’s since 0.3.2, a balance’s since 0.3.1 — so a row is never served raw, whether or not this member holds the asset or instrument it references. Kept, deprecated, so a client generated from 0.3.2 still compiles; it goes at the next major.