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:
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.
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:
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
Documentation: 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
Disclosure: this article was prepared with AI assistance and reviewed by the 3Stone founder.