Passkey Indexer
Mercury runs a free, public indexer for passkey-kit smart wallets on Stellar. It indexes both event generations — the legacy sw_v1 contracts (live on mainnet and testnet) and the v1 contract vocabulary — live on both networks, with the full wallet history held by Mercury already indexed.
The indexer is currently free to use, and for now requires no authentication or API key.
Base URLs
Testnet
https://testnet.mercurydata.app/rest/passkey-indexer
Mainnet
https://mainnet.mercurydata.app/rest/passkey-indexer
Endpoints
All endpoints are GET, public, and return JSON.
/
Health check: {"status":"ok","service":"passkey-indexer"}
/api/lookup/:credentialId
Find wallets by WebAuthn credential ID (hex, 0x prefix optional, lowercased)
/api/lookup/address/:address
Find wallets by ed25519 (G...) or policy (C...) signer address
/api/wallet/:contractId
Full signer state for one wallet, including removed signers
/api/stats
Indexer statistics: totals, ledger range, per-event-type counts per generation
Lookups match active signers only. /api/wallet/:contractId returns 404 with {"error":"Wallet not found"} only when the contract has no indexed signers at all; a wallet whose signers were all removed still returns 200 with tombstoned signers.
Example:
curl https://mainnet.mercurydata.app/rest/passkey-indexer/api/lookup/1a9eb168624d3ecfeb964f58c5f7ddf00e78fa74{
"credentialId": "1a9eb168624d3ecfeb964f58c5f7ddf00e78fa74",
"wallets": [
{
"contract_id": "C...",
"generation": "legacy",
"signer_count": 1,
"first_seen_ledger": 54309985,
"last_seen_ledger": 54309985
}
],
"count": 1
}generation is "legacy" or "v1" — the generation of the latest event seen for the wallet (an upgraded wallet reads "v1").
Wallet signers
/api/wallet/:contractId returns:
key — type is "secp256r1", "ed25519", or "policy"; value is the WebAuthn credential ID (lowercase hex) for secp256r1, a G... strkey for ed25519, a C... strkey for policy.
publicKey — 65-byte SEC-1 uncompressed secp256r1 public key, lowercase hex. Present for secp256r1 signers only.
expiration / expiration_unit — the raw on-chain number; semantics depend on the generation that wrote the signer: "ledger" (legacy) is a ledger sequence, "unix" (v1) is UNIX seconds. Both are inclusive: the signer is still valid at the expiration ledger/second itself. Omitted when the signer never expires.
limits — preserves the on-chain SignerLimits semantics exactly: field omitted = unlimited; {} (empty object) = fail-closed deny-all (not the same as unlimited); otherwise an object mapping contract address to either null (any key context) or an array of key objects the signer is restricted to.
storage — "persistent" or "temporary".
status — "live", "expired" (active but past expiration, computed per unit against the current ledger or clock), or "removed" (tombstone; last-known fields kept). "evicted" is intentionally never derived: temporary-storage eviction is not observable from events, so SDKs needing eviction status should probe RPC for the ledger entry.
Last updated