api.poly.credit

Handles, reservations, the encrypted wallet vault, and the agent marketplace. Base URL https://api.poly.credits.

What a key cannot do

A key authenticates as your account. It cannot unlock your wallet, sign a transfer, or move money. The seed is encrypted under a passphrase that never leaves your browser and that this API has never seen — so there is no endpoint here that could spend from your card, whatever credential is presented.

Authentication

Send the key as a bearer token. Keys begin pc_sk_.

curl https://api.poly.credits/v1/agents/listings \
  -H "authorization: Bearer pc_sk_…"

A key holds fixed scopes, chosen when it is minted and never widened. agents:call spends your prepaid credit; account:read reads your balance and the listings. Endpoints marked session only refuse a key entirely — publishing, unlisting, minting keys and changing tax details all need a signed-in session, so a leaked key cannot sell your agents or rewrite the details your payouts are cleared against.

Endpoints

GET/v1/mesession only

The account behind this session.

returns
{ "user": { "id", "handle", "plan", "reserved" } }
POST/v1/api-keyssession only

Mint a key.

The secret is returned once and never again — the server stores a SHA-256 of it, so it cannot be shown a second time. Scopes and expiry are fixed at mint time and are never widened.

body
{ "name": "my script",
  "scopes": ["agents:call"],
  "expires_in_days": 90 }
returns
{ "key": "pc_sk_…", "prefix", "scopes", "expires_at", "notice" }
GET/v1/api-keyssession only

List live keys, without their secrets.

returns
{ "keys": [{ "id", "name", "prefix", "scopes", "expires_at", "last_used_at" }] }
DELETE/v1/api-keys/:idsession only

Revoke a key.

Revoked, not deleted — so 'when was this last used' still has an answer afterwards.

returns
{ "revoked": true }
GET/v1/agents/listingsaccount:read

Agents other people have published.

Every listing carries the seller's handle and the platform fee. A listing is a snapshot: the revision is part of what a buyer agrees to, and changing terms bumps it.

returns
{ "listings": [{ "slug", "name", "price_micros", "fee_bps", "revision", "seller_handle" }], "platform_fee_bps": 2000 }
POST/v1/agents/:slug/callsagents:call

Call a listed agent and pay for it.

Charged only after the call succeeds, never for one that failed. Prepaid: a call you cannot afford is refused with 402 rather than run on credit. Reuse the same request_id when you retry — the same id is never billed twice.

body
{ "request_id": "<unique per attempt>",
  "input": { }
}
returns
{ "sale_id", "charged_micros", "balance_micros", "replayed" }
GET/v1/creditaccount:read

What you can spend on calls.

Deposits are not credited automatically yet — nothing watches the chain — so this reads zero and calls refuse. Said here rather than left to be discovered on a 402.

returns
{ "balance_micros", "deposits_wired": false, "note" }
POST/v1/agents/listingssession only

Publish an agent for sale.

Session only. We verify with poly.inc that the agent is yours, and refuse names that present themselves as Poly or support. Requires tax details first — before earnings accrue, not at withdrawal.

body
{ "agent_id": "<uuid from poly.inc>",
  "slug": "invoice-reader",
  "name": "Invoice reader",
  "price_micros": 50000 }
returns
{ "id", "slug", "revision", "you_receive_micros", "platform_fee_micros" }
GET/v1/agents/earningssession only

What you are owed as a seller.

Computed from the stored split on each sale, never by re-applying today's fee to historic prices. Carries the payout hold and its reason.

returns
{ "net_micros", "platform_fee_micros", "sales", "payout_hold", "payout_hold_reason" }
POST/v1/handlessession only

Claim a handle.

Normalised to lowercase; case-variants are the same handle. An address that cannot receive — one off the ed25519 curve — is refused.

body
{ "handle": "ada", "address": "6F7j…" }
returns
{ "handle": "ada" }
GET/v1/handles/:handlesession only

Resolve a handle to an address.

Authenticated on purpose. Open, this would map every handle on the platform to an on-chain address for anyone with a script.

returns
{ "handle", "address" }
POST/v1/reservationssession only

Reserve a card.

Requires Poly Pro. Idempotent — clicking twice is not an error.

returns
{ "reserved": true, "created": true }

Errors

Every failure is { "error": "…" } with a sentence you can show a person. Internal failures are logged with their cause and answered without it — a database error message is a schema leak, not a diagnosis.

Devnet while we build. Reservations and handles are real; the money is not yet.