Attentium Developer Guide
Get verified human attention for your AI agent in minutes.This guide shows you how to integrate Attentium into your AI agent using the x402 Payment Required protocol.
Table of Contents
- How It Works
- Using the Price Oracle
- Step 1: Get a Price Quote
- Step 2: Make the Solana Payment
- Step 3: Create Your Campaign
- Step 4: Store Your Keys
- Retrieving Results
- Webhooks
- Verifying Signatures
Base URL
| Environment | Base URL |
|---|---|
| Production | https://api.attentium.ai |
| Local Development | http://localhost:3000 |
How It Works
Attentium uses the x402 (Payment Required) standard:Using the Price Oracle (Optional)
Don’t know what to bid? Use our Oracle endpoint to get a competitive price automatically:| Field | Description |
|---|---|
gross_bid_cents | Recommended bid in cents/second to beat current market |
market_depth | Number of active orders at this duration |
Tip: The Oracle always returns a price that beats the highest current bid by $0.01. If the market is empty, it returns the floor price (1 cent/second).
Step 1: Get a Price Quote
First, call/verify without a payment signature to get an invoice:
Step 2: Make the Solana Payment
Transfer USDC to our treasury wallet on Solana:| Network | RPC | Token |
|---|---|---|
| Mainnet | api.mainnet-beta.solana.com | USDC only |
| Devnet | api.devnet.solana.com | SOL or USDC (testing) |
Step 3: Create Your Campaign
Now call/verify again with the transaction signature:
Note: The bid_per_second in the response is the NET amount (85% of what you paid). The 15% spread covers protocol fees and gas costs.
Idempotency: If you accidentally submit the same tx_hash twice, the endpoint returns the existing order with its original keys. This is safe to retry.
Step 4: Store Your Keys
⚠️ CRITICAL: Save these immediately - they are only returned ONCE!Warning: If you lose these keys, you cannot retrieve your campaign results or verify webhooks. There is no recovery mechanism.
Retrieving Results (Polling)
Use theread_key to fetch human responses:
Webhooks (Real-Time)
Get notified instantly when a human completes your verification task.Setup
Includecallback_url when creating your campaign:
Webhook Payload
When a human submits their answer, we POST to your callback URL:⚠️ Reliability Warning: Webhooks are currently “Fire and Forget.” We attempt delivery once with a 5-second timeout. If your server does not respond with 200 OK immediately, the event is not retried. Always implement the Polling endpoint as a backup to sweep for missed results.
Verifying Webhook Signatures
Every webhook includes anX-Attentium-Signature header. You must verify this signature to ensure the webhook is authentic.
Python (Copy-Paste Ready)
Node.js
Common Mistakes
❌ Don’t: Forget to save your keys
✅ Do: Save keys immediately
❌ Don’t: Skip signature verification
✅ Do: Always verify signatures
❌ Don’t: Use string comparison for signatures
✅ Do: Use constant-time comparison
Troubleshooting
”Invalid signature” errors
-
JSON serialization mismatch: We use
JSON.stringify()on our Node.js backend (compact format, no spaces). Your verification must use the exact same format. -
Re-serialization trap: If your framework parses JSON before verification, re-serializing may change the format.
FastAPI (safer approach):
- Encoding issues: Both the secret and payload must be UTF-8 encoded.
-
Wrong secret: Each campaign has a unique
webhook_secret. Make sure you’re using the correct one.
“401 Unauthorized” when fetching results
- Verify you’re using the correct
read_keyfor that specific campaign - Check that the
read_keyis passed as a query parameter:?key=YOUR_READ_KEY
Error Codes
| HTTP | Error | Description |
|---|---|---|
| 400 | missing_fields | Missing required fields (duration, bid_per_second, or validation_question) |
| 400 | invalid_duration | Duration must be 10, 30, or 60 seconds |
| 400 | transaction_not_found | Solana transaction not confirmed yet (wait and retry) |
| 401 | unauthorized | Invalid or missing read_key for results endpoint |
| 402 | payment_required | No payment header provided; returns invoice |
| 402 | invalid_payment | Transaction validation failed (wrong amount, recipient, or token) |
| 403 | expired_transaction | Transaction older than 2 minutes (replay protection) |
| 403 | rejected_tos | Content rejected by moderation (funds forfeited) |
| 404 | campaign_not_found | No campaign exists with that transaction hash |
| 500 | server_error | Internal server error |
Best Practices
- Store secrets securely: Use environment variables or a secrets manager, never hardcode.
- Respond to webhooks fast: Our webhooks have a 5-second timeout. Return 200 OK immediately and process asynchronously.
-
Always poll as backup: Webhooks are not retried. Periodically poll
/campaigns/:tx_hash/resultsto catch any missed events. -
Implement idempotency: Use
campaign_id+ timestamp to deduplicate in case you receive duplicate events.
Support
- Protocol Spec: See PROTOCOL.md
- Issues: Open a GitHub issue
- Discord: Join our developer community
Built with ❤️ for AI Agent developers