1. Getting access as an agent
An agent acting for a person needs that person's permission. Three ways, from most to least common:
- OAuth: MCP apps and API clients send the person to an IndexerPal page to allow access (details).
- An API key the person creates in the dashboard and gives to the agent.
- Agent registration (/auth.md,
service_auth): the agent only knows the person's email.
Agent registration in four calls
# 1. Register with the user's email
curl -X POST https://indexerpal.com/api/agent/identity \
-H "Content-Type: application/json" \
-d '{"type": "service_auth", "login_hint": "[email protected]", "agent_name": "Acme assistant"}'
# 2. Show the user claim.verification_uri and claim.user_code (6 digits).
# They log in (or sign up) as that email and type the code.
# 3. Poll every 5 seconds until it succeeds
curl -X POST https://indexerpal.com/oauth/token \
-d grant_type=urn:workos:agent-auth:grant-type:claim -d claim_token=clm_...
# 4. When the access token expires, exchange the identity assertion
curl -X POST https://indexerpal.com/oauth/token \
-d grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer -d assertion=IDENTITY_ASSERTION
IndexerPal sends no email for a registration: the code travels from the agent to the person, who types it on a page where they're signed in as that address. On that page they can also untick permissions the agent asked for; the token's scope says what was granted. After 5 wrong codes the registration is locked. The person can disconnect the agent at any time from the dashboard. Full protocol: /auth.md.
2. Buying credits for a user
Credits come in one-time packs; the card payment always happens on IndexerPal's Stripe page, by a person, so no card details pass through an agent. x402 is the exception: the agent pays in USDC itself.
| Way | For | How |
|---|---|---|
| Checkout link | Any agent (API, MCP) | POST /api/v1/checkout or the buy_credits tool returns checkout_url. Give it to the person, then poll GET /api/v1/orders/{id} until paid. |
| ACP | Agents that speak the Agentic Commerce Protocol | Checkout sessions that escalate to the person through continue_url. |
| UCP | Agents that speak the Universal Commerce Protocol | Checkout sessions that escalate to the person through continue_url. |
| A2A with AP2 | Agents that delegate over A2A | Ask the agent to buy a pack: you get an AP2 CartMandate and the payment link. |
| x402 | Agents with a USDC wallet | Pay over HTTP 402, where enabled. No person needed. |
Prices are final: nothing is added at checkout. The account must already exist; buying is allowed before the first purchase (that's how an account starts).
3. Agentic Commerce Protocol (ACP)
Discovery: /.well-known/acp.json. Version 2026-04-17, REST at https://indexerpal.com/api/acp, bearer token with the purchase scope. Items are pack ids (basic, pro, premium, agency), one per session.
curl -X POST https://indexerpal.com/api/acp/checkout_sessions \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"line_items": [{"id": "pro"}], "currency": "usd", "capabilities": {}}'
The session comes back as requires_escalation with a continue_url: the person pays there, then the session reads completed. Also available: GET and POST /checkout_sessions/{id}, /complete and /cancel. Delegated payment tokens are declined.
4. Universal Commerce Protocol (UCP)
Profile: /.well-known/ucp. Version 2026-08-25, shopping service over REST at https://indexerpal.com/api/ucp, checkout and identity linking (our OAuth server) capabilities.
curl -X POST https://indexerpal.com/api/ucp/checkout-sessions \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"line_items": [{"item": {"id": "premium"}, "quantity": 1}]}'
Sessions escalate with requires_escalation and continue_url; GET, PUT, /complete and /cancel work as in the spec. No payment handlers are offered.
5. A2A agent (with AP2)
Agent card: /.well-known/agent-card.json. JSON-RPC at https://indexerpal.com/a2a (A2A 1.0; 0.3 method names work too), bearer token. Skills: index URLs (or a sitemap), check URLs, project status, account and pricing, buy credits.
curl -X POST https://indexerpal.com/a2a \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "SendMessage", "params": {"message": {"messageId": "1", "role": "ROLE_USER",
"parts": [{"text": "Index https://example.com/new-post with instant indexing"}]}}}'
Indexing answers with a task whose id is the project id: GetTask follows it to completion, CancelTask takes unsent URLs back. Structured requests work too, as a data part: {"skill": "check-indexed", "urls": [...]}.
AP2 (merchant role): asking to buy a pack returns a task in TASK_STATE_INPUT_REQUIRED with an AP2 CartMandate signed by IndexerPal (key in /.well-known/jwks.json) and the payment link. The task completes when the person has paid.
6. In the browser (WebMCP)
Pages of IndexerPal register tools with document.modelContext for agents built into the browser: get-pricing, estimate-cost, open-page, buy-credits (opens checkout) and get-agent-access. They never act on an account by themselves: anything account-related opens a page where the person stays in control.
7. Our bot (Web Bot Auth)
When you import a sitemap, IndexerPal fetches it with the user agent IndexerPalBot/1.0. Its requests are signed (HTTP Message Signatures, RFC 9421, tag="web-bot-auth"), so a site or CDN can verify them instead of trusting the user agent:
Signature-Agent: sig1="https://indexerpal.com"
Signature-Input: sig1=("@authority" "signature-agent";key="sig1");created=...;keyid="...";alg="ed25519";expires=...;nonce="...";tag="web-bot-auth"
Signature: sig1=:...:
The public key is at /.well-known/http-message-signatures-directory, matched by keyid. The bot only fetches the sitemap URLs a user gives it, and never private addresses.