An API you've already written against.
Acorn implements the OpenAI HTTP surface for every route we ship — request shape, response shape, error codes. Point your existing client at api.acorncompute.com and it works. The whole reference fits on one page.
Three steps to your first transcript.
If you've never written a line of Acorn code, you'll be done by step three. If you're migrating from OpenAI, skip to step two.
Get your API key.
Sign up at app.acorncompute.com, head to Keys, and create a key scoped to the routes you'll use. New accounts land with $25 in credit and a 100-hour-a-month free tier on transcription.
# Acorn keys start with `acn_live_` or `acn_test_` export ACORN_API_KEY="acn_live_8c1f...c93a"
Install. Or keep your OpenAI client.
Acorn ships native SDKs for Python, Node, Go, and Ruby. If you have an OpenAI client wired up, you don't have to touch your import lines — change the base URL and the key, and the existing methods route to us unchanged.
pip install acorn from acorn import Acorn client = Acorn(api_key=os.environ["ACORN_API_KEY"])
npm install acorn import { Acorn } from "acorn"; const client = new Acorn({ apiKey: process.env.ACORN_API_KEY });
go get github.com/acorn-compute/acorn-go import "github.com/acorn-compute/acorn-go" client := acorn.NewClient(os.Getenv("ACORN_API_KEY"))
# All routes accept Bearer auth. curl https://api.acorncompute.com/v1/audio/transcriptions \ -H "Authorization: Bearer $ACORN_API_KEY" \ -F file="@interview.mp3" \ -F model="whisper-large-v3"
Submit your first job.
Most routes work async-with-immediate-return: a single POST gives you the result back inline when the job finishes quickly, or a job_id you poll for longer work. The shape is the same.
from acorn import Acorn client = Acorn() # reads ACORN_API_KEY from env result = client.audio.transcriptions.create( model="whisper-large-v3", file=open("interview.mp3", "rb"), response_format="verbose_json", diarization=True, ) print(result.text) print("cost:", result.cost_usd, "USD")
import { Acorn } from "acorn"; import { createReadStream } from "node:fs"; const client = new Acorn(); const result = await client.audio.transcriptions.create({ model: "whisper-large-v3", file: createReadStream("interview.mp3"), response_format: "verbose_json", diarization: true, }); console.log(result.text);
import "github.com/acorn-compute/acorn-go" client := acorn.NewClient(os.Getenv("ACORN_API_KEY")) result, err := client.Audio.Transcriptions.Create(ctx, acorn.TranscriptionRequest{ Model: "whisper-large-v3", File: file, ResponseFormat: "verbose_json", Diarization: true, })
curl https://api.acorncompute.com/v1/audio/transcriptions \ -H "Authorization: Bearer $ACORN_API_KEY" \ -F file="@interview.mp3" \ -F model="whisper-large-v3" \ -F response_format="verbose_json" \ -F diarization="true"
Handle the webhook.
For longer batches and larger audio files we POST the result to a URL you register. Every payload is signed with HMAC-SHA256 — verify the header in one line with the SDK, then queue the work.
from acorn import verify_webhook @app.post("/hooks/acorn") def on_acorn_event(): event = verify_webhook( body=request.get_data(), signature=request.headers["X-Acorn-Signature"], timestamp=request.headers["X-Acorn-Timestamp"], secret=os.environ["ACORN_WEBHOOK_SECRET"], ) if event.type == "job.finished": enqueue(event.data.job_id, event.data.result_url) return "", 204
import { verifyWebhook } from "acorn"; app.post("/hooks/acorn", express.raw({ type: "*/*" }), (req, res) => { const event = verifyWebhook({ body: req.body, signature: req.headers["x-acorn-signature"], timestamp: req.headers["x-acorn-timestamp"], secret: process.env.ACORN_WEBHOOK_SECRET, }); if (event.type === "job.finished") enqueue(event.data.job_id); res.status(204).end(); });
curl https://api.acorncompute.com/v1/webhooks \ -H "Authorization: Bearer $ACORN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://yourapp.com/hooks/acorn", "events":["job.finished","job.failed"] }'
Four native clients. Five OpenAI ones.
Native SDKs unlock the Acorn-specific bits — webhook verification, job-id helpers, region pinning. The official OpenAI SDKs work too; you just don't get the extras.
Every endpoint, every status.
The full surface area Acorn exposes today. Beta routes will keep the same request and response shape at GA — only the pricing locks.
Two lines of diff, then you're routing to Acorn.
Your existing OpenAI client works as-is. Change the base URL and the key, and every openai.audio.transcriptions.create() call routes to us instead.
from openai import OpenAI client = OpenAI( api_key=os.environ["OPENAI_API_KEY"], )
from openai import OpenAI client = OpenAI( api_key=os.environ["ACORN_API_KEY"], base_url="https://api.acorncompute.com/v1", )
Notify, don't poll.
For longer jobs — batches, BYO models, large audio — register a webhook and we POST the result the moment a worker hands it back.
HMAC-signed, retried, replayable.
- Signed. Every payload carries
X-Acorn-SignatureandX-Acorn-Timestampheaders — HMAC-SHA256 overtimestamp.body. Reject timestamps outside a five-minute window before comparing the signature. - At-least-once. We retry with exponential backoff for up to 24 hours, then drop to the dead-letter queue. Use the
job_idas your idempotency key. - Filtered. Subscribe per route, per region, per environment. Test webhooks land at a separate URL of your choice.
- Replayable. The last 30 days of events are queryable from the dashboard if your endpoint was down.
{
"event": "job.finished",
"event_id": "evt_8c1f",
"created": 1747824312,
"data": {
"job_id": "job_3uA9k2",
"route": "/v1/audio/transcriptions",
"model": "whisper-large-v3",
"status": "succeeded",
"duration_sec": 2.1,
"cost_usd": 0.0569,
"result_url": "https://res.acorncompute.com/job_3uA9k2",
"worker": "node_quiet-cedar-4419"
}
}
Errors look like errors.
OpenAI-shape error objects, so your existing handlers keep working. The error.acorn block carries retry hints and a worker fingerprint for the support ticket you'll never have to open.
{
"error": {
"code": "worker_unavailable",
"message": "All nearby nodes were busy. Job was rescheduled.",
"param": null,
"type": "server_error",
"acorn": {
"retried": 3,
"workers_tried": ["node_quiet-cedar-4419", "node_brave-otter-1102"],
"retry_after_sec": 2,
"job_id": "job_3uA9k2",
"billed": false
}
}
}
The docs are above. Or just sign up.
The free tier covers a real integration before you commit. No card, no demo call — your key works the moment you finish sign-up.