Skip to main content
MarketplaceProvider Keys — ElevenLabs

Provider Keys — ElevenLabs

ElevenLabs is a path-style provider: the provider's own path goes straight onto our route, and the seller's xi-api-key is attached on our side.

Billing unit: per 1 000 characters.

ElevenLabs is the one live provider where the seller's account keeps a record of your call. Their generation history shows that a request happened, even on routes where we delete the result after handing it to you. That is a property of the provider, not of our proxy, and it is why the trait badges on a listing matter here more than anywhere else.

Three routes, and that is the whole surface

ElevenLabs publishes over four hundred operations. Three are reachable.

What the allowlist admits
POST /v1/sound-generationa short sound effect — your result, nothing of the accountopen
POST /v1/musicleaves no history; its two account fields are refused where it is pricedopen
GET /v1/modelsthe static model list, free and read-onlyopen
everything elseaccount data, stored data, or cannot be priced before the callrefused
An allowlist, not a denylist: a route is unreachable until someone opens it deliberately. Everything not named here is refused, including routes nobody has thought about yet.

?output_format= is the one query parameter passed through — it is the only one the three routes take.

Calling them

ElevenLabs through Surplus
# Answers with audio BYTES, not JSON. The cost headers still ride on the response.
curl -X POST $SURPLUS_BASE_URL/resources/elevenlabs/v1/sound-generation \
  -H "Authorization: Bearer $SURPLUS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"text":"a short soft chime","duration_seconds":1}' \
  --output chime.mp3 --dump-header headers.txt

grep x-si- headers.txt
# x-si-buyer-cost-micro: 1500
# x-si-list-cost-micro: 3000

POST /v1/music is capped at 50 seconds, inside the fleet's 60-second drain, so a deploy never cuts a generation the seller is already billed for.

Why the other routes are closed

The rule is one sentence: the seller's account may keep a record of your request, but you may read nothing of that account. Each family below fails it for a different reason, and the reasons are worth knowing because they tell you what would have to change.

Can they…Reaches account dataUnpriceable up frontLeaves seller history
Text-to-speech, speech-to-speech, dialogueYesvoice_id may be a private cloned voiceNoYes
Speech-to-textYesuse_speaker_library, webhookNoYes
The voice lists (/v1/voices, /v2/voices)Yesthey ARE the seller’s libraryNoNo
Audio isolationNoYesbilled by uploaded audio lengthYes
Forced alignmentNoYessame basis as isolationYes
Account, keys, billing, usageYesservice accounts can mint keysNoNo
StreamingNoYescannot be metered for settlementNo
Read across a row for why that family is closed. Two different disqualifiers recur: a field that reaches the seller's own account data, and a billing basis no quote taken before the call can bound.

Two of those are worth drawing out:

  • Voice routes are not a capacity question. A voice_id can name one of the seller's private cloned voices, so serving text-to-speech would need an ownership check we do not have yet. Opening it is that check, not a policy edit.
  • Audio isolation and forced alignment are priced by the length of a file you upload. No quote taken before the call can bound that, which is the same property that keeps LLMs off Fal. Opening either is a cost-source change first.

Music is the exception that proves the rule: it leaves no history, and its two fields that would touch the account — finetune_id and store_for_inpainting — are refused at the point where it is priced.

Two layers, not one

A route can be closed two ways here, and the difference is deliberate.

Everything ElevenLabs publishesover 400 operations
Named on the denylistaccount, stored data, voices, streams — can never be opened by widening an allow rule
Refused by absence alonenot opened yet; e.g. the audio-effects catalogue
Opensound generation, music, models
The allowlist is what we have opened. The denylist underneath is the safety net: it names the routes that reach account data, so a later, wider allow rule still cannot open them.

GET /v1/audio-effects/catalog is deliberately not on the denylist. It lists filter presets — a static catalogue of the same class as GET /v1/models, which is open — so naming it would imply it reaches the seller's account, which it does not. It stays refused by the allowlist, which is what "we have not opened this yet" looks like. A denylist that collects everything unopened stops telling you which entries are load-bearing.