The d parameter encodes a JSON envelope. The request object inside it requires these fields on every type:
| Field | Type | Notes |
|---|---|---|
| type * | string | One of connect, transfer, sc_call, sign_message, verify_message |
| nonce * | string | 16–128 chars, alphanumeric or -_=+. Must be unique — Sigil tracks seen nonces for 1 hour and rejects replays |
| dapp.origin * | string | Must be a valid HTTPS URL, e.g. https://yourapp.example |
| dapp.name | string | Display name shown to the user. Strongly recommended |
| dapp.icon | string | URL to the dApp's icon. Optional |
| exp | integer | Unix seconds. Defaults to 5 min from receipt if omitted. Max 1 hour from now — requests further out are rejected |
Encode the envelope (not just the request) with URL-safe base64, no padding.
function b64url(str: string): string {
return btoa(str)
.replaceAll('+', '-')
.replaceAll('/', '_')
.replaceAll('=', '');
}
function buildSigilUri(
request: SigilRequest,
options: { callback?: string; redirect_uri?: string } = {},
): string {
const envelope = {
request,
callback: options.callback ?? null,
redirect_uri: options.redirect_uri ?? null,
};
return `sigil://v1/request?d=${b64url(JSON.stringify(envelope))}`;
}Two delivery modes are available. Set one or both in the envelope — they are independent and can be combined.
| Field | How it works | Best for |
|---|---|---|
callback | Sigil POSTs the result as JSON from the Rust layer after the user acts | Apps with a server — production dApps, anything that handles money or needs server-side nonce verification |
redirect_uri | Sigil opens redirect_uri?result=<base64url JSON> in the default browser after the user acts | Static sites, SPAs, and tools with no server — read new URLSearchParams(location.search).get("result") client-side |
Sigil POSTs a JSON body to your callback URL from the Rust layer. If delivery fails, the result stays recoverable in request history for retry, JSON export, or clipboard copy.
https:// in productionhttp://localhost and http://127.0.0.1 are allowed for local devSigil opens redirect_uri?result=<value> in the browser after the user acts. The result query parameter is the same JSON response body as the POST callback, base64url-encoded (no padding). Read it client-side — no server required.
callback: HTTPS in production, localhost HTTP for dev{
"status": "rejected",
"type": "<original request type>",
"nonce": "<the nonce you sent>",
"reason": "user_rejected"
}Match the nonce in the callback body against the one you sent. Different nonce = different request. Don't trust the body until that matches.
Requests can be unsigned (legacy_unverified — dApp name/origin are self-reported) or carry an ES256 proof. If a proof is present but the signature is invalid, or the issuer's origin doesn't match, Sigil blocks approval entirely. See the @sigil-oss/connect SDK page for how to sign requests.
| Level | Meaning | Blocks? |
|---|---|---|
legacy_unverified | No proof — dApp name/origin self-reported | No |
signed_untrusted | Valid ES256 signature, issuer not in user's registry | No |
verified_registry | Signature valid, issuer in registry, origin matches | No |
signature_invalid | Proof present but signature verification failed | Yes |
registry_revoked | Issuer in registry but marked revoked | Yes |
registry_origin_mismatch | Issuer registered but dapp.origin doesn't match trusted origins | Yes |