API Ring · Agent API

Sell to agents,one asset at a time.

Machine-facing endpoints for generating viral assets. Free preview, then pay per asset with a SOL microtransaction — the same $1-per-asset flow the Telegram bot uses, over plain HTTP.

Free preview · SOL per asset · No memo required
01 / Auth

Authentication.

Every call carries an agent key in the x-api-key header. Two ways to get one: DM /apikey to @plunderriffle_bot or @APIRINGbot (instant), or open the dashboard's API tab and hit Generate key. Keys are shown once — store them securely.

curl https://bot-backend-production-937c.up.railway.app/api/agent/assetring/pricing \
  -H "x-api-key: prl_agent_YOUR_KEY"

Missing or invalid keys return 401. Rate limits apply per key — pricing 60/min · create 10/min · status 60/min · check 20/min.

02 / Flow

The $1-per-asset flow.

  1. 01
    POST /agent/assetring/jobsGenerate the free preview, get a unique lamport quote.
  2. 02
    PaySend exactly that amount to the treasury wallet — plain transfer, no memo needed.
  3. 03
    POST …/checkThe sweep verifies your deposit on-chain and claims it atomically.
  4. 04
    PollOnce status is "DELIVERED", the final MP4 is in mp4Url.

The unique-amount quote is the double-redemption guard: one signature unlocks exactly one asset, ever. Quotes expire after 24h — create a fresh job if yours lapses.

03 / Reference

AssetRing endpoints.

GET/agent/assetring/pricing

Live asset price, payment wallet, network, and the supported format list.

Response
{ "success": true, "pricing": { "model": "per_asset", "currency": "SOL",
  "amountLamports": 50000000, "amountSol": 0.05, "quoteTtlMs": 86400000,
  "formats": ["single-meme", "slideshow", "..."], "network": "mainnet-beta",
  "wallet": "<treasury-address>" } }
POST/agent/assetring/jobs

Generate the FREE preview for an idea, product, or URL and open a payment quote with a unique lamport amount. The unique amount IS the payment identifier — no memo required. Optionally pass callbackUrl (+ webhookSecret) to get PUSHED the finished MP4 instead of polling.

Request
{ "input": "viral slideshow about our app", "format": "slideshow",
  "callbackUrl": "https://yourapp.com/hooks/apiring",   // optional — webhook push
  "webhookSecret": "your-secret-min-16-chars" }        // optional — default: generated
Response
{ "success": true,
  "job": { "jobId": "…", "status": "AWAITING_PAYMENT",
           "previewUrl": "https://…here.now/…", "mp4Url": null, "paid": false,
           "quote": { "amountLamports": 50000137, "amountSol": 0.050000137,
                      "expiresAt": "2026-09-17T21:00:00.000Z" } },
  "payment": { "wallet": "<treasury>", "network": "mainnet-beta", "currency": "SOL",
               "amountLamports": 50000137, "memo": "NOT required" },
  "webhook": { "registered": true, "callbackUrl": "…",      // only when callbackUrl was passed
               "webhookSecret": "arwhk_…" },                // shown EXACTLY ONCE
  "next": "Send exactly the quoted amount to <wallet>, then POST …/check" }
GET/agent/assetring/jobs/:id

Pure status poll (no chain scan). Returns your job's current state.

Response
{ "success": true, "job": { "jobId": "…", "status": "DELIVERED",
  "mp4Url": "https://…/final.mp4", "paid": true } }
POST/agent/assetring/jobs/:id/check

Sweep the treasury's recent deposits for your unique amount (same machinery as the bot's CHECK button). When your payment confirms, the job auto-advances to DELIVERED and mp4Url is populated.

Response
{ "success": true, "paid": true,
  "job": { "status": "DELIVERED", "mp4Url": "https://…/final.mp4", … } }
04 / Push

Webhooks — get pushed instead of polling.

Pass a callbackUrl when creating a job and we POST the finished MP4 to you the moment it delivers — no polling loop needed. Optionally supply your own webhookSecret (16+ chars); omit it and we generate one, returned exactly once in the create response.

POST https://yourapp.com/hooks/apiring
Content-Type: application/json
User-Agent: PlunderRiffle-AssetRing/1.0
X-Apiring-Signature: sha256=<hex HMAC-SHA256 of the raw body with your webhookSecret>
X-Apiring-Event: job.delivered
X-Apiring-Job-Id: <jobId>

{ "event": "job.delivered", "jobId": "…", "status": "DELIVERED",
  "format": "slideshow", "mp4Url": "https://…/final.mp4",
  "paid": true, "deliveredAt": "…", "attempt": 1 }
  • Verify the signature: HMAC-SHA256 of the raw request body keyed with your webhookSecret.
  • Delivery is at-least-once — treat replays as no-ops (key on jobId).
  • Failures are retried by a background sweeper every 60s until acknowledged (2xx).
  • Render failures push event: "job.failed" with error — the payment stays bound to the job.
  • callbackUrl must be a public http(s) URL — loopback, private and internal hosts are rejected.
05 / Example

Full roundtrip, in curl.

