Registry endpoints
Publish
POST /api/v1/registry/announcements validates and stores new announcements.
List
GET /api/v1/registry/announcements returns paginated announcements with filters.
Stats
GET /api/v1/registry/stats returns total count and non-zero view-tag distribution.
POST /api/v1/registry/announcements
Request schema
Preferred publish path. Use the payment_id returned by /api/v1/stealth/create.
Fallback publish path. Use the full announcement object returned by /api/v1/stealth/create only when payment_id is unavailable or expired.
Monad announce transaction hash. Required when the relayer is not configured; ignored when server-side relaying is active.
Optional source-chain payment transaction hash for verification and encrypted metadata.
Optional EIP-155 chain ID for the source-chain payment.
Optional amount string in decimal base units or 0x hex uint256.
Optional source-chain name (for example ethereum, arbitrum, base, monad-testnet).
Optional ERC-20 token contract address for source-chain payment verification.
Response schema
Assigned registry announcement id.
Publish confirmation.
Monad Testnet transaction hash of the announce() call. Monad is the registry chain where announcements are recorded. When the relayer is not configured, this matches the tx_hash you supplied.
GET /api/v1/registry/announcements
Query parameters
Filter announcements by a specific view tag.
Start of time-range filter (Unix timestamp).
End of time-range filter (Unix timestamp).
Pagination offset.
Pagination limit.
Response schema
Paginated announcement rows.
Total matching rows before pagination.
GET /api/v1/registry/stats
Response schema
Current total number of stored announcements.
Array of non-zero tag buckets (tag, count).
Example calls
- Publish (cURL)
- List (cURL)
- Stats (cURL)
curl -s -X POST https://backend.specterpq.com/api/v1/registry/announcements \
-H "Content-Type: application/json" \
-d '{
"payment_id":"<PAYMENT_ID_FROM_STEALTH_CREATE>",
"tx_hash":"0xabc123...",
"payment_tx_hash":"0xdef456...",
"source_chain_id":1,
"chain":"ethereum",
"amount":"100000000000000000"
}' | jq .
curl -s "https://backend.specterpq.com/api/v1/registry/announcements?view_tag=42&offset=0&limit=20" | jq .
curl -s "https://backend.specterpq.com/api/v1/registry/stats" | jq .
Behavior notes
Duplicate transaction hashes are rejected
Publish reserves a dedup slot before relaying. When server DB keys are configured, payment_tx_hash is normalized and HMACed for duplicate-payment prevention without storing the payment hash plaintext.
List filter precedence
Listing uses view_tag when present. If absent, it uses time range only when both from_timestamp and to_timestamp are provided. Otherwise it returns all.
Storage scope
API state uses MemoryRegistry in local/dev mode and Turso when REGISTRY_BACKEND=turso is configured.
Metadata encryption
The preferred payment_id path encrypts payment metadata into a 93-byte blob while keeping byte 0 (view_tag) plaintext. The fallback announcement path has no shared secret and emits 77-byte plaintext metadata.
The plaintext block is 77 bytes laid out as:
| Bytes | Field | Size |
|---|---|---|
| 0 | view_tag | 1 |
| 1-32 | tx_hash | 32 |
| 33-64 | amount (uint256) | 32 |
| 65-72 | source_chain_id (big-endian u64) | 8 |
| 73-76 | reserved | 4 |
Encryption uses AES-256-GCM and adds a 16-byte authentication tag over bytes 1-76, leaving the view_tag in the clear: 1 + 76 + 16 = 93 bytes. The @specterpq/sdk produces the same block client-side. See announcement metadata.