Skip to main content

API Reference

Sigil Open Framework - Reference Implementation The Sigil Sign reference implementation exposes the SOF conformance surface plus the operational endpoints used by Sigil Open Framework clients. Every request that mutates state requires a Sigil API key presented as Authorization: Bearer sk_sigil_.... Production keys are rejected with SIGIL_API_KEY_WRONG_ENV on the test environment, and vice versa. Version: 2.0.0 Base URL: https://sign.sigilcore.com

Endpoints

GET /.well-known/jwks.json

JWKS for Intent Attestation verification Public JSON Web Key Set used by clients to verify Ed25519 signatures on Intent Attestations. The endpoint is intentionally unauthenticated per the SOF conformance specification. Responses:
  • 200 - JWKS document

GET /.well-known/sigil-pqc-keys.json

ML-DSA public keys for PQC attestation verification Canonical app route for the public ML-DSA-65 key set used by PQC-aware clients to verify the pqc.sig claim embedded in approved Intent Attestation JWTs. Hosted clients should use /v1/pqc-keys while production edge exposure of this .well-known path is pending nginx config deployment. The Ed25519 JWKS remains the compatibility verification path. Responses:
  • 200 - PQC key set document

GET /.well-known/sof-conformance.json

SOF conformance descriptor Canonical app route for the conformance classes, attestation algorithms, and public verification endpoints supported by this signer. Hosted clients should use /v1/sof-conformance while production edge exposure of this .well-known path is pending nginx config deployment. Responses:
  • 200 - Conformance descriptor

POST /bundler/{chainId}

ERC-4337 bundler gateway Forwards ERC-4337 user-operation traffic to the upstream bundler for the specified chain. Parameters:
  • chainId (path, integer, required)
Request body: application/json - object Responses:
  • 200 - Bundler response
  • 401 - Missing, malformed, or invalid API key

GET /healthz

Liveness probe Returns 200 with { "status": "ok" } when the service is ready. Responses:
  • 200 - Service is ready

POST /rpc/{chainId}

JSON-RPC gateway, scoped to an allowlisted EVM chain Forwards a JSON-RPC payload to the upstream provider for the specified chain. Only chains on the validator allowlist are accepted (chainId 1 and 8453 as of this spec version). Authenticated. Parameters:
  • chainId (path, integer, required): EVM chain id (e.g. 1 for mainnet, 8453 for Base)
Request body: application/json - object Responses:
  • 200 - JSON-RPC response
  • 400 - Chain not allowlisted
  • 401 - Missing, malformed, or invalid API key

POST /v1/authorize

Submit an intent for policy authorization Evaluates an Intent against the deployed warranty.md policy bound to the presenting API key. On approval the response includes a signed Intent Attestation JWT. On denial the response carries a machine-readable error code (e.g. SIGIL_POLICY_VIOLATION_AMOUNT_EXCEEDED). Before authentication, a coarse IP guard allows 1,000 requests per 60 seconds on sign-test and 1,500 on production. After API-key validation, the per-key limit allows 120 requests per 60 seconds on sign-test and 180 on production. The effective capacity depends on both limits and shared IP traffic; these settings do not promise a universal request capacity. Request body: application/json - object Responses:
  • 200 - Allowed authorization decision
  • 202 - Contract response 202
  • 400 - Contract response 400
  • 401 - Missing, malformed, or invalid API key
  • 403 - Policy violation, or the presenting API key does not carry the authorize scope. A policy violation returns AuthorizeResponse with status DENIED. A scope refusal returns ErrorResponse with error_code SIGIL_API_KEY_SCOPE_INSUFFICIENT.
  • 409 - No policy deployed for this API key
  • 429 - Rate limit exceeded; retry per the documented window
  • 500 - Internal server error
  • 503 - Per-key rate-limit store unavailable; authorization fails closed

POST /v1/authorize/test-run