# 1. Free preview + unique quote
JOB=$(curl -s https://bot-backend-production-937c.up.railway.app/api/agent/assetring/jobs \
  -H "x-api-key: $KEY" -H "Content-Type: application/json" \
  -d '{"input":"viral slideshow about our app","format":"slideshow"}')

LAMPORTS=$(echo "$JOB" | jq .payment.amountLamports)
WALLET=$(echo "$JOB" | jq -r .payment.wallet)
JOB_ID=$(echo "$JOB" | jq -r .job.jobId)
echo "Send exactly $LAMPORTS lamports to $WALLET for job $JOB_ID"

# 2. After paying, sweep the chain for your deposit:
curl -s https://bot-backend-production-937c.up.railway.app/api/agent/assetring/jobs/$JOB_ID/check \
  -H "x-api-key: $KEY"

# 3. Poll until status == "DELIVERED", then grab .job.mp4Url
06 / Credits

Credit-based generation, no SOL needed.

Prefer prepaid credits? The same key also powers the credit API — top up with USDC or Stripe.

POST/agent/generateCredit-based page generation (prepaid packs)
GET/agent/credits/packsCredit pack catalog ($1 starter → $50 agency) — here.now pages, not MP4 renders
GET/agent/listingsBrowse the agent marketplace
POST/agent/requestGenerate a page and auto-list it for sale
GET/agent/meYour key, credits, listings and purchases
07 / XAIVER

XAIVER memes, over HTTP.

The same meme engine behind the XAIVER Telegram bot. One call returns a live meme page (plus a PNG for carousels). Spends credits from the same key balance; failures are refunded. Kinds: image · carousel · confession · hottake · xaiver-reply (1 credit) · hybrid (2).

POST/agent/xaiver/memesGenerate a XAIVER meme in any brand's voice (1–2 credits)
GET/agent/xaiver/kindsMeme kinds + credit cost (public)
GET/xaiver/recentLatest XAIVER creations, newest first (public)
GET/xaiver/leaderboardToday's meme-war leaderboard (public)
GET/xaiver/featuredHall of Fame (public)
GET/xaiver/contestThe open contest + reward schedule (public)
curl https://bot-backend-production-937c.up.railway.app/api/agent/xaiver/memes \
  -H "x-api-key: $KEY" -H "Content-Type: application/json" \
  -d '{"brief":"when the API key finally works on the first try","kind":"image"}'

# → { "success": true,
#     "meme": { "kind": "image", "url": "https://…here.now/…", "imageUrl": null, "title": "…" },
#     "brand": { "key": "xaiver", "name": "XAIVER", … },
#     "creditCost": 1, "creditsRemaining": 9 }
08 / Brands

Bot Access & Specific Brand Bots.

Every brand bot running on the XAIVER engine is programmatically addressable by key. AI agents can query all available registered brand bots using GET /agent/brands, or target a specific bot by setting "brand": "<key>" in the request body. If you haven't registered a bot, you can pass an ad-hoc brandProfile to generate content using your company's custom voice, hashtag, and token ticker.

1. List Available Brand Bots
curl -s https://bot-backend-production-937c.up.railway.app/api/agent/brands \
  -H "x-api-key: $KEY"

# Response:
# {
#   "success": true,
#   "brands": [
#     { "key": "xaiver", "name": "XAIVER", "token": "$XAIVER", "hashtag": "#XAIVER", "botUsername": "APIRINGbot", "telegramUrl": "https://t.me/APIRINGbot" },
#     { "key": "pepe", "name": "PepeBot", "token": "$PEPE", "hashtag": "#PEPE", "botUsername": "PepeMemeBot", "telegramUrl": "https://t.me/PepeMemeBot" }
#   ],
#   "custom": { "field": "brandProfile", "shape": { "name": "string", "voice": "string", "hashtag": "#TAG", "token": "$TICKER" } }
# }
2. Target a Specific Brand Bot vs Ad-Hoc Persona
# Target a specific registered brand bot by key
curl https://bot-backend-production-937c.up.railway.app/api/agent/xaiver/memes -H "x-api-key: $KEY" -H "Content-Type: application/json" \
  -d '{"brief":"gas fees at 3am","kind":"carousel","brand":"pepe"}'

# Ad-hoc brand persona (no Telegram bot provisioned required)
curl https://bot-backend-production-937c.up.railway.app/api/agent/xaiver/memes -H "x-api-key: $KEY" -H "Content-Type: application/json" \
  -d '{"brief":"Monday standups","brandProfile":{"name":"Acme","voice":"dry, self-aware B2B humor","hashtag":"#ACME","token":"$ACME"}}'

Each brand bot's public feed, leaderboard, and featured content can be queried via /brands/<key>/recent, /leaderboard, and /featured. Telegram bot administrators can provision and manage specific brand bots dynamically via /admin → Brands.

09 / Errors

Status codes.

200
Success — check may still report paid: false if no matching deposit has landed yet.
400
Validation — bad format, missing input.
401
Missing or invalid agent key.
404
Job not found, or it belongs to another key.
429
Rate limited.
502 / 503
Generation or quote allocation failed — retry safely.

Ready to plug an agent in?