API reference

Signet's public API is read-only and versioned: every endpoint answers a GET with JSON (one returns an SVG badge), and v1 only ever changes by adding things. It is what @signet/sdk reads.

Base URL

Every path below is relative to the deployment's /api/v1. The version is in the path; there is no version header.

base URL example
curl -s "https://signet-web-pearl.vercel.app/api/v1/health"

Authentication and API keys

No key is needed: anonymous callers can read everything. A key is a rate-limit identity, not a permission. Send it as a bearer token for the higher keyed budget, and keep it server-side. An invalid or revoked key is a 401, never silently anonymous.

API key example
curl -s -H "Authorization: Bearer sgk_…" "https://signet-web-pearl.vercel.app/api/v1/profiles/alice"

Rate limits

Anonymous callers get 60 requests per minute per IP; a key raises that to 300 by default. Every response carries RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset (seconds), so a client can pace itself. Over the limit is a 429 with Retry-After in seconds.

Errors

A response has either data or error, never both. Branch on error.code, a closed list; message is for logs and may change.

error envelope
{ "error": { "code": "not_found", "message": "No profile for handle 'nobody'.", "details": {} } }
Error codes and their HTTP statuses
codestatusMeaning
bad_request400The request is malformed or a parameter is invalid. Do not retry.
unauthorized401An invalid or revoked API key was sent. Do not retry.
not_found404The resource does not exist (for a handle: it is not bound). Do not retry.
rate_limited429Over budget. Retry after the Retry-After header.
unavailable503A dependency (database, chain RPC, Horizon) could not answer. Retry with backoff.
internal500A bug in Signet. The response carries no internals.

Pagination

Lists take limit (default 25, at most 100) and an opaque cursor. Pass meta.nextCursor back for the next page; it is null on the last one. A cursor is a position, not an offset, so items added while you page never repeat or shift a page. meta.truncated says a list may be partial (a capped read, or no layer able to answer), and meta.source which layer answered.

pagination example
curl -s "https://signet-web-pearl.vercel.app/api/v1/profiles/alice/contracts?limit=25"
curl -s "https://signet-web-pearl.vercel.app/api/v1/profiles/alice/contracts?limit=25&cursor=<meta.nextCursor>"

CORS and caching

Every response sends Access-Control-Allow-Origin: *, so a browser on any site can call the API; the API is read-only, so there are no credentials to protect. Cacheable answers carry a weak ETag and honour If-None-Match with a 304; errors are no-store.

Endpoints

Badges

Specifications

Health

Registry

Other

Profiles

The machine-readable document is at /api/v1/openapi.json. The full design rules, including what counts as a breaking change, are in docs/API_V1.md.