X1ID is live on X1 mainnet
X1ID / Gate

Gate

Mainnet

Gate answers one question over HTTP: does this subject hold a verified on-chain attestation that satisfies my policy? Point it at an @handle or a wallet, hand it a policy, and get back a decision with the attestations behind it. You reuse X1ID's verification oracle as your allowlist instead of running your own.

This is the hosted version of the SDK's gating primitive. If you'd rather read chain yourself (or gate on-chain from another program via a CPI), see Attestation gating — same policy shapes, same staleness rules, no key needed.

Check a subject

POST/v1/gate/check

Body: exactly one of handle / wallet, plus a policy. A wallet subject is gated on its primary @handle.

POST /v1/gate/check
curl -X POST https://api.x1id.io/v1/gate/check \
  -H "X-API-Key: $X1ID_API_KEY" -H "content-type: application/json" \
  -d '{ "handle": "@jack", "policy": { "kind": 4 } }'
{
  "passed": true,
  "subject": { "handle": "jack", "wallet": null },
  "policy": { "kind": 4 },
  "attestations": [
    { "platform": "github", "kind": 4, "attested_at": 1733270400 }
  ]
}
fieldmeaning
passedthe decision.
subjectwho was evaluated. For a wallet subject, handle is its resolved primary (or null).
policythe policy that ran.
attestationsthe live attestations that count — the which behind the decision.
reasonpresent only when passed is false for a structural reason: no-primary-handle (the wallet has no primary) or handle-not-registered. Lets you tell "no identity" from "identity, but doesn't match."

A definitive "does not pass" — an unregistered handle, a wallet with no primary, or no matching attestation — is a real 200 { "passed": false } decision (and is metered). Only malformed input (400) and infrastructure failure (502) are non-decisions.

Policies

A policy is what the subject must prove. Three inline shapes, mirroring the SDK's Gate type exactly:

PolicyPasses when the handle holds…
"any-verified"at least one non-stale attestation of any kind.
{ "kind": 4 }a non-stale attestation of exactly that kind.
{ "anyOf": [2, 4] }a non-stale attestation of any listed kind (X or GitHub).

Attestation kinds: 0 dns · 1 social (legacy) · 2 x · 3 discord · 4 github · 5 telegram. A policy with an out-of-range kind is rejected at definition time (400 BAD_GATE), never silently never-matching.

Named policies

Define a policy once and reference it by id — handy when the same door is checked from many places. Policy management is keyed only (a policy is scoped to your API key).

POST/v1/gate/policies
POST /v1/gate/policies
curl -X POST https://api.x1id.io/v1/gate/policies \
  -H "X-API-Key: $X1ID_API_KEY" -H "content-type: application/json" \
  -d '{ "name": "github-verified", "gate": { "kind": 4 } }'
# → 201 { "id": "gp_…", "name": "github-verified", "gate": { "kind": 4 }, "created_at": "…" }

Then pass the gp_… id as the policy in a check:

curl -X POST https://api.x1id.io/v1/gate/check \
  -H "X-API-Key: $X1ID_API_KEY" -H "content-type: application/json" \
  -d '{ "wallet": "H8Fs…X1HiA", "policy": "gp_…" }'

GET /v1/gate/policies/:id reads one back (owner-scoped). A gp_… string is always treated as a stored-policy reference; any other value is an inline policy.

Metering

A gate decision is metered exactly like a resolve: with a key it counts against your rate limit; with no key, each decision can be paid for per call via x402. Defining and reading named policies always requires a key.

What a pass means — and what it doesn't

Trust in the gate = trust in the attestor, exactly like the blue-tick.

  • passed: true means the handle carries a live, attestor-signed attestation matching your policy. The attestor is X1ID's verification oracle.
  • It is "verified by x1id", not trustless proof and not legal personhood. The attestor key is admin-rotatable. Render the result as exactly that.
  • Staleness is enforced for you. An attestation only counts for the current owner — one left from a previous owner (before a transfer, sale, or re-register) never counts.
  • Ownership changes, so re-check per session. Pair a gate check with Connect to first prove the visitor controls the handle, then gate on what it's verified.

Next

Browse the docs

Gate