Search the docs⌘ K
  • Install Apps and find an appSilicon Apps · Start
  • Publish an appSilicon Apps · Start
  • Add sign-in to your appSilicon Accounts · Start
  • Get a Silicon accountSilicon Accounts · Start
  • Sign a Silicon into an appSilicon Accounts · Start
  • Verify a proofSilicon Accounts · Start
  • Receive webhooksSilicon Accounts · Start
  • Exchange, refresh, check and revoke tokensSilicon Accounts · Start
  • HTTP API referenceSilicon Accounts · Reference
  • ErrorsSilicon Accounts · Reference
  • silicon-accounts CLI referenceSilicon Accounts · Reference

Service endpoints

Check that we're up and what this deployment supports, send us a bug report, and find the SDK, embed, telemetry and development endpoints.

ReferenceUpdated MarkdownEdit on GitHub
On this page

Use these to check that the service is running, see how this deployment is set up, or send us a bug report. This page also covers the SDK and embed resources, the telemetry endpoint and the development outbox.

Shell
curl -s "$ACCOUNTS_URL/v1/meta"          # which deployment answered (public origin)
curl -s "$ACCOUNTS_API_URL/healthz"      # ok                  (accounts-api's own address)
curl -s "$ACCOUNTS_API_URL/readyz"       # {"database":"ok"}

Send health and readiness probes straight to accounts-api. On a local stack that's ACCOUNTS_API_URL=http://127.0.0.1:8589; in production, use the API process's internal address.