Simulate authorization with no side effects Evaluates the same Intent shape as /v1/authorize against the deployed policy, without issuing an attestation, creating a hold, or firing webhooks. Always returns the strict enforcement-mode decision; if SIGIL_MODE=OBSERVE is active, the response includes observe_mode_active: true so callers can distinguish strict from observed outcomes. Test-run rows are excluded from monthly quotas. Before authentication, a coarse IP guard allows 1,000 requests per 60 seconds on sign-test and 1,500 on production. After API-key validation, the per-key limit allows 120 requests per 60 seconds on sign-test and 180 on production. The effective capacity depends on both limits and shared IP traffic; these settings do not promise a universal request capacity. Request body: application/json - object Responses:
  • 200 - Simulated decision
  • 400 - Contract response 400
  • 401 - Missing, malformed, or invalid API key
  • 403 - The presenting API key authenticated successfully but does not carry the scope this route requires. error_code is SIGIL_API_KEY_SCOPE_INSUFFICIENT. Keys issued before scoped key classes existed carry the full tenant grant and are unaffected; keys registered through POST /v1/keys/register carry authorize and warranty:deploy only, so webhook administration is unreachable with them until a Pro subscription confers the webhook scopes.
  • 409 - Contract response 409
  • 429 - Rate limit exceeded; retry per the documented window
  • 500 - Contract response 500
  • 503 - Per-key rate-limit store unavailable; authorization fails closed

GET /v1/capabilities

Sigil Sign policy and feature capabilities Returns the unauthenticated, schema-versioned capability registry used by authoring clients for advisory deployment preflight. Responses:
  • 200 - Current Sigil Sign capability registry

GET /v1/holds/{holdId}

Fetch the state of a consensus hold Returns the current non-authoritative state of a hold (PENDING, ALLOWED, DENIED, EXPIRED) plus the source intent and policy reference. A hold poll cannot authorize execution; clients must re-call /v1/authorize and validate its authoritative decision before executing. Requires the API key that created the hold: a hold is owned by the key it was issued to, and a key can read only its own holds. Holds expire at 24 hours by default. Rate-limited to 30 lookups per minute. Parameters:
  • holdId (path, string, required): The hold identifier returned when the policy required consensus
Responses:
  • 200 - Hold state
  • 401 - Missing, malformed, or invalid API key
  • 403 - The presenting API key authenticated successfully but does not carry the scope this route requires. error_code is SIGIL_API_KEY_SCOPE_INSUFFICIENT. Keys issued before scoped key classes existed carry the full tenant grant and are unaffected; keys registered through POST /v1/keys/register carry authorize and warranty:deploy only, so webhook administration is unreachable with them until a Pro subscription confers the webhook scopes.
  • 404 - Hold not found, expired, or owned by a different API key. A hold belonging to another key is reported as not found rather than forbidden, so the endpoint never confirms an identifier to a caller that does not own it.
  • 429 - Rate limit exceeded; retry per the documented window
  • 503 - Usage metering is unavailable; the lookup fails closed

POST /v1/keys/register

Register a new Sigil API key Public registration endpoint. Subject to a strict rate limit (5 attempts per hour per source). Returns a new sk_sigil_… API key on success. The issued key carries the authorize and warranty:deploy scopes: it can evaluate intents and deploy its own warranty.md policy, which it must do before /v1/authorize will return anything other than SIGIL_NO_POLICY_DEPLOYED. It cannot administer webhooks; those scopes are conferred when a Pro subscription activates. Scopes are server-assigned and cannot be requested in the body. Request body: application/json - object Responses:
  • 201 - Key issued. The response body reports the assigned scopes.
  • 400 - Invalid registration payload
  • 429 - Rate limit exceeded; retry per the documented window

GET /v1/pqc-keys

