가이드 본문은 영어입니다. 사이트 탐색은 선택한 언어를 유지합니다.

← 문서

API 레퍼런스

모든 엔드포인트는 OpenAPI 스펙에서 생성됩니다 — 이 페이지가 클라이언트가 맞춘 계약과 어긋나지 않도록. 스펙 다운로드하여 클라이언트를 생성하거나 Postman에 가져오세요.

기본 URL

https://sandbox.identityinc.io
Sandbox — free test verifications (real Shufti test account), simulated chain. Keys are bi_test_… and must not be sent to production. Mint via POST /v1/billing/checkout on this host (see Quickstart).
https://api.identityinc.io
Production — the base URL for the API key issued at signup (bi_…)

공개로 표시되지 않은 모든 엔드포인트는 Authorization: Bearer <key>를 사용합니다. 인증 참고.

Accounts

POST/v1/accounts/freeSponsor free provisional account

요청 본문

ownerPublicKey필수string
activePublicKeystring
passkeyCredentialIdstring
preferredNamestringRequested account name. Permanent once created. Conflicts with an existing name return 409 and hand the kycCreateToken back, so the caller can retry with a different name without repeating KYC. Pattern: ^[a-z1-5.]{1,12}$
deviceFingerprintstring
personDidstring
kycCreateTokenstringOne-time token from GET /v1/kyc/status after approval.
emailProofTokenstringFrom POST /v1/email/otp/confirm. Binds the verified address to the new account. Required when the organization sets requireEmailProofBeforeFreeCreate.
phoneProofTokenstringFrom POST /v1/phone/otp/confirm.

응답

201Created
409Requested name, email, or number already taken
GET/v1/accounts/name-availableCheck whether an account name can be claimed

Advisory only. Nothing is reserved: the chain is the authority and /v1/accounts/free re-checks, so a name can still be lost between this call and create.

매개변수

name필수string · 쿼리

응답

200Availabilityname: string · available: boolean · reason: TAKEN | INVALID · message: string
POST/v1/accounts/unlockRemove faucet cosigner after bind

응답

200Unlocked
GET/v1/accounts/{did}Account status, lifecycle, and active bindings

매개변수

did필수string · 경로Account DID, URL-encoded (`did:antelope:<chain>:<name>`)

응답

200Account with non-revoked bindings
404Account not found in this organization

KYC

POST/v1/kyc/startStart KYC; returns verification URL / access token

Person-first by default: omit `accountDid` to create a Person before any chain account (required when the organization gates free-create on KYC). Identity checks are document + face via Shufti Pro — BoundIdentity does not enable Shufti phone OTP for KYC. On sandbox, complete `verificationUrl` with a Shufti test ID (free on the test account).

요청 본문

accountDidstringOptional. Omit for person-first KYC before free-create.
levelNamestring
redirectUrlstringOptional post-Shufti browser return. Sandbox allows only jungle4.blocksfinity.com /identity paths. Live allows only blocksfinity.com /identity paths. Invalid values are ignored.

응답

200Token issued
429KYC-start budget spent for this organization or IP
502`PROVIDER_FAILURE` — the provider rejected the request (bad level name, credentials, or plan). Not transient: the same request gets the same answer, so fix it rather than retrying.
503`PROVIDER_UNAVAILABLE` — every configured provider was unreachable or erroring. Already retried, and failed over to a standby where one is configured, before you saw this. Safe to retry with backoff; `details.retryAfterSec` is present when the provider named a window.
GET/v1/kyc/statusKYC status for a person

매개변수

personDid필수string · 쿼리
refresh1 | true · 쿼리When the person is not already approved, pull the current review from the KYC provider. Use after a missed webhook or a hosted session that later succeeded. Do not send this on every poll.

응답

200Status, level, provider, and country. Approved people also receive a one-time create token.
404Person not found in this organization

KYB

POST/v1/kyb/startStart Know-Your-Business for a legal entity

