CredentialRow
A credential as the API serves it: the `CredentialUpdated` record, the row extras (`globalSequence`; the deprecated `unscaled`, never present since 0.3.3) and the credential's `health` — the one shape its reads and its commands answer.
Properties
| Name | Type | Description |
|---|---|---|
| credentialId | integer | Sticky entity key. |
| version | string | Monotonic per entity. int64 as a decimal JSON string |
| orgId | integer | Owner-stamped. |
| status | object | 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 UNKN |
| providerKind | object | 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 UNKN |
| exchangeId | integernull | The refdata exchange for an EXCHANGE-kind credential — carried, not resolved here; a credential that can trade must name one (MISSING_VENUE); 0 = no venue. |
| canReadBalances | boolean | Whether the key may read balances. a boolean; absent reads false |
| canExecuteTransfers | boolean | Whether the key may execute transfers. a boolean; absent reads false |
| canServeAddresses | boolean | Whether the key may serve deposit addresses. a boolean; absent reads false |
| canTrade | boolean | Capability boolean: an order routes through its account's trading pipe — the account's designated tradingCredentialId, else its own credential — which must be ACTIVE and carry canTrade. Any number of |
| keyCreatedAtNs | stringnull | Key metadata: when the venue key was minted; 0 = not stated. int64 as a decimal JSON string |
| rotateByNs | stringnull | Governance deadline for rotation; a breach is an ops alert; 0 = none. int64 as a decimal JSON string |
| pendingByUserId | integernull | The user whose proposal is pending, so an approver is checked to be someone else; 0 when nothing is pending. |
| pendingTransition | object | ACTIVATE, AMEND (capabilities/secretRef), REACTIVATE, REVOKE or ROTATE; NONE otherwise. NONE is the unset sentinel: outputs only — as input, omit the field instead; explicit NONE refuses 400. The valu |
| observedPermissions | array | The observed axis: the key scopes the venue stated to the probing connector, parsed by name; empty until a probe answers. a set (SBE bit-set) served as the array of its set choice names in declared or |
| observedAllowlist | object | The probe's allowlist verdict against the cluster's egress set; UNKNOWN until a probe answers. UNKNOWN is the unset sentinel: outputs only — as input, omit the field instead; explicit UNKNOWN refuses |
| probeOutcome | object | UNKNOWN = never probed; NONE = the venue's key-restrictions read answered; else the probe's own failure in the credential or gate band. UNKNOWN is the unset sentinel: outputs only — as input, omit the |
| probedAtNs | stringnull | Consensus time of the probe report this row records — owner-stamped; 0 = never probed. int64 as a decimal JSON string |
| observedKeyCreatedAtNs | stringnull | The key creation time the venue stated to the probe; 0 = the venue states none, or never probed. int64 as a decimal JSON string |
| scopeUnobserved | boolean | TRUE = the probe answered but its venue serves no read of the key's own scope (Binance Demo Mode has no /sapi), so observedPermissions is empty because nothing stated it — the approval's scope edges a |
| name | string | Natural key — per-org unique among live credentials. |
| secretRef | string | LOGICAL credential name (okx-account-prod) — never a store path or provider URI; resolution happens only at the owning connector's edge. |
| venueKeyId | string | The venue's identifier for the key — metadata, not material. |
| keyFingerprint | string | The credential's fingerprint as the intake computed it — fp- and the first 16 hex characters of SHA-256 over the canonical payload — the pin a connector adopts the material at: enough to prove a cutov |
| appGroup | string | The connector app group serving this credential (desk 5-as-amended, okx-oe D-E17): the assignment rides the row — one group per credential by construction, empty = unassigned (no connector serves it; |
| observedKeyId | string | The venue-facing key identifier the probing connector resolved (the public half, never the secret); empty until a probe answers. |
| observedKeyFingerprint | string | The fingerprint of the material the probe adopted — compare with keyFingerprint, the intake's pin; empty until a probe answers. |
| venueAccountRef | string | The venue's account identifier behind the key (OKX uid); empty when the venue states none or no probe answered. |
| permissionDetail | string | The venue's own permission string, verbatim (not a secret); empty until a probe answers. |
| allowlistDetail | string | The venue's own allowlist, verbatim (IP addresses are not secrets); empty when none or no probe answered. |
| probeDetail | string | Redacted diagnostic text for a non-NONE probe outcome; empty-not-null. |
| globalSequence | object | |
| unscaled | boolean | 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 |
| health | object | The latest report from the connector serving this credential, or null when no connector has reported on it. It is observed, not decided: it changes without the row's `version` moving, and it reads the |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/immix/json-schema/immix-credential-row-schema.json",
"title": "CredentialRow",
"description": "A credential as the API serves it: the `CredentialUpdated` record, the row extras (`globalSequence`; the deprecated `unscaled`, never present since 0.3.3) and the credential's `health` — the one shape its reads and its commands answer.",
"x-generated": "2026-10-29",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/immix-rest-openapi.json#/components/schemas/CredentialRow",
"type": "object",
"properties": {
"credentialId": {
"type": "integer",
"description": "Sticky entity key."
},
"version": {
"type": "string",
"pattern": "^-?[0-9]+$",
"description": "Monotonic per entity. int64 as a decimal JSON string"
},
"orgId": {
"type": "integer",
"description": "Owner-stamped."
},
"status": {
"$ref": "#/$defs/CredentialUpdatedStatus",
"description": "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"
},
"providerKind": {
"$ref": "#/$defs/CredentialUpdatedProviderKind",
"description": "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"
},
"exchangeId": {
"type": [
"integer",
"null"
],
"description": "The refdata exchange for an EXCHANGE-kind credential — carried, not resolved here; a credential that can trade must name one (MISSING_VENUE); 0 = no venue."
},
"canReadBalances": {
"type": "boolean",
"description": "Whether the key may read balances. a boolean; absent reads false"
},
"canExecuteTransfers": {
"type": "boolean",
"description": "Whether the key may execute transfers. a boolean; absent reads false"
},
"canServeAddresses": {
"type": "boolean",
"description": "Whether the key may serve deposit addresses. a boolean; absent reads false"
},
"canTrade": {
"type": "boolean",
"description": "Capability boolean: an order routes through its account's trading pipe — the account's designated tradingCredentialId, else its own credential — which must be ACTIVE and carry canTrade. Any number of trading credentials may share one (org × venue) — one venue key per sub-account. a boolean; absent reads false"
},
"keyCreatedAtNs": {
"type": [
"string",
"null"
],
"pattern": "^-?[0-9]+$",
"description": "Key metadata: when the venue key was minted; 0 = not stated. int64 as a decimal JSON string"
},
"rotateByNs": {
"type": [
"string",
"null"
],
"pattern": "^-?[0-9]+$",
"description": "Governance deadline for rotation; a breach is an ops alert; 0 = none. int64 as a decimal JSON string"
},
"pendingByUserId": {
"type": [
"integer",
"null"
],
"description": "The user whose proposal is pending, so an approver is checked to be someone else; 0 when nothing is pending."
},
"pendingTransition": {
"$ref": "#/$defs/CredentialUpdatedPendingTransition",
"description": "ACTIVATE, AMEND (capabilities/secretRef), REACTIVATE, REVOKE or ROTATE; NONE otherwise. 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"
},
"observedPermissions": {
"type": "array",
"items": {
"$ref": "#/$defs/CredentialUpdatedObservedPermissionsItem"
},
"description": "The observed axis: the key scopes the venue stated to the probing connector, parsed by name; empty until a probe answers. a set (SBE bit-set) served as the array of its set choice names 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"
},
"observedAllowlist": {
"$ref": "#/$defs/CredentialUpdatedObservedAllowlist",
"description": "The probe's allowlist verdict against the cluster's egress set; UNKNOWN until a probe answers. 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"
},
"probeOutcome": {
"$ref": "#/$defs/CredentialUpdatedProbeOutcome",
"description": "UNKNOWN = never probed; NONE = the venue's key-restrictions read answered; else the probe's own failure in the credential or gate band. 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"
},
"probedAtNs": {
"type": [
"string",
"null"
],
"pattern": "^-?[0-9]+$",
"description": "Consensus time of the probe report this row records — owner-stamped; 0 = never probed. int64 as a decimal JSON string"
},
"observedKeyCreatedAtNs": {
"type": [
"string",
"null"
],
"pattern": "^-?[0-9]+$",
"description": "The key creation time the venue stated to the probe; 0 = the venue states none, or never probed. int64 as a decimal JSON string"
},
"scopeUnobserved": {
"type": "boolean",
"description": "TRUE = the probe answered but its venue serves no read of the key's own scope (Binance Demo Mode has no /sapi), so observedPermissions is empty because nothing stated it — the approval's scope edges are not applied, and the row says so. FALSE (the fail-safe decode, and every pre-v8 frame) = the scope, as observed, is the venue's word and is judged. a boolean; absent reads false"
},
"name": {
"type": "string",
"description": "Natural key — per-org unique among live credentials."
},
"secretRef": {
"type": "string",
"description": "LOGICAL credential name (okx-account-prod) — never a store path or provider URI; resolution happens only at the owning connector's edge."
},
"venueKeyId": {
"type": "string",
"description": "The venue's identifier for the key — metadata, not material."
},
"keyFingerprint": {
"type": "string",
"description": "The credential's fingerprint as the intake computed it — fp- and the first 16 hex characters of SHA-256 over the canonical payload — the pin a connector adopts the material at: enough to prove a cutover, never enough to sign. Empty on a row seeded before the intake."
},
"appGroup": {
"type": "string",
"description": "The connector app group serving this credential (desk 5-as-amended, okx-oe D-E17): the assignment rides the row — one group per credential by construction, empty = unassigned (no connector serves it; fail-safe). Replaces the compile-time CredentialAssignments table."
},
"observedKeyId": {
"type": "string",
"description": "The venue-facing key identifier the probing connector resolved (the public half, never the secret); empty until a probe answers."
},
"observedKeyFingerprint": {
"type": "string",
"description": "The fingerprint of the material the probe adopted — compare with keyFingerprint, the intake's pin; empty until a probe answers."
},
"venueAccountRef": {
"type": "string",
"description": "The venue's account identifier behind the key (OKX uid); empty when the venue states none or no probe answered."
},
"permissionDetail": {
"type": "string",
"description": "The venue's own permission string, verbatim (not a secret); empty until a probe answers."
},
"allowlistDetail": {
"type": "string",
"description": "The venue's own allowlist, verbatim (IP addresses are not secrets); empty when none or no probe answered."
},
"probeDetail": {
"type": "string",
"description": "Redacted diagnostic text for a non-NONE probe outcome; empty-not-null."
},
"globalSequence": {
"$ref": "#/$defs/GlobalSequenceValue"
},
"unscaled": {
"type": "boolean",
"description": "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.",
"deprecated": true
},
"health": {
"oneOf": [
{
"$ref": "#/$defs/ConnectionHealth"
},
{
"type": "null"
}
],
"description": "The latest report from the connector serving this credential, or null when no connector has reported on it. It is observed, not decided: it changes without the row's `version` moving, and it reads the same on both views. Judge it by `reportedAtNs`: a serving connector restates its report on a heartbeat, so a time that stops advancing means nothing is reporting on the credential any more."
}
},
"required": [
"credentialId",
"version",
"orgId",
"status",
"providerKind",
"pendingTransition",
"name",
"secretRef",
"venueKeyId",
"keyFingerprint",
"globalSequence",
"health"
],
"$defs": {
"ConnectionHealth": {
"type": "object",
"properties": {
"credentialId": {
"type": "integer",
"description": "The credential the report is about."
},
"status": {
"$ref": "#/$defs/ConnectionHealthStatus",
"description": "Whether a connector is serving the credential: CONNECTED serves, DEGRADED serves impaired, DOWN does not serve, dialing and redialing 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"
},
"reason": {
"$ref": "#/$defs/ConnectionHealthReason",
"description": "Why the status is what it is; NONE when nothing is wrong. 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"
},
"sinceNs": {
"type": "string",
"pattern": "^-?[0-9]+$",
"description": "When the current status and reason began, on the connector's own clock. int64 as a decimal JSON string"
},
"venueRoundTripNs": {
"type": [
"string",
"null"
],
"pattern": "^-?[0-9]+$",
"description": "The latest round trip to the venue the connector measured; 0 = not measured. int64 as a decimal JSON string"
},
"transitionAtNs": {
"type": "string",
"pattern": "^-?[0-9]+$",
"description": "Platform time the current status began. A restatement leaves it, and so does a change of reason alone, so the time since it is how long the credential has been in this status. int64 as a decimal JSON string"
},
"reportedAtNs": {
"type": "string",
"pattern": "^-?[0-9]+$",
"description": "Platform time of the latest report. A connector serving the credential restates its report on a heartbeat, so a time that stops advancing means nothing is reporting on it any more. int64 as a decimal JSON string"
},
"detail": {
"type": "string",
"description": "What the connector or the venue said, for people: display it, do not parse it. Empty when there is nothing to add."
}
},
"required": [
"credentialId",
"status",
"reason",
"sinceNs",
"transitionAtNs",
"reportedAtNs",
"detail"
],
"title": "ConnectionHealth"
},
"ConnectionHealthReason": {
"type": "string",
"enum": [
"UNKNOWN",
"NONE",
"AUTH_FAILED",
"IP_NOT_WHITELISTED",
"PERMISSION_DENIED",
"RATE_LIMITED",
"VENUE_UNREACHABLE",
"STARTUP",
"RECONNECT",
"HEARTBEAT_TIMEOUT",
"VENUE_MAINTENANCE",
"BACKPRESSURE",
"RESYNC",
"SHUTDOWN",
"FAILOVER",
"LAGGING",
"RECOVERED",
"INVALID_KEY",
"CLOCK_SKEW",
"CONFIG_ERROR",
"STREAM_STALE",
"VENUE_UNAVAILABLE"
],
"description": "Why the status is what it is; NONE when nothing is wrong. 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",
"title": "ConnectionHealthReason"
},
"ConnectionHealthStatus": {
"type": "string",
"enum": [
"UNKNOWN",
"CONNECTED",
"DEGRADED",
"DOWN"
],
"description": "Whether a connector is serving the credential: CONNECTED serves, DEGRADED serves impaired, DOWN does not serve, dialing and redialing 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",
"title": "ConnectionHealthStatus"
},
"CredentialUpdatedObservedAllowlist": {
"type": "string",
"enum": [
"UNKNOWN",
"NONE",
"COVERS",
"MISSES"
],
"description": "The probe's allowlist verdict against the cluster's egress set; UNKNOWN until a probe answers. 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",
"title": "CredentialUpdatedObservedAllowlist"
},
"CredentialUpdatedObservedPermissionsItem": {
"type": "string",
"enum": [
"read",
"trade",
"withdraw"
],
"title": "CredentialUpdatedObservedPermissionsItem"
},
"CredentialUpdatedPendingTransition": {
"type": "string",
"enum": [
"NONE",
"ACTIVATE",
"AMEND",
"REACTIVATE",
"UNFREEZE",
"RETIRE",
"REVOKE",
"ROTATE",
"RESUME_TRADING"
],
"description": "ACTIVATE, AMEND (capabilities/secretRef), REACTIVATE, REVOKE or ROTATE; NONE otherwise. 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",
"title": "CredentialUpdatedPendingTransition"
},
"CredentialUpdatedProbeOutcome": {
"type": "string",
"enum": [
"UNKNOWN",
"NONE",
"AUTH_FAILED",
"IP_NOT_WHITELISTED",
"PERMISSION_DENIED",
"RATE_LIMITED",
"VENUE_UNREACHABLE",
"STARTUP",
"RECONNECT",
"HEARTBEAT_TIMEOUT",
"VENUE_MAINTENANCE",
"BACKPRESSURE",
"RESYNC",
"SHUTDOWN",
"FAILOVER",
"LAGGING",
"RECOVERED",
"INVALID_KEY",
"CLOCK_SKEW",
"CONFIG_ERROR",
"STREAM_STALE",
"VENUE_UNAVAILABLE"
],
"description": "UNKNOWN = never probed; NONE = the venue's key-restrictions read answered; else the probe's own failure in the credential or gate band. 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",
"title": "CredentialUpdatedProbeOutcome"
},
"CredentialUpdatedProviderKind": {
"type": "string",
"enum": [
"UNKNOWN",
"EXCHANGE",
"CUSTODIAN",
"WALLET_PROVIDER",
"CHAIN_RPC",
"BANK"
],
"description": "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",
"title": "CredentialUpdatedProviderKind"
},
"CredentialUpdatedStatus": {
"type": "string",
"enum": [
"UNKNOWN",
"DRAFT",
"PENDING_APPROVAL",
"ACTIVE",
"SUSPENDED",
"REVOKED"
],
"description": "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",
"title": "CredentialUpdatedStatus"
},
"GlobalSequenceValue": {
"type": "string",
"pattern": "^[0-9]+$",
"description": "The position as a decimal string — the last change this member had applied, orders, balance readings and algo instances included.",
"title": "GlobalSequenceValue"
}
}
}
Work with this as data
Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
curl "https://apis.io/api/v1/json-schemas/immix-credential-row"
curl "https://apis.io/api/v1/json-schemas?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.