# Relaystation — full agent reference Pay-per-call API platform for AI agents and developers. Prepaid; no monthly fees, no subscription. Network: Base. Payment assets: USDC, EURC (same EIP-3009 settlement; 1:1 micros pricing). ## Baton — the model A baton is a prepaid storage object configured along five independent groups. Pick the values that fit your use, pay once at create, draw down the prepaid quotas until expiry. There are no post-create per-use charges. 1. Write behavior — one of four: - Single object — stores one file, image, video, or binary payload. Replace it any time; delete it when done. - Append — a text log you add entries to over time. - Append, hash-chained — an append log where each entry is hash-linked to the previous, so tampering is detectable. Auto-includes a document-witness. - Overwrite — a text file you replace in full; only the latest is kept. 2. Capacity — size (storage), duration (validity), egress (the read budget). A single write over 3 MB uploads via a presigned URL the create returns. 3. Sharing — collaborator tokens. Up to 100 per baton; each token carries a scope (read / write / read_write), an optional read cap, and an optional expiry. 4. Lifecycle — burn-after-reading (delete the baton once every token read cap is consumed) and disposal (soft delete with a grace period, or hard delete). 5. Trust — document-witness. When enabled, Relaystation cryptographically signs the content hash and keeps the signed record for 7 years; verify offline against Relaystation's published key. Funding mechanisms (two — both resolve to one customerId): - x402 per-call (no account) — sign EIP-3009 USDC off-chain, one HTTPS call carries payload + X-Payment header. The wallet IS the identity. (A wallet can also sign in via wallet-JWT to read its account/history — that is authentication, not a separate way to pay.) - Stripe-funded balance — human signs up via OAuth, tops up via Stripe Checkout (card or crypto), balance debited per order. ## Preconfigs — fast-start prefills Five preconfigs set the five-group values to common shapes; every value remains configurable on create. They are fast-start prefills, not the organizing principle. - Drop — Store a file. Single object; multi-read until expiry. - Pass — Share a file. Single object plus a read-capped token; burns once the token is consumed. - Scratchpad — Collaborate. Append log; tokens for collaborators. - Checkpoint — Save state. Overwrite; replace the snapshot as you go. - Ledger — Audited Ledger. Append, hash-chained; tamper-evident; auto-witnessed. ## Pricing One engine-computed quote is the published price. Quote any shape with POST /v1/baton/quote; create it with POST /v1/baton. The price is the engine quote of the shape, frozen at create. No catalog prices; no tiers as priced SKUs. Settlement: each x402 call authorizes a $0.01 settlement chunk (the 402 advertises it as maxAmountRequired). Calls >= $0.01 settle on-chain individually; sub-cent calls draw down off-chain from an already-settled chunk until exhausted, then the next chunk settles -- on common sub-cent ops a penny covers around 50 calls. You are charged exactly the sum of your call prices (capture-to-actual), never $0.01 per call; on-chain settlement is batched at the chunk. Every chunk + draw-down is a ledger row you can audit. (The $0.001 network-minimum is the chunk's on-chain floor, not a per-call charge.) ## x402 wire summary Header: X-Payment: . Assets: USDC or EURC. The 402 challenge lists one accepts[] entry per asset; pick one and sign its EIP-712 domain. Domain: { name, version, chainId, verifyingContract } — take name + version from the chosen accepts[].extra (USDC = "USD Coin"/"2" on Base mainnet, "USDC"/"2" on Base Sepolia; EURC = "EURC"/"2"), verifyingContract = that asset's contract. Types: TransferWithAuthorization(address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce). Server response success: HTTP 200/201 + PAYMENT-RESPONSE header (base64 receipt with tx hash, payer, amount). Server response payment-required: HTTP 402 with body { x402Version: 2, accepted: [...], error: "PAYMENT_REQUIRED" }. ## Trust model Two prepaid flags: - hashChaining — chained per-entry hash, append-only enforced (a chained baton with overwrite=true returns 409). - witness — flat document-witness ($0.05 standalone, OR prepaid at create when chained — requires: witness). A chained baton (hashChaining=true) auto-commits a prepaid witness. The customer can call POST /trust/document-witness any time; if they never do, the auto-seal-at-expiry sweeper pass fires it at expiry, free, while content is live. Verify offline via GET /trust/proof + POST /trust/challenge. Public, free, per-IP rate-limited on challenge. ## Full endpoint roster ### System / discovery GET /v1/baton/system/info — agent-facing descriptor. GET /v1/baton/system/egress-ips — outbound webhook delivery IPs (currently dynamic; HMAC-verify advisory in body). GET /v1/baton/prices — the named preconfigs + their default shapes (fast-start prefills). POST /v1/baton/quote — public price-of-record for any shape (a preconfig ref or a custom shape). GET /openapi.json — OpenAPI 3.1. GET /llms.txt — concise summary. GET /llms-full.txt — this document. GET /.well-known/mcp.json — MCP advertisement. GET /.well-known/ai-catalog.json — ARD (Agentic Resource Discovery) manifest: MCP server + REST API + llms.txt + recipe pages, one machine-readable catalog. POST /mcp — MCP transport (JSON-RPC over HTTP). ### Baton lifecycle POST /v1/baton — create. Billable. Pays at create; the whole baton config (resources + flags) is frozen onto the baton. GET /v1/baton/{id} — read (owner-addressed). GET /v1/baton/{tokenId} — read (token-addressed; "tok_<43-char>" replaces {id} on the URL). No Authorization header required. POST /v1/baton/{id} — write (owner-addressed; append for append / append-chained batons, overwrite/replace for single-object / overwrite batons). POST /v1/baton/{tokenId} — write (token-addressed). GET /v1/baton/{id}/entries — paginated entries (owner). GET /v1/baton/{tokenId}/entries — paginated entries (token). GET /v1/baton/{id}/tail — long-poll for new entries (owner). GET /v1/baton/{tokenId}/tail — long-poll (token). DELETE /v1/baton/{id} — soft-delete + scheduled purge per on_expiration. POST /v1/baton/{id}/add — buy another tier of the same preset. Billable. POST /v1/baton/{id}/extend — buy à-la-carte dimensions (size, duration, egress, writes). Billable. GET /v1/baton/{id}/meta — read metadata + flags snapshot. POST /v1/baton/{id}/meta — mutate metadata (allowlisted fields only). GET /v1/baton/{id}/event-logs — paginated audit log. ### Tokens (collaborators) POST /v1/baton/{id}/tokens — mint a token (read / write / read_write capability + per-token caps). GET /v1/baton/{id}/tokens — list tokens. POST /v1/baton/{id}/tokens/{tokenId} — modify (mutable subset) OR revoke ({"revoke":true}). ### Trust POST /v1/baton/{id}/trust/document-witness — freeze + sign the baton (billable $0.05 standalone OR free on prepaid path). POST /v1/baton/{id}/trust/verify-chain — verify chained-hash integrity (free). POST /v1/baton/{id}/trust/challenge — public, free; per-IP rate-limited. Match a candidate against a witnessed baton. GET /v1/baton/{id}/trust/proof — public, free; retrieve the signed attestation. ### Auth bootstrap GET /v1/auth/challenge?wallet=0x... — wallet sign-in nonce. POST /v1/auth/verify — verify EIP-191 sig, mint wallet JWT. ### Account GET /v1/account — customer profile + balance. POST /v1/account/api-keys/regenerate — rotate API key (dashboard auth only). GET /v1/account/products / POST /v1/account/products/{product}/enable — enrollment primitive (no valid product slugs registered). ### Webhooks POST /v1/webhooks — register a webhook (returns secret ONCE). GET /v1/webhooks — list. GET /v1/webhooks/{id} — detail. PUT /v1/webhooks/{id} — update. DELETE /v1/webhooks/{id} — delete. GET /v1/webhooks/{id}/deliveries — paginated delivery history. ### Billing POST /v1/billing/checkout — Stripe Checkout for balance top-up (dashboard auth). GET /v1/billing/packs — public pack list + custom-amount bounds. ### E-sign (esigndoc) — send PDFs for legally-binding e-signature Billed per sent envelope; charge-on-successful-send, no refund. The PDF is a multipart `pdf` File or the cputools input-source ({ inline } base64 / { inputKey }). POST /v1/esigndoc/envelopes — create from a PDF + recipients; sends (and bills) when fields or autoPlaceSignature are present, else a free draft. POST /v1/esigndoc/envelopes/from-template — instantiate from a template; bills when sendImmediately. POST /v1/esigndoc/envelopes/{id}/send — distribute a draft. Billable. GET /v1/esigndoc/envelopes — list. GET /v1/esigndoc/envelopes/{id} — cached detail. GET /v1/esigndoc/envelopes/{id}/status — live status. GET /v1/esigndoc/envelopes/{id}/download — signed/original PDF (binary). GET /v1/esigndoc/envelopes/{id}/signed-document — same in the cputools output envelope (agent-friendly). POST /v1/esigndoc/envelopes/{id}/resend — chase unsigned recipients. POST /v1/esigndoc/envelopes/{id}/fields + DELETE …/fields/{fid} — edit fields on a draft. DELETE /v1/esigndoc/envelopes/{id} — cancel. POST|GET /v1/esigndoc/templates, GET|PUT|DELETE /v1/esigndoc/templates/{id} — reusable templates (all free). ### ID verification (idverify) — hosted identity checks Billed per verification; charge-on-attempt, the async verdict never refunds. POST /v1/idverify/verifications — initialize a document / liveness / biometric check (optional addons.aml); returns a hostedUrl the end-user completes. Billable. GET /v1/idverify/verifications — list. GET /v1/idverify/verifications/{id} — cached detail. GET /v1/idverify/verifications/{id}/status — live re-poll (self-heals the cache). Government-ID documents only (passport / driver's license / national ID), not arbitrary credentials. ### Screening (screening) — sanctions + PEP name screening Billed per match attempt (charge-on-attempt). Composable standalone compliance primitive — no full ID check required. POST /v1/screening/match — screen a name against sanctions (OFAC / EU / UK; UN rides along) and Wikidata-derived PEP lists; scope via lists:[sanctions,pep] (default both). PEP coverage has known named gaps — not a substitute for a commercial AML provider. Free sources; attribution returned in every response. ### Language & AI tasks (llm) — task-based, cost-plus POST /v1/llm/{task} with { tier: budget|value|best, input, params? } — translate, summarize, extract to JSON, classify, proofread, rewrite, sentiment, keywords, title, repair JSON. You authorize the published per-increment ceiling and pay the actual provider cost + a small markup. The model behind each tier is named + dated on the disclosure page. GET /v1/llm/tasks — FREE live catalog (admin-managed registry rows). ### Agent contracts (contracts) — binding-by-goodwill agreements + arbitration POST /v1/contracts — create a binding agreement (terms + parties; a hash-chained, auto-witnessed record). POST /v1/contracts/{id}/sign — sign (EIP-712 wallet or authenticated account). GET /v1/contracts/{id} — check whether all parties have signed. POST /v1/contracts/{id}/arbitrate — open a dispute for a transparent AI ruling. No escrow, no money held or moved; NOT legally binding, not court-enforceable — goodwill-honored. Offline-verifiable via GET /v1/contracts/disclosure. ### Retrieval — vector search + RAG Vector baton — the `vector` preset is a prepaid similarity-search index, priced and disposed exactly like any baton (size × duration; the index is destroyed at expiry). POST /v1/baton { preset: "vector", ... } freezes dims + metric at create. POST /v1/baton/{id}/vectors — write vectors (id + values + optional metadata), metered per started batch. POST /v1/baton/{id}/vectors/query — nearest-neighbor top-k; pass a numeric vector, or raw text that is embedded for you. Empty index → []. POST /v1/rag/answer — the full retrieval loop under ONE charge: embed the question, retrieve the top-k chunks from a vector baton, and answer from ONLY those chunks with source ids (chunks are untrusted data; sources come from the retrieval, not the model). Settle-at-actual = embed units + retrieval + the LLM cost. POST /v1/llm/embed — standalone embeddings (Titan v2), single string or a batch, metered per started 10 KB; returns the vectors + dimensions. Docs: https://relaystation.ai/docs/rag ### Async jobs — submit → poll → job.completed Long-running ops return a job ticket immediately instead of blocking the request. POST /v1/doc/analyze-async (multi-page PDF document analysis, the first consumer) starts a Textract job and returns { ticket, status: "running", ceiling_micros }. GET /v1/jobs/{id} — poll one job (statuses: submitted / running / succeeded / failed / expired); the result is inline when small, or a scratch URL / delivered into a baton. Or subscribe to the job.completed webhook (account registry) for a push. Billing: the x402 rail settles the counted ceiling at submit (the price is deferred, not the money); a prepaid-balance / API-key call holds at submit and captures the ACTUAL at completion; a failed or timed-out job is made whole (hold released, or the settled amount credited back off-chain). Docs: https://relaystation.ai/docs/async-jobs ### Bundles — one-call recipes (curated multi-step workflows, one payment) POST /v1/bundles/rag-ingest — { text, batonId?, chunkBytes? }: chunk the text, embed each chunk, and write the vectors into a vector baton (creates one if batonId is absent; returns the id — persist it, it is the memory address). Bills the sum of steps (embed units + vector batches + create when applicable). POST /v1/bundles/rag-query — { batonId, question, answer?, topK? }: embed the question, nearest-neighbor query the vector baton, and (answer: true) synthesize a grounded answer from ONLY the retrieved chunks with source ids. Bills the sum of steps. POST /v1/bundles/ingest-document — { file }: OCR a scanned document into a searchable PDF, extract its tables, write them to xlsx, and drop both artifacts to durable URLs. The cputools showcase in one payment; bills the sum of steps. Full worked recipes (services, workflow, cost per run, a copyable agent prompt): https://relaystation.ai/recipes/agent-rag-memory · /recipes/storage-handoff · /recipes/document-chores · /recipes/kyc-then-sign ## Compute tools (cputools) — full op reference 143 pay-per-call file/data ops across 21 categories (pdf, image, media, doc, office, qr/barcode/codes, csv, data, pipeline, text, utils, archive, generate). I/O: inline base64 (≤4 MiB), free 24h scratch via POST /v1/cputools/upload-url (chain an op's outputKey as the next op's inputKey), or a baton as a durable input/output. Each op is also an MCP tool (GET /mcp/full) and is in /openapi.json with its full schema. ### cputools — pdf POST /v1/pdf/attachments — List (and optionally extract) embedded file attachments in a PDF. POST /v1/pdf/bookmarks — Read a PDF outline / bookmarks. POST /v1/pdf/compress — Recompress a PDF (qpdf object+content streams, worker). POST /v1/pdf/diff — Text-compare two PDFs (extract text → unified diff). POST /v1/pdf/encrypt — Password-protect a PDF (qpdf, 256-bit AES, worker). POST /v1/pdf/extract-text — Extract text from a (text-layer) PDF via unpdf. POST /v1/pdf/form — Fill AcroForm fields and/or flatten a PDF (pdf-lib). POST /v1/pdf/from-html — Generate a PDF from HTML on headless Chromium (dedicated render worker) — invoices/reports/contracts/certificates. POST /v1/pdf/from-office — Convert an Office document to PDF (LibreOffice) — docx/xlsx/pptx/odt/ods/odp/rtf/txt/csv. POST /v1/pdf/images — Extract embedded images from a PDF → PNGs. POST /v1/pdf/merge — Merge 2+ PDFs into one (pdf-lib). POST /v1/pdf/metadata — Read or set PDF document metadata (pdf-lib). POST /v1/pdf/ocr — OCR a scanned/image PDF (pdftoppm → tesseract LSTM, worker). POST /v1/pdf/ocr-searchable — Make a scanned PDF SEARCHABLE: per page, render → tesseract emits a page PDF with the image + an invisible text layer → qpdf merges. POST /v1/pdf/pages — Delete / reorder / insert PDF pages (pdf-lib). POST /v1/pdf/render — Rasterize PDF pages to PNG/JPEG (poppler pdftoppm, worker). POST /v1/pdf/repair — Repair a damaged PDF (qpdf, worker): `qpdf --check` diagnoses (findings report), then a full rewrite reconstructs the xref + normalizes structure. POST /v1/pdf/rotate — Rotate pages 90/180/270° (pdf-lib). POST /v1/pdf/split — Split one PDF into multiple (pdf-lib). POST /v1/pdf/verify-signatures — Verify a PDF's digital signatures (poppler pdfsig, worker). POST /v1/pdf/watermark — Stamp text on PDF pages (pdf-lib). ### cputools — image POST /v1/image/adjust — Adjust image color/tone (sharp modulate/negate/tint). POST /v1/image/blur — Gaussian-blur an image. POST /v1/image/composite — Overlay/watermark one image onto another. POST /v1/image/compress — Compress an image at its current format (sharp). POST /v1/image/contact-sheet — Tile images into a thumbnail-grid PNG. POST /v1/image/convert — Convert image format (sharp; png/jpeg/webp/avif — HEIC input supported). POST /v1/image/crop — Crop a region from an image. POST /v1/image/dominant-color — Get the dominant color of an image. POST /v1/image/exif-strip — Strip EXIF/metadata from an image (auto-orients first, then drops all metadata). POST /v1/image/extend — Pad (extend) an image on any side (sharp). POST /v1/image/from-html — Render caller-supplied HTML to an image (png/jpeg/webp) via headless-Chromium page.screenshot on the dedicated render worker. POST /v1/image/grayscale — Convert an image to grayscale. POST /v1/image/metadata — Read image dimensions/format/EXIF presence (sharp). POST /v1/image/ocr — OCR a raster image (tesseract LSTM, worker — PNG/JPEG/TIFF/BMP/WebP). POST /v1/image/resize — Resize an image (sharp). POST /v1/image/rotate — Rotate / flip an image (sharp). POST /v1/image/sharpen — Sharpen an image. POST /v1/image/trim — Auto-crop uniform-color borders from an image (sharp trim). ### cputools — media POST /v1/media/audio-convert — Re-encode an audio file to another audio format/bitrate/sample-rate — a standalone audio↔audio transcode (vs media_audio_extract, which pulls audio off a video). POST /v1/media/audio-extract — Strip + (re)encode the audio track of a media file. POST /v1/media/audio-mix — Mix multiple audio inputs down to one track (ffmpeg amix). POST /v1/media/concat — Join 2–10 clips end-to-end via the ffmpeg concat demuxer (fast STREAM-COPY — no re-encode). POST /v1/media/convert — Convert a media file to another container/codec (RE-ENCODE). POST /v1/media/frames — Extract evenly-sampled frames from a video → a manifest of presigned image refs (mirrors pdf_render). POST /v1/media/gif — Turn a video segment into an animated GIF (palette-optimized). POST /v1/media/loudnorm — Normalize a media file's audio loudness (EBU R128 / ffmpeg loudnorm) — a consistent perceived level for podcasts/voiceover/music. POST /v1/media/metadata — Read OR write container metadata tags (ffprobe / ffmpeg -metadata, STREAM-COPY — no re-encode). POST /v1/media/overlay — Composite an image (logo/watermark) onto a video. POST /v1/media/probe — Inspect a media file's metadata via ffprobe — duration, format, streams, codecs, dimensions, bitrate. POST /v1/media/silence — Detect OR trim silence in audio (ffmpeg silencedetect / silenceremove). POST /v1/media/speed — Speed up or slow down audio/video. POST /v1/media/storyboard — Build a frame-sampled thumbnail sprite sheet from a video (ffmpeg fps-sample + tile). POST /v1/media/subtitle-burn — Render a subtitle file (SRT/WebVTT) permanently INTO the video frames via libass. POST /v1/media/subtitle-extract — Pull an embedded subtitle/caption track out of a container to a text sidecar (SRT or WebVTT). POST /v1/media/thumbnail — Grab a single frame from a video at a timestamp → PNG/JPEG. POST /v1/media/trim — Cut a time range from audio/video — fast STREAM-COPY (no re-encode; codecs preserved, use media_convert to change them). POST /v1/media/waveform — Render an audio file as a waveform OR spectrogram PNG (ffmpeg showwavespic / showspectrumpic). ### cputools — doc POST /v1/doc/analyze-async — Analyze a MULTI-PAGE document asynchronously (AWS Textract StartDocumentAnalysis). POST /v1/doc/ask-document — Ask natural-language questions of a single-page document (AWS Textract AnalyzeDocument QUERIES). POST /v1/doc/convert — Convert a markup/structured document between formats via pandoc — markdown, html, docx, odt, rtf, epub, latex, rst, org, textile, mediawiki, plain (plus pptx + ipynb/asciidoc/gfm/jira/typst as the matrix widens). POST /v1/doc/extract-form — Extract form key→value pairs from a single-page document (AWS Textract AnalyzeDocument FORMS). POST /v1/doc/extract-tables — Extract tables from a single-page document (AWS Textract AnalyzeDocument TABLES). GET /v1/doc/formats — List the supported document-conversion matrix (pandoc) — the exact from→to pairs and the pdf composition path. POST /v1/doc/ocr-layout — OCR a single-page document image/PDF with line+word layout (AWS Textract DetectDocumentText). POST /v1/doc/parse-id — Parse a government identity document (driver's license / passport page) into structured fields (AWS Textract AnalyzeID). POST /v1/doc/parse-invoice — Parse an invoice/receipt into structured fields (AWS Textract AnalyzeExpense). ### cputools — office GET /v1/office/formats — List the office → PDF input rosters — the exotic/legacy rescue set (office_rescue) and the everyday from-office set (pdf_from_office), both always → PDF. POST /v1/office/rescue — Best-effort convert an EXOTIC/LEGACY office format to PDF (LibreOffice) — Apple iWork (pages/numbers/key), Visio (vsd/vsdx), MS Publisher (pub), CorelDRAW (cdr), flat-ODF (fodt), legacy MS binaries (doc/xls/ppt), WordPerfect (wpd) — plus the everyday from-office roster. ### cputools — qr POST /v1/qr — Generate a QR code (PNG/SVG). ### cputools — barcode POST /v1/barcode — Generate a barcode (PNG/SVG; bwip-js). ### cputools — codes POST /v1/codes/color-convert — Convert a color between hex / rgb / hsl. POST /v1/codes/qr-decode — Read a QR code from an uploaded image (sharp → jsqr). ### cputools — csv POST /v1/csv/convert — Convert between csv/tsv/json/ndjson (Papaparse). POST /v1/csv/dedupe — Drop duplicate CSV rows, order-preserving (Papaparse). POST /v1/csv/select — Project/reorder CSV columns (Papaparse). ### cputools — data POST /v1/data/cast — Coerce column types best-effort (a non-coercible cell → null). POST /v1/data/derive — Add computed columns from a STRUCTURED expression (no eval). POST /v1/data/diff — Row-level changeset between two tables. POST /v1/data/dropna — Drop rows with empty/null cells. POST /v1/data/explode — Unnest one cell's list into multiple rows. POST /v1/data/fillna — Fill empty/null cells. POST /v1/data/filter — Filter rows by a STRUCTURED predicate tree (no expression eval). POST /v1/data/from-xlsx — Parse an Excel .xlsx into a table (the first row is the header). POST /v1/data/groupby — Group by columns and apply named aggregates (no expression eval). POST /v1/data/join — Hash-join two tables on key columns. POST /v1/data/pivot — Reshape a table. POST /v1/data/profile — Profile each column: inferred type, count, nullCount, distinctCount, min, max, mean (numeric only), topK. POST /v1/data/rename — Rename columns. POST /v1/data/sample — Sample rows from a dataset. POST /v1/data/schema-infer — Infer per-column types from the sample and emit a schema. POST /v1/data/slice — Slice / sample rows. POST /v1/data/sort — Stable multi-key sort. POST /v1/data/sql — Run full DuckDB SQL, READ-ONLY over your file, in a sandboxed worker (ETL-T). POST /v1/data/sql-large — Run SQL over a LARGE file already on Relaystation storage via AWS Athena (for datasets past the in-process data_sql ceiling). POST /v1/data/to-xlsx — Emit a table as an Excel .xlsx. POST /v1/data/union — Concatenate 2+ tables (ordered key-union schema; missing cells empty). POST /v1/data/validate — Validate rows against a STRUCTURED schema (no expression eval — `pattern` is a bounded RegExp over cell strings, never code). ### cputools — pipeline POST /v1/pipeline — Run a sequence of cputools transforms in ONE call, threading bytes step-to-step in-process (the ETL-T moat — per-call composition). ### cputools — text POST /v1/text/apply-patch — Apply a unified diff (the patch text_diff produces) to a source string. POST /v1/text/case — Recase text. POST /v1/text/count — Count characters / words / lines + reading time. POST /v1/text/diff — Unified text diff of two strings. POST /v1/text/html-to-text — Convert HTML → plain text. POST /v1/text/markdown-to-html — Render Markdown (GFM) → sanitized HTML (marked → whitelist sanitizer; script/unsafe-scheme stripped). POST /v1/text/merge3 — Three-way merge of two changes against a common base (git-style). POST /v1/text/regex-extract — Extract regex matches (ReDoS-guarded: catastrophic-backtracking patterns rejected; input + match count bounded). POST /v1/text/sanitize-html — Sanitize HTML against a whitelist (safe tags/attrs; http/https/mailto only; script/style/event-handlers stripped). POST /v1/text/slugify — Slugify text (lowercase, strip diacritics, non-alphanumeric → separator). POST /v1/text/template — Render a logic-less mustache-subset template (NO eval): {{var}} (HTML-escaped), {{{raw}}}, {{#section}}…{{/section}}, {{^inverted}}…{{/inverted}}. ### cputools — utils POST /v1/utils/base64 — Base64 encode or decode a string (Node Buffer). POST /v1/utils/hash — Hash bytes with sha256/sha512/sha1/md5 (Node crypto). POST /v1/utils/hmac — HMAC bytes with a secret key (Node crypto; sha256/sha512/sha1/md5). POST /v1/utils/jwt-decode — Decode a JWT header + payload WITHOUT verifying the signature (jose). POST /v1/utils/jwt-verify — Verify a JWT signature, alg-pinned (jose). POST /v1/utils/uuid — Generate v4 UUIDs (Node crypto.randomUUID). ### cputools — archive POST /v1/archive/zip — Zip 1+ files into a single archive (fflate, in-memory). ### cputools — generate POST /v1/generate/chart — Render a bar / line / pie chart PNG from data points (hand-rolled SVG → sharp; no chart-lib). POST /v1/generate/favicon — Generate a favicon set (PNGs at several sizes) from EITHER an image OR initials text. POST /v1/generate/identicon — Render a deterministic GitHub-style 5×5 mirror-symmetric identicon PNG from a seed string (sha256 → color + cell grid; same seed → same image). POST /v1/generate/invoice — Render a clean invoice PDF from structured data (pdf-lib, in-process). POST /v1/generate/mock-data — Generate fake rows from a field→type schema (@faker-js/faker). POST /v1/generate/og-image — Render a clean OG / social-card PNG (satori → SVG → sharp). POST /v1/generate/placeholder — Render a placeholder image (solid background + centered dimensions/label text; hand-rolled SVG). POST /v1/generate/qr-logo — Render a QR code with your logo composited in the center (qrcode at ECC level H → sharp.composite, white-padded for scan contrast). ### cputools — location POST /v1/location/geocode — Geocode a free-text address to coordinates (AWS Location Service). POST /v1/location/place-search — Free-text place/POI search (AWS Location Service SearchText). POST /v1/location/reverse-geocode — Reverse-geocode WGS-84 coordinates to the nearest address (AWS Location Service). POST /v1/location/route — Calculate a route between two points (AWS Location Service CalculateRoutes). ### cputools — vision POST /v1/vision/compare-faces — Compare the largest face in a source image against faces in a target image (AWS Rekognition CompareFaces). POST /v1/vision/detect-celebrities — Recognize celebrities in an image (AWS Rekognition RecognizeCelebrities). POST /v1/vision/detect-faces — Detect faces + attributes (age range, emotions, pose, quality) in an image (AWS Rekognition DetectFaces). POST /v1/vision/detect-labels — Detect objects/scenes/concepts in an image (AWS Rekognition DetectLabels). POST /v1/vision/detect-ppe — Detect personal protective equipment (face covers, hand covers, head covers) on persons in an image (AWS Rekognition DetectProtectiveEquipment). POST /v1/vision/moderate — Detect unsafe/inappropriate content in an image (AWS Rekognition DetectModerationLabels). ### cputools — llm POST /v1/llm/embed — Generate text embedding vectors (AWS Bedrock, amazon.titan-embed-text-v2 by default — model is operator-tunable). ### cputools — rag POST /v1/rag/answer — Grounded question-answering over a VECTOR-preset baton (the full RAG loop in one call): embeds your question, retrieves the top-k chunks from the baton's index, and answers with the live llm answer task using ONLY those chunks — returning the answer plus the source chunk ids. ### cputools — web POST /v1/web/pdf — Render a public web page (by URL) to PDF on a headless Chromium worker. POST /v1/web/readability — Extract the clean article text of a public web page (by URL) — title, byline, excerpt, and body text with the chrome/ads/nav stripped (Mozilla Readability, run in-page on the Chromium worker). POST /v1/web/screenshot — Screenshot a public web page (by URL) to PNG/JPEG/WebP on a headless Chromium worker. ### cputools — bundles POST /v1/bundles/ingest-document — One-call document ingest (the cputools showcase): OCR a scanned SINGLE-PAGE document into a searchable PDF, extract its tables (AWS Textract), write them to xlsx (one sheet per table), and store both artifacts in durable drop batons. POST /v1/bundles/rag-ingest — One-call RAG ingest: chunk your text, embed every chunk, and write the vectors into a VECTOR-preset baton — creating the baton for you when you don't pass one (persist the returned batonId: it is your memory address across sessions). POST /v1/bundles/rag-query — One-call RAG query: embeds your question, nearest-neighbor queries the vector baton, and (answer: true) synthesizes a grounded answer from ONLY the retrieved chunks. ## MCP — one endpoint (search-first) Connect at https://api.relaystation.ai/mcp — a single MCP server for everything: storage (create_baton, append_to_baton, …), utilities (pdf/csv/image/data/…), agent↔human/agent messaging (ask_operator / notify_operator / message_agent), and account self-service (balance / transactions / create_topup_link). One balance, one login. The lean surface (api.relaystation.ai/mcp) lists a small hot set + the discovery facade: search_tools (find a tool by keyword), describe_tool (its schema), call_tool (run a safe/billable one). Consequential tools (money / credentials / messaging) are named-only — call them directly so your client confirms. The complete enumerated roster is at https://api.relaystation.ai/mcp/full. tools/list and tools/call per MCP "Streamable HTTP" transport. Auth headers thread through to the wrapped REST routes unchanged. Connect: add the /mcp URL as a connector and approve in your browser (OAuth 2.1 — Google / GitHub / Wallet), or paste it with your rs_live_* key as a `?key=` API-key fallback. ## Auth modes - x402 EIP-3009 USDC payment in X-Payment header (lodestone — no account). - API key in Authorization: Bearer rs_live_... (signup at app.relaystation.ai). - MCP OAuth 2.1 — add /mcp as a connector, approve once in the browser; the agent then spends your prepaid balance headlessly. Protected-resource + authorization-server metadata at /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server. Revoke at app.relaystation.ai → Connected agents. - Wallet JWT (challenge + verify at /v1/auth/challenge + /v1/auth/verify). - rs_session cookie (dashboard only; cookie-only routes scoped to /v1/account/api-keys/* + /v1/billing/checkout). ## Idempotency Every billable POST/PUT/DELETE accepts and requires Idempotency-Key: on the request. Replays within 24h return the cached response; same key + different body → 409 IDEMPOTENCY_CONFLICT. Canonical: https://relaystation.ai/docs/idempotency ## File I/O — passing & receiving files Every file-taking/producing op uses the same model. PASS A FILE IN three ways: Inline — base64 in the body, ≤ 4 MiB, nothing persists. Scratch — FREE customer-scoped working storage, 24h TTL: POST /v1/cputools/upload-url (free) mints a presigned upload + an inputKey; pass { inputKey } to any op for 24h. A baton — pass { batonId, entryRef? } to read a baton as input (the op compute charge applies; baton storage/egress draw down its prepaid quota). Works on BOTH HTTP and the MCP cputools tools; a baton you don't own → 404 on either surface. GET RESULTS BACK: outputs whose BASE64 encoding exceeds 4 MiB (raw ≈ 3 MiB — base64 inflates ~1.37×) land in scratch automatically: the response carries outputKey (chainable) + outputUrl (presigned GET, 1h) and NO inline field — handle both shapes. CHAINING: an op's outputKey re-submits directly as the next op's inputKey — multi-step transforms with no re-upload, each step pay-per-call. DELIVER: deliver:{batonId} or deliver:{new:{…}} lands an output straight into a baton. Baton is the paid durable/shareable/witnessed tier when a result must outlive the day — OPTIONAL, no op requires one. Canonical: https://relaystation.ai/docs/receiving-outputs ## Receipts Every charge is a ledger row (direction, amountMicros, serviceKey, status; failed work reverses). x402 responses carry a PAYMENT-RESPONSE header (settlement is async — the transaction field may be empty at response time). Cost-plus products (llm) return usage: { model, inputTokens, outputTokens, providerCostMicros, markupPct, chargedMicros, ceilingMicros } — you authorize the published ceiling, pay the actual, never more. Canonical: https://relaystation.ai/docs/receipts ## Errors Spec-shaped JSON body: { error: "", code: "" }. Status set: 400, 401, 402, 403, 404, 409, 410, 422, 429, 500, 503. ## Docs https://relaystation.ai/api-reference