응답

200Organization pending
502`PROVIDER_FAILURE` — the provider rejected the request; not transient
503`PROVIDER_UNAVAILABLE` — every configured provider was unreachable. Retry with backoff; see `/v1/kyc/start` for the full contract.

Bind

POST/v1/bind/challengeIssue bind nonce for wallet signature

응답

200Challenge
POST/v1/bind/confirmConfirm bind with signature; issue AccountBinding VC

응답

200Bound

Compliance

POST/v1/aml/screen-applicantScreen applicant id hash (sanctions / denylist)

응답

200Screen result
POST/v1/risk/assessAnti-abuse risk score before free create / bind

응답

200Assessment
POST/v1/compliance/exportExport hash-chained audit log for a date range

응답

200Export job
GET/v1/compliance/exportsList recent compliance export jobs

응답

200Jobs
GET/v1/compliance/export/{jobId}Fetch completed export artifact

매개변수

jobId필수string · 경로

응답

200Job + artifact JSON
POST/v1/compliance/audit/verifyVerify audit hash-chain integrity

응답

200Verification result

Admin

POST/v1/admin/accounts/suspendSuspend an account (compliance action)

응답

200Suspended
GET/v1/admin/dashboardOrganization dashboard aggregates (lifecycle, AML, recent audit)

응답

200Dashboard payload
GET/v1/admin/accountsList chain accounts for the organization

응답

200Account list
GET/v1/admin/peopleList people / KYC subjects

응답

200People list
GET/v1/admin/organizationsList KYB businesses

응답

200Businesses
GET/v1/admin/auditHash-chained audit log entries

응답

200Audit entries
GET/v1/admin/membersOrganization console memberships (requires admin scope)

응답

200Members
POST/v1/admin/membersAdd a console member, or restore and re-role a revoked one

The membership roster decides who may sign in to the admin console and what they may do there. Roles, weakest first: `viewer`, `operator`, `compliance_officer`, `admin`, `owner`. Re-adding an existing address updates its role and reactivates it, so a returning colleague does not collide with their old row. While an organization has no members at all, the console accepts any address with the correct password and treats it as an `owner` — adding the first member closes that path.

요청 본문

email필수string (email)
role필수viewer | operator | compliance_officer | admin | owner

응답

201Member added or updated
PATCH/v1/admin/members/{email}Change a member's role or reactivate them

매개변수

email필수string (email) · 경로

요청 본문

roleviewer | operator | compliance_officer | admin | owner
activeboolean

응답

200Updated
404No such member in this organization
DELETE/v1/admin/members/{email}Revoke a member's console access

Deactivates rather than deletes. The address remains the recorded actor on every audit entry the member produced, and removing the row that explains who they were would leave those entries unresolvable.

매개변수

email필수string (email) · 경로

응답

200Revoked
404No such member in this organization
GET/v1/admin/amlPEP / sanctions alerts + AML audit events

응답

200Screening feed
GET/v1/admin/riskAnti-abuse posture (velocity, shared devices, risk events)

응답

200Risk summary
GET/v1/admin/tenantCurrent organization + policy (scoped by API key)

응답

200Organization detail
GET/v1/admin/api-keysList API keys (prefixes only)

응답

200Keys
POST/v1/admin/api-keysCreate or rotate API key (raw returned once)

요청 본문

name필수stringMax length 64.
revokeKeyIdstring (uuid)Deactivate this key after minting the new one
scopesread | accounts_write | kyc_write | bind_write | unlock_write | admin | compliance_export | webhook_manage[]Least-privilege scope set. **Omitting this grants every scope, including `admin`** — the historical behaviour of this endpoint. Pass a narrower set for a key that only needs part of the API, for example `["read"]` for a dashboard or `["accounts_write","kyc_write"]` for an onboarding service.

응답

