Why we built one API for AI research, media, and editable artifacts 3Stone AI released the 3Stone API, a single server-side API contract that unifies AI research, media generation, and editable artifact creation behind one authentication, job, and billing model. The API uses durable jobs with polling for creation endpoints and requires idempotency keys on every mutating request to prevent duplicate provider cost or output from blind retries. The company said it deliberately does not yet advertise public website/software execution or webhooks, and warned developers never to expose API keys in browser or mobile code. A useful AI product often needs more than a text completion. It may need current research with sources, file understanding, generated media, an editable PowerPoint or spreadsheet, durable job state, storage, and usage accounting. Building each of those paths against a different provider creates a familiar problem: every integration has its own authentication, retry rules, status model, output format, and billing data. The first demo can be quick. The production system is not. That is the problem we built the 3Stone API to address: one server-side API contract for research, creation, and finished artifacts. Simple chat can complete synchronously: js const response = await fetch "https://one.3stoneai.com/v1/chat", { method: "POST", headers: { Authorization: Bearer ${process.env.THREESTONE API KEY} , "Idempotency-Key": crypto.randomUUID , "Content-Type": "application/json", }, body: JSON.stringify { model: "3stone-auto", input: "Explain the tradeoffs between queues and scheduled polling.", } , } ; const result = await response.json ; Creation endpoints use durable jobs. The initial request returns a job ID; clients poll that job and download the artifact only after it reaches a completed state. js const headers = { Authorization: Bearer ${process.env.THREESTONE API KEY} , "Content-Type": "application/json", }; const submitted = await fetch "https://one.3stoneai.com/v1/presentations", { method: "POST", headers: { ...headers, "Idempotency-Key": crypto.randomUUID , }, body: JSON.stringify { prompt: "Create a concise editable project update deck.", } , }, .then response = response.json ; let job; do { await new Promise resolve = setTimeout resolve, 1500 ; job = await fetch https://one.3stoneai.com/v1/jobs/${submitted.job id} , { headers }, .then response = response.json ; } while "queued", "provider starting", "running" .includes job.status ; if job.status == "completed" { throw new Error Job stopped: ${job.error?.code} ; } const artifact = await fetch https://one.3stoneai.com/v1/jobs/${submitted.job id}/artifact , { headers }, ; The same job pattern applies to spreadsheets, images, and video. Long-running provider work can outlive an HTTP connection. A blind retry can create duplicate provider cost or duplicate customer-visible output. Every mutating request therefore accepts a stable idempotency key. If the same key is reused with a different body, the API returns an idempotency conflict. If an accepted provider operation cannot yet be authoritatively reconciled, the request can enter a reconciliation-required state. Clients should preserve the request and job IDs instead of replaying the work. That distinction matters: a network timeout does not prove that external execution failed. A research response is only useful when the application can retain and render its evidence: python import json, os, urllib.request, uuid request = urllib.request.Request "https://one.3stoneai.com/v1/research", data=json.dumps { "query": "Research current battery recycling policy and cite primary sources." } .encode , headers={ "Authorization": f"Bearer {os.environ 'THREESTONE API KEY' }", "Idempotency-Key": str uuid.uuid4 , "Content-Type": "application/json", }, method="POST", with urllib.request.urlopen request, timeout=120 as response: result = json.load response print result "output text" for source in result.get "sources", : print source "url" The current public release includes: We deliberately do not advertise public API website/software execution or webhooks yet. Production truth matters more than a long launch list. Never expose a 3Stone API key in browser or mobile code. Put calls behind your authenticated backend or server function. Persist the returned request and job IDs so reconnecting clients can resume without duplicating work. Useful production error handling includes: 401 invalid api key : reject and rotate/revoke as appropriate. 402 insufficient balance : fund the usage balance before new provider work. 409 idempotency conflict : use a new key only when the request body truly changes. 429 rate limit exceeded : back off with jitter. reconciliation required : preserve identifiers and do not replay blindly. 3Stone API is usage-based and separate from consumer subscriptions. Developer Mode exposes keys, balance, request logs, charges, and job state. I would especially value feedback on: Quickstart, OpenAPI, and examples: https://github.com/jathanks3/3stone-developer-apis?utm source=devto&utm medium=content&utm campaign=api launch https://github.com/jathanks3/3stone-developer-apis?utm source=devto&utm medium=content&utm campaign=api launch Documentation: https://www.3stoneai.com/developers/docs?utm source=devto&utm medium=content&utm campaign=api launch https://www.3stoneai.com/developers/docs?utm source=devto&utm medium=content&utm campaign=api launch Developer Mode: https://one.3stoneai.com/developer?utm source=devto&utm medium=content&utm campaign=api launch https://one.3stoneai.com/developer?utm source=devto&utm medium=content&utm campaign=api launch Disclosure: this article was prepared with AI assistance and reviewed by the 3Stone founder.