Build an integration
If you maintain a plugin, adapter, node, or extension that calls the Speechify API on someone else’s behalf, set one header and we can tell your traffic apart from everything else hitting the API.
That is the whole contract. Both are optional, they need no registration, and a request without them works exactly as it does today.
Why it matters to you
Without it your integration is invisible to us, and so are its problems.
Server-side integrations reach our API as httpx, aiohttp, node, or with no user agent at all. Those are also what a hand-rolled script and our single largest customer look like, so there is no way to separate them after the fact. In practice that means:
- We cannot tell you when your integration breaks. An error rate or a latency regression that affects only your users is invisible inside the aggregate.
- We cannot warn you before a change reaches your users. When a model is retired or a default changes, we can only email everyone or no one. With the header we can tell you specifically that your plugin’s default is affected, and how many workspaces that is.
- We cannot credit you. Partner conversations, co-marketing, and rate-limit or credit arrangements all start from “how much real usage does this integration drive”. Untagged traffic makes that number zero.
Choosing a slug
Lowercase, and use one slug per thing a developer installs.
That is the unit that has its own version, its own release cadence, and that can independently break or fall behind — and it is the unit a fix targets. If you ship one package, the slug is just its name. If you ship a Python plugin and a JavaScript plugin, those are two installs and they get two slugs, because “which of your two plugins is on the old default” is a question we should be able to answer without asking you.
Shipping more than one package? Give each one its own slug rather than sharing: livekit and livekit-js, not livekit twice. We can roll several slugs up into one partner on our side; we cannot split one slug back apart.
The slug is a name, not a structure. We do not parse it, and you should not encode meaning in its punctuation — how your packages group under your company is something we track on our side, so it never depends on you spelling it a particular way and never breaks if your company is renamed.
The accepted form is up to 40 characters of a-z, 0-9, -, _, and .. We fold case, so LiveKit and livekit are the same integration. A value outside that set is dropped entirely rather than trimmed, because half a slug would show up in our reporting as an integration that does not exist. If your traffic is not appearing, that is the first thing to check.
Keep the slug stable across releases. It names the integration for as long as it exists, so changing it splits your own history in two.
Sending your version
Put your release in Speechify-Caller-Version, never in the slug:
Two headers rather than one value because the slug is what everything groups by — folding the version into it would make every report per-release instead of per-integration, and “how much traffic does this integration drive” would stop having an answer.
It earns its keep on the day it matters. When we retire a model or change a default, the slug tells us which integration is affected; the version tells us whether the fix you already shipped has actually reached your users, and therefore whether we need to warn anyone at all. Up to 32 characters of A-Za-z0-9, ., -, _, +, so ordinary semver including prereleases and build metadata is fine. Case is preserved here, unlike the slug. It is ignored unless a valid slug rides with it.
Set it once, in your client
Set it where you construct the HTTP client, not per call.
If you build on one of the official SDKs, set it as a default header there and keep the SDK’s own identity headers as they are. The two answer different questions: the SDK headers say which Speechify client built the request, and Speechify-Caller says whose product the developer is building on. An integration that uses our SDK sends both, and that is the useful case rather than a conflict.
What Speechify does with it
The value is recorded on the request, and it appears in the workspace’s own request log so the developer using your integration can see which of their tools made a call.
Speechify-Caller is set by the caller, so anyone can send any value. It never grants access, raises a rate limit, changes a price, or unlocks a feature, and it never will. If you are looking for a way to identify your integration to obtain different limits, that is a partner conversation rather than a header — talk to us.
It is not a substitute for the end customer’s API key. Every request still authenticates as the workspace whose key it carries, and the header says nothing about who that workspace is.
Browser clients
The header is on our CORS allow-list, so a browser-based integration can send it on a cross-origin request without a preflight failure. Bear in mind that a browser integration exposes whatever key it holds, so the usual advice applies: call Speechify from your server, not from your users’ browsers.
Tell us you shipped
If you have built or maintain a Speechify integration, we would like to know it exists, link to it from these docs, and warn you before anything changes underneath it. Open an issue on the relevant repository or get in touch.