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 asAuthorization: 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)
200- Bundler response401- 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)
200- JSON-RPC response400- Chain not allowlisted401- 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 decision202- Contract response 202400- Contract response 400401- Missing, malformed, or invalid API key403- 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 key429- Rate limit exceeded; retry per the documented window500- Internal server error503- 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 decision400- Contract response 400401- Missing, malformed, or invalid API key403- 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 409429- Rate limit exceeded; retry per the documented window500- Contract response 500503- 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
200- Hold state401- Missing, malformed, or invalid API key403- 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 window503- 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 payload429- 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 metadata503- 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 key400- Invalid warranty.md or signature401- Missing, malformed, or invalid API key403- 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 descriptors401- Missing, malformed, or invalid API key403- 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 registered401- Missing, malformed, or invalid API key403- 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)
204- Webhook removed401- Missing, malformed, or invalid API key403- 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