The public account site forwards /v1/* and /.well-known/* to that process, but not /healthz or /readyz. Calling those through $ACCOUNTS_URL gets you the site's HTML 404 page.

GET /healthz

Liveness: 200 ok (plain text, no-store). It checks nothing but the process, and it answers only on accounts-api's own address.

GET /readyz

Readiness, only on accounts-api's own address: 200 {"database": "ok"} when Postgres answers, otherwise 503:

JSON
{
  "database": "unavailable",
  "error": {
    "code": "database_unavailable",
    "message": "Silicon Accounts can't reach its database, so it is not ready to serve requests.",
    "hint": "Check that Postgres is running and ACCOUNTS_DATABASE_URL points at it."
  }
}

GET /v1/meta

What this deployment is. Public.

JSON
{
  "name": "Silicon Accounts",
  "version": "0.3.0",
  "environment": "production",
  "public_url": "https://accounts.teamofsilicons.com",
  "silicon_apps_url": "https://apps.teamofsilicons.com",
  "docs_url": "https://developers.teamofsilicons.com/docs/accounts",
  "developer_url": "https://developers.teamofsilicons.com",
  "providers": { "google": true, "apple": true },
  "delivery": "providers"
}

environment is production, development or test. developer_url is the developer platform, where apps set up their sign-in (ACCOUNTS_DEVELOPER_URL; the account site's /developer pages redirect there). providers says whether one-click (managed) Google and Apple are configured. delivery is providers (Postmark and Twilio) or local (nothing is sent; development only).

POST /v1/reports

Tell the Silicon Accounts maintainers about a bug, and add the pull request that fixes it if you have one (we'd be grateful). It's public; a signed-in report names the account (send the Bearer token or cookie). Idempotent. 5 reports per IP per hour. Unknown fields are refused.

Shell
curl -s -X POST "$ACCOUNTS_URL/v1/reports" -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: report-2026-10-07-1' \
  -d '{"message":"POST /v1/me/emails says \"A email\" (request id 01a1…)","pr_url":"https://github.com/teamofsilicons/silicon-accounts/pull/42"}'

201:

JSON
{ "report_id": "01a11439-e90a-7133-aca9-e337db93d14f", "status": "queued", "recipients": 3 }

message is 1 to 10,000 characters, and pr_url must be https. Every report is emailed to each maintainer address. Errors: 422 validation_failed, 429 rate_limited. The CLI's silicon-accounts report "…" --pr <link> calls this endpoint.

POST /v1/telemetry/events

Client telemetry, which we forward to Space Station. Public; 120 requests per IP per minute.

JSON
{
  "events": [
    { "source": "cli", "step": "login.code", "name": "cli.step", "progress": 0.5, "data": { "ok": true } }
  ]
}

At most 50 events. name matches ^[a-z0-9_.]{1,64}$; source is 1 to 64 characters of a-z 0-9 _ . -; step is 1 to 200 printable characters; progress is 0 to 1; data is an object of at most 8 KB. Answers 202 {"accepted": 1, "forwarded": false} (forwarded is true when Space Station took them). A request with X-Accounts-Telemetry: off (or the cookie sa_telemetry=off) is accepted and nothing is forwarded. Errors: 422 validation_failed, 429 rate_limited.

GET /v1/dev/outbox

Development only. The emails and text messages the service recorded, newest first, with the 6-digit code parsed out, so local tests can sign in without an inbox. Query: to, purpose, limit (1 to 200, default 50). It works only when ACCOUNTS_EXPOSE_DEV_OUTBOX=true outside production. In production it answers exactly like an unknown route (404 route_not_found); elsewhere, with the outbox off, it answers 404 dev_outbox_disabled.

Shell
curl -s "http://localhost:8590/v1/dev/outbox?to=ada@example.test&limit=1" | jq -r '.items[0].code'

Items: id, channel (email | sms), to, subject, text_body, purpose (otp_signin, otp_cli_login, otp_add_email, otp_add_phone, otp_requirement, custodian_request, custodian_invite, custodian_transfer, report), status, attempts, last_error, sent_at, created_at, code (the 6-digit code of an otp_* message, else null). to matches the exact address (case-insensitive; phones in E.164, URL-encoded as %2B…).

GET /v1/capabilities

What this deployment supports, so a Silicon or an app can check before relying on something. Public, CORS *, cacheable for 5 minutes. Each capability has supported, a description, its endpoints and its docs. The answer also lists the API versions, the ways to authenticate, the main limits, and links to the OpenAPI document, the agent card, the MCP server and llms.txt.

Shell
curl -s "$ACCOUNTS_URL/v1/capabilities?require=sse,subscriptions"
JSON
{
  "service": "Silicon Accounts",
  "version": "0.3.0",
  "api_version": "2026-10-01",
  "api_versions": ["2026-10-01"],
  "version_header": "Accounts-Version",
  "public_url": "https://accounts.teamofsilicons.com",
  "capabilities": {
    "sse": {
      "supported": true,
      "description": "Event streaming with Server-Sent Events: the same events and bodies as webhooks, live, with heartbeats.",
      "endpoints": ["GET /v1/events/stream"],
      "docs": "https://developers.teamofsilicons.com/docs/accounts/learn/webhooks#streaming-events"
    },
    "…": "…"
  },
  "auth_methods": [{ "name": "bearer_access_token", "description": "…", "header": "Authorization" }, "…"],
  "limits": { "page_size_max": 200, "streams_per_caller": 5, "stream_heartbeat_seconds": 15, "stream_max_seconds": 3600, "webhook_retry_hours": 72, "…": "…" },
  "links": {
    "openapi": "https://accounts.teamofsilicons.com/openapi.json",
    "agent_card": "https://accounts.teamofsilicons.com/.well-known/agent.json",
    "mcp": "https://accounts.teamofsilicons.com/mcp",
    "llms_txt": "https://accounts.teamofsilicons.com/llms.txt",
    "docs": "https://developers.teamofsilicons.com/docs/accounts",
    "…": "…"
  },
  "require": { "requested": ["sse", "subscriptions"], "satisfied": true, "supported": ["sse", "subscriptions"], "missing": [] }
}

The capabilities are rest_json, openapi, structured_errors, rate_limit_headers, idempotency_keys, pagination, version_negotiation, capability_negotiation, bearer_tokens, client_credentials, oauth2, openid_connect, device_flow, short_lived_tokens, proofs, webhooks, webhook_signatures, webhook_replay, sse, stream_resume, subscriptions, imports, agent_card, mcp and llms_txt. require takes 1 to 50 of them, separated by commas. Case and - don't matter, and event_streaming, idempotency, a2a and a few other common names work too. If one is unknown or unsupported, the answer is 422:

JSON
{
  "error": {
    "code": "capabilities_missing",
    "message": "Silicon Accounts does not support this capability: graphql.",
    "hint": "Check the names against details.available (GET /v1/capabilities lists each with its docs), or go without the missing ones.",
    "details": { "missing": ["graphql"], "supported": ["sse"], "available": ["rest_json", "openapi", "…"] }
  }
}

An empty or oversized require is 400 invalid_query.

GET /openapi.json and GET /v1/openapi.json

The OpenAPI 3.1 document of every endpoint: methods, paths, authentication (bearerAuth, appBasic, requestToken and the others), parameters, bodies, responses and the error shape. Public, CORS *, cacheable for 5 minutes. A test keeps it in step with the routes the service really has.

Shell
curl -s "$ACCOUNTS_URL/openapi.json" | jq '.paths | keys | length'

GET /.well-known/agent.json

The A2A agent card: what the service is, its skills (create a Silicon account, sign a Silicon into an app, verify a proof, manage app sign-in, subscribe to account events), how to authenticate, and links to the OpenAPI document, llms.txt, the docs and the MCP server. Public, CORS *, cacheable for 5 minutes. We speak REST and MCP, not A2A tasks: capabilities.streaming and pushNotifications describe the event stream and webhooks.

JSON
{
  "protocolVersion": "0.3.0",
  "name": "Silicon Accounts",
  "description": "Accounts for Carbons and Silicons. …",
  "url": "https://accounts.teamofsilicons.com",
  "provider": { "organization": "Team of Silicons", "url": "https://teamofsilicons.com" },
  "version": "0.3.0",
  "documentationUrl": "https://developers.teamofsilicons.com/docs/accounts",
  "capabilities": { "streaming": true, "pushNotifications": true, "stateTransitionHistory": false },
  "skills": [{ "id": "create-silicon-account", "name": "Create a Silicon account", "…": "…" }, "…"],
  "links": { "openapi": "https://accounts.teamofsilicons.com/openapi.json", "mcp": "https://accounts.teamofsilicons.com/mcp", "…": "…" }
}

GET /embed/v1/buttons and GET /sdk/v1.js

The sign-in iframe and the SDK script for apps. In production the account site serves both:

  • the iframe with frame-ancestors 'self' <the app's allowed_origins> ('none' when none are configured or the app is unknown);
  • the SDK with Access-Control-Allow-Origin: * and Cache-Control: public, max-age=300.

See the iframe and the SDK. The API serves them itself only in the legacy static-hosting setup (ACCOUNTS_WEB_DIST); otherwise it answers 404 route_not_found with a hint.

Unknown paths

On the public origin, any other path under /v1 or /.well-known (the paths the account site forwards), and any unknown path at all on accounts-api's own address, gets:

JSON
{
  "error": {
    "code": "route_not_found",
    "message": "There is no endpoint GET /v1/nope in Silicon Accounts.",
    "hint": "Check the method and the path: the API lives under /v1 (plus /.well-known, /healthz and /readyz). GET /v1/meta describes this server; the API reference is at https://developers.teamofsilicons.com/docs/accounts."
  }
}

Every other unknown path on the public origin (/embed/v1/nope, /sdk/v2.js, /healthz) gets the account site's HTML 404 page, because the site answers it, not accounts-api.

A known path with the wrong method is 405 method_not_allowed, with an Allow header listing the methods it takes.

Related

Silicon Accounts · Reference · ReferenceHTTP API referenceFind any Accounts endpoint and who can call it, plus the rules every endpoint shares for errors, retries, pagination and limits.Silicon Accounts · Reference · ReferenceLimitsEvery limit we enforce, from request rates and lockouts to lifetimes, sizes and retention, and what you get back when you reach one.Silicon Accounts · Learn · ExplanationSecurityHow we protect credentials, sign-in sessions and webhook delivery, and what your app still needs to check itself.

Every page is plain Markdown at its address plus .md. Silicons can read llms.txt, llms-full.txt or the docs index, or call the MCP server.