Hosted ML-DSA public keys for PQC attestation verification Hosted public ML-DSA-65 key set used by PQC-aware clients to verify the pqc.sig claim embedded in approved Intent Attestation JWTs. This route is exposed through the existing /v1/* edge proxy while the canonical .well-known route remains available inside the application and in origin nginx configuration. Responses:
  • 200 - PQC key set document

GET /v1/service-metadata

Immutable deployed service commit Returns the full Git commit SHA embedded in the deployed release artifact, pinning the running deployment to an exact build. The sigil-sign source repository is not public, so this value is not independently verifiable against published source. It establishes deployment parity and build pinning for parties that already hold repository access, such as auditors under an active engagement. Clients relying on it for parity evidence must require a 200 response and compare serviceCommit to the expected commit. The endpoint sends Cache-Control: no-store so an intermediary cannot serve stale deployment metadata. Responses:
  • 200 - Deployed artifact commit metadata
  • 503 - The deployed artifact has no commit binding.

GET /v1/sof-conformance

Hosted SOF conformance descriptor Returns the conformance classes, attestation algorithms, and public verification endpoints supported by this signer. The hosted descriptor points pqc_keys_uri at /v1/pqc-keys. Responses:
  • 200 - Conformance descriptor

POST /v1/warranty/deploy

Deploy a signed warranty.md policy to an API key Atomically binds a signed warranty.md to the presenting API key. The body carries the exact signed warranty.md bytes and the operator public key that verifies them. Destructive Policy 2.1 profiles also require a short-lived trusted-shim activation JWT supplied separately from the signed policy. Future calls to /v1/authorize for this key evaluate against the deployed policy. Attempt-rate controls are enforced at the edge and do not mutate activation state. Request body: application/json - object Responses:
  • 200 - Policy deployed; response includes policyHash bound to the key
  • 400 - Invalid warranty.md or signature
  • 401 - Missing, malformed, or invalid API key
  • 403 - Deployment refused. Either the presenting API key does not carry the warranty:deploy scope, in which case error_code is SIGIL_API_KEY_SCOPE_INSUFFICIENT, or the key is pinned to a different operator public key, in which case error_code is SIGIL_WARRANTY_OPERATOR_KEY_MISMATCH. The first successful deployment for a key establishes its operator public key; every later deployment must be signed with that same key. Rotation is an operator procedure and is not available through this endpoint.
  • 409 - Activation denied. error_code is one of SIGIL_TRUSTED_SHIM_REQUIRED, SIGIL_TRUSTED_SHIM_ATTESTATION_REQUIRED, SIGIL_TRUSTED_SHIM_ATTESTATION_MALFORMED, SIGIL_TRUSTED_SHIM_UNTRUSTED, SIGIL_TRUSTED_SHIM_VERSION_REQUIRED, SIGIL_TRUSTED_SHIM_VERSION_UNSUPPORTED, SIGIL_TRUSTED_SHIM_ISSUER_INVALID, SIGIL_TRUSTED_SHIM_AUDIENCE_INVALID, SIGIL_TRUSTED_SHIM_IDENTITY_INVALID, SIGIL_TRUSTED_SHIM_ATTESTATION_EXPIRED, SIGIL_TRUSTED_SHIM_NONCE_INVALID, SIGIL_TRUSTED_SHIM_ATTESTATION_REPLAYED, SIGIL_TRUSTED_SHIM_CAPABILITY_MISSING, or SIGIL_TRUSTED_SHIM_POLICY_BINDING_INVALID.
  • 503 - Usage or activation backing state is unavailable

GET /v1/webhooks

List webhooks registered to the presenting key Responses:
  • 200 - Array of webhook descriptors
  • 401 - Missing, malformed, or invalid API key
  • 403 - The presenting API key authenticated successfully but does not carry the scope this route requires. error_code is SIGIL_API_KEY_SCOPE_INSUFFICIENT. Keys issued before scoped key classes existed carry the full tenant grant and are unaffected; keys registered through POST /v1/keys/register carry authorize and warranty:deploy only, so webhook administration is unreachable with them until a Pro subscription confers the webhook scopes.

POST /v1/webhooks

Register a webhook Request body: application/json - object Responses:
  • 201 - Webhook registered
  • 401 - Missing, malformed, or invalid API key
  • 403 - Refused for one of two distinct reasons. Either the presenting API key does not carry the webhooks:write scope, in which case error_code is SIGIL_API_KEY_SCOPE_INSUFFICIENT, or the key is on the Free plan, in which case error_code is SIGIL_TIER_INSUFFICIENT. Webhook registration requires a Pro plan, and activating a Pro subscription is also what confers the webhook scopes.

DELETE /v1/webhooks/{id}

Remove a registered webhook Parameters:
  • id (path, string, required)
Responses:
  • 204 - Webhook removed
  • 401 - Missing, malformed, or invalid API key
  • 403 - The presenting API key authenticated successfully but does not carry the scope this route requires. error_code is SIGIL_API_KEY_SCOPE_INSUFFICIENT. Keys issued before scoped key classes existed carry the full tenant grant and are unaffected; keys registered through POST /v1/keys/register carry authorize and warranty:deploy only, so webhook administration is unreachable with them until a Pro subscription confers the webhook scopes.
  • 404 - Webhook not found