201Created — the raw key is returned once and never againid: string (uuid) · prefix: string · apiKey: string · scopes: string[] · revokedKeyId: string · warning: string · scopeNotice: string
DELETE/v1/admin/api-keys/{id}Revoke API key

매개변수

id필수string · 경로

응답

200Revoked
POST/v1/admin/signing/enableEnable HMAC request signing (secret once)

응답

200HMAC secret
POST/v1/admin/signing/disableDisable HMAC request signing

응답

200Disabled
PUT/v1/admin/ip-allowlistReplace organization IP allowlist

응답

200Allowlist
POST/v1/admin/dpa/acceptAccept Data Processing Agreement (sets dpaAcceptedAt)

응답

200Acceptance recorded
GET/v1/admin/webhooksList outbound webhooks

응답

200Webhooks
POST/v1/admin/webhooksRegister outbound webhook (signing secret once)

응답

201Registered
DELETE/v1/admin/webhooks/{id}Deactivate outbound webhook

매개변수

id필수string · 경로

응답

200Deactivated
GET/v1/admin/webhooks/deliveriesRecent outbound delivery attempts

Diagnostics for a receiver that is rejecting events: status, attempt count, and the last error per delivery. Scoped to your own webhooks.

매개변수

statuspending | failed | delivered | dead · 쿼리
limitinteger · 쿼리

응답

200Delivery attempts
POST/v1/admin/webhooks/deliveries/{id}/replayResend a delivery that gave up

Re-queues a `failed` or `dead` delivery and resets its attempt counter, for use once the receiving system has been repaired. The signed body is stored with the delivery, so the replay carries the original payload and signature inputs rather than a regenerated approximation. Deliveries that already succeeded are refused — deduplicate on `X-BI-Delivery-Id` if you need to reprocess one.

매개변수

id필수string · 경로

응답

200Re-queued
409Already delivered, or the payload is no longer available
GET/v1/tenantCurrent organization posture (signing, allowlist, policy)

응답

200Organization
PUT/v1/admin/country-policySet the organization's jurisdiction policy

Enforced when binding a person to an account: a country on `blockedCountries`, or absent from a non-empty `allowedCountries`, is refused. The blocklist takes precedence. When either list is non-empty a subject whose country is unknown is also refused, so the control cannot be bypassed by an unresolvable jurisdiction. Empty lists mean no restriction. Omit a field to leave it unchanged.

요청 본문

allowedCountriesstring[]ISO-3166 alpha-2 codes
blockedCountriesstring[]

응답

200Policy appliedallowedCountries: string[] · blockedCountries: string[]
400A code was not a valid alpha-2

AML

POST/v1/aml/screen-accountKYT-style screen of a chain account

요청 본문

chainAccount필수string

응답

200Score and labels
POST/v1/aml/clearClear PEP / sanctions flags on a person

Compliance-officer action. Requires `compliance_export`. By default this resets `pepFlag`, `sanctionsFlag`, and `riskScore` immediately, closes any open AML case for the subject as `cleared`, and writes an `aml.cleared` audit entry with the reason. When the organization's policy sets `requireSecondApprovalToClearAml` (four eyes), this call only *proposes* the clear: the case moves to `pending_approval`, the flags stay up, and the response carries `pendingApproval: true` with the `caseId`. A different person then calls `/v1/aml/cases/{caseId}/approve-clear`, which is what lifts the flags. If the subject has no open case, one is opened by hand so the proposal has somewhere to live.

요청 본문

subjectDid필수string
reason필수stringMax length 500.

응답

200Flags cleared, or (under four eyes) a clear proposed.cleared: boolean · pendingApproval: boolean · caseId: string · subjectDid: string
404Person not found in this organization
409The case was closed by someone else while this decision was being made
GET/v1/aml/casesThe open AML case queue, worst first

Cases with status `open` or `pending_approval`, ordered by priority (set from match severity) then age. Requires `compliance_export`.

응답

200List of cases
POST/v1/aml/cases/{caseId}/approve-clearApprove a proposed clear (four eyes)

The second pair of eyes. Lifts the subject's flags and closes the case as `cleared`, in one transaction. Refused when the approver is the identity that proposed it: a tenant-minted API key counts as one person, and the console derives the operator from the signed session. Requires `compliance_export`.

매개변수

caseId필수string · 경로

요청 본문

notesstringMax length 500.

응답

200Flags cleared and case closed
403The person who proposed the clear cannot approve it
404Case not found in this organization
409Case is not awaiting approval
POST/v1/aml/cases/{caseId}/confirmConfirm the match and close the case

One person may always make things stricter. Closes the case as `confirmed`; the flags stay up. Requires `compliance_export`.

매개변수

caseId필수string · 경로

요청 본문

reason필수stringMax length 500.

응답

200Case confirmed
404Case not found in this organization
409Case already closed

Billing

POST/v1/billing/chain/confirm공개Settle an on-chain A payment for a Growth checkout

Verifies a transfer to the treasury carrying this checkout's memo, then provisions the organization. A transaction id can only ever pay for one checkout. Returns 425 while the transfer is still reversible — retry shortly rather than treating it as a rejection.

요청 본문

sessionId필수string
transactionId필수string
accountstringOptional payer; when set the transfer must originate from it

응답

201Organization set up (API key returned once)
400Payment not verified
409Already provisioned
425Transfer seen but not yet irreversible — retry
GET/v1/billing/checkout/{sessionId}공개Poll checkout status

매개변수

sessionId필수string · 경로

응답

200Status with a masked email; never includes the API key
404Unknown session

Phone

POST/v1/phone/otp/startSend an SMS one-time code

Rate limited per phone and per client IP. Requires `accounts_write`. On hosted sandbox and production the code is delivered by SMS only — it is never returned in the response body.

요청 본문

phone필수stringE.164, or a local Ghana number

응답

200Challenge issuedchallengeId: string (uuid) · expiresAt: string (date-time) · phoneMasked: string
429Too many codes for this phone or IP
POST/v1/phone/otp/confirmConfirm an SMS code, returning a short-lived phone proof

Capped at 5 attempts per challenge. The returned `phoneProofToken` is accepted by `POST /v1/accounts/free` for 4 hours.

요청 본문

challengeId필수string (uuid)
code필수string

응답

200Proof issuedphoneProofToken: string · expiresInSec: integer · personDid: string · softIdentity: boolean
400Invalid or expired code
429Attempt cap reached for this challenge

Contact

Verified email and phone bound to an account. Contact channels are never identity evidence - KYC owns that.

POST/v1/email/otp/startEmail a verification code

Confirming an email never creates or promotes a Person. Email is a contact channel; KYC remains the only identity authority.

요청 본문

email필수string (email)

응답

200Challenge issuedchallengeId: string (uuid) · expiresAt: string (date-time) · emailMasked: string · devCode: string
409Address already bound to an account
POST/v1/email/otp/confirmConfirm an emailed code; returns a short-lived emailProofToken

요청 본문

challengeId필수string (uuid)
code필수string

응답

200VerifiedemailProofToken: string · expiresInSec: integer · emailMasked: string
429Too many attempts on this challenge
GET/v1/accounts/{did}/contactMasked view of the contacts bound to an account

매개변수

did필수string · 경로Account DID, or the bare chain name.

응답

200Masked contacts; raw values are never returned
POST/v1/accounts/contact/challengeIssue a nonce the account's owner key must sign to change a contact

Contact changes are authorized by the account key, not by the session — whoever can change the address controls where account notices go. The nonce is single-use and consumed by the matching start call.

요청 본문

accountDid필수string
channel필수email | phone

응답

200Challengenonce: string · payloadToSign: string · expiresAt: string (date-time)
POST/v1/accounts/contact/email/startSend a code to a proposed new email

Nothing is unbound until the code is confirmed.

요청 본문

accountDid필수string
email필수string (email)
nonce필수string
signature필수string

응답

200Challenge issued
400INVALID_SIGNATURE - the signature does not verify against the account's active key.
409Address already bound to another account
POST/v1/accounts/contact/email/confirmConfirm the code and swap the bound email

Detach and attach run in one transaction, so the account is never left without a verified email. The previous address is notified.

요청 본문

challengeId필수string (uuid)
code필수string

응답

200Changed
POST/v1/accounts/contact/phone/startSend a code to a proposed new phone number

요청 본문

accountDid필수string
phone필수string
nonce필수string
signature필수string

응답

200Challenge issued
POST/v1/accounts/contact/phone/confirmConfirm the code and swap the bound phone number

요청 본문

challengeId필수string (uuid)
code필수string

응답

200Changed

Resolution

GET/.well-known/did.json공개Issuer DID document (W3C did:web)

Publishes the Ed25519 `assertionMethod` key used to sign issued credentials. A relying party needs only this document to verify a credential offline.

응답

200DID document
GET/people/{personId}/did.json공개Person DID document (W3C did:web)

매개변수

personId필수string (uuid) · 경로

응답

200DID document exposing KYC status only
404Unknown person
GET/orgs/{orgId}/did.json공개Organization DID document (W3C did:web)

매개변수

orgId필수string (uuid) · 경로

응답

200DID document exposing KYB status only
404Unknown organization

Ops

GET/v1/health공개Liveness

응답

200OK
GET/v1/whoami공개The source IP this API attributes to you

Returns the address tenant IP allowlists are compared against. Call it from the server that will hold your API key before configuring an allowlist: NAT and egress gateways mean the address we see is often not the one you expect, and an allowlist that does not match fails closed — every request returns 403. Unauthenticated, and returns nothing beyond your own address.

응답

200The caller's resolved source addressclientIp: string
GET/v1/ready공개Readiness

응답

200Ready
503Not ready
GET/v1/metricsMetrics (Prometheus text exposition)

Requires `read` scope.

응답

200text/plain exposition
401Missing or invalid API key
GET/v1/billing/plans공개Public Identity Inc. plan catalog

응답

200Plans
POST/v1/billing/ai/advise공개AI checkout advisor (rate-limited)

응답

200Recommendation
429Rate limited
POST/v1/billing/email/otp/start공개Send a signup verification code to the claimed work email

Required before POST /v1/billing/checkout. Proves control of the mailbox that will own the organization. Unauthenticated. Rate-limited per IP and per address. In non-production mock mode the response may include `devCode`; production never echoes the code.

응답

200Challenge id and masked email
429Rate limited
POST/v1/billing/email/otp/confirm공개Confirm the signup email code and receive a one-time proof token

Spend the emailed code. The returned `emailProofToken` is accepted once by POST /v1/billing/checkout for the same address.

응답

200emailProofToken
400Incorrect or expired code
POST/v1/billing/checkout공개Builder signup, Growth Stripe Checkout, or Institutional lead

Requires `emailProofToken` from POST /v1/billing/email/otp/confirm. Builder mints a full-access API key only after that proof is spent.

응답

200Redirect or sales lead
201Builder provisioned
403Email not verified
429Rate limited
POST/v1/billing/stripe/webhook공개Stripe lifecycle + checkout.session.completed

응답

200Received
POST/v1/billing/checkout/complete공개Complete a pending Growth checkout (sandbox / test settlement)

응답

200Provisioned or upgraded
POST/v1/billing/checkout/reveal공개Reveal API key once after Stripe Checkout (rate-limited)

응답

200Key payload
GET/v1/billing/usagePlan + usage meters for the authenticated organization

응답

200Usage snapshot
POST/v1/billing/upgradeBuilder → Growth Checkout (keeps organization + keys)

응답

200Checkout redirect
POST/v1/billing/portalStripe Customer Portal session

응답

200Portal URL
API reference · Identity Inc.