Skip to main content

ElevenLabs

An ElevenLabs connection reaches https://api.elevenlabs.io, the voice AI API behind ElevenLabs' text to speech, Voice Library and dubbing. Almost everything here is a read: browsing the voices on your account and in the public library, listing models, checking what you have already generated, and seeing how much of your character allowance is left. The one action that spends money — synthesising speech — starts switched off and asks a human every time.

What you need

An ElevenLabs API key. That is a static credential, so this connector works end to end today: you paste the key once and the gateway seals it.

  1. Sign in and open your API keys in the ElevenLabs app.
  2. Create a key and restrict it. ElevenLabs lets you limit which endpoint groups a key may reach, so grant it read access to voices, models, history, dubbing and user information, plus text to speech. Leave voice cloning, workspace administration and Agents disabled — nothing in this connector uses them.
  3. While you are there, set a credit limit on the key. That is a hard budget cap underneath Permaura's approval gate, and it is the one control that still applies if you later hand the key to something else.
  4. Copy the key.

Paste it exactly as ElevenLabs gave it to you. Permaura sends it as the xi-api-key header, so you do not add a prefix of your own.

Add the connection

In the console, open Access → Connections → Add connection and pick ElevenLabs from the catalog. Paste the API key when the form asks for the credential. It is sealed on your gateway at that moment and never displayed again, and from then on Permaura injects it server-side on each approved call.

Adding the connection makes these actions possible, not permitted. An agent cannot touch any of them until a grant allows it.

What the agent can do

Capabilities are namespaced under the connection id, so an agent sees voices.list as <connection>.voices.list.

ActionWhat it doesOn by default
voices.listLists and searches the voices on your accountYes
voices.readRetrieves one voice by voice_idYes
shared_voices.searchSearches the public Voice LibraryYes
models.listLists the models available to youYes
subscription.readReads your tier, characters used and character limitYes
history.listLists past generationsYes
history.readRetrieves one history itemYes
dubbing.listLists dubbing jobsYes
dubbing.readReads one dubbing job's statusYes
speech.createSynthesises speech from text with a chosen voiceNo, and it asks for approval
history.deletePermanently deletes a history itemNo, and it asks for approval

speech.create is the only capability that consumes characters, so it stays off until you switch it on and prompts you every time even then. history.delete is off for a different reason: it is irreversible, and a history item is the only record of a generation you have already paid for.

Good to know

  • The host is pinned. Every call goes to api.elevenlabs.io and nowhere else, whatever an agent asks for. Data residency is an Enterprise feature, and a residency workspace is a separate environment with its own hostname and its own API key: api.eu.residency.elevenlabs.io, api.in.residency.elevenlabs.io or api.sg.residency.elevenlabs.io. If you are on one of those, change the connection's base URL to match before you use it, or every call will hit the wrong region.
  • Audio does not travel well through a gateway, so this connector picks the endpoint that does. ElevenLabs' plain text-to-speech endpoint returns raw audio/mpeg bytes. Permaura parses upstream responses as JSON and hands the agent a JSON result, so a binary body would arrive as 200 with nothing in it — the audio would simply be dropped. speech.create therefore calls ElevenLabs' with timestamps variant, which returns JSON containing audio_base64 plus character-level alignment. The agent gets real audio it can decode and save.
  • Keep the script short. Because the MP3 comes back base64-encoded inside the JSON response, a long passage produces a very large payload for an agent to carry. Generate a paragraph at a time rather than a chapter.
  • Only the listed inputs reach ElevenLabs. speech.create forwards text, model_id, language_code and voice_settings in the body, and output_format and enable_logging in the query string. Anything else an agent sends is dropped before the request leaves your gateway.
  • Your account details are deliberately out of reach. ElevenLabs' /v1/user endpoint returns your API key back in the response body. It is not part of this connector at all — subscription.read gives you the tier, character count and limit without ever putting the key in a response. xi_api_key is on the redaction list as well, as a second line of defence.
  • Voices are on v2, everything else on v1. ElevenLabs versions per endpoint rather than per API, so the base URL is the bare host and each capability carries its own version segment. The older /v1/voices listing still works but is filed under legacy, so this connector uses /v2/voices.
  • Character usage lives on the subscription, not a usage endpoint. ElevenLabs has deprecated its character-stats endpoint, so subscription.read is the supported way to see character_count against character_limit.
  • There is no sandbox. Every synthesis bills real characters against your plan, including the free tier's allowance. There is no test mode to rehearse against.
  • Concurrency is capped by plan. ElevenLabs limits how many requests you may have in flight at once and the cap rises with your tier; a burst beyond it is rejected rather than queued. Check the number on your plan before pointing a batch job at this connection.
  • History is a log of what you generated. Anything speech.create produces shows up in history.list, text and all. If that is sensitive, prune it with history.delete, or pass enable_logging=false on the call. That second option is ElevenLabs' zero-retention mode: the generation is never written to history, so history.list and history.read will not show it and request stitching stops working. It is an Enterprise-only feature, and it is set per request rather than on the account, which is why the parameter is forwarded at all.
  • Speech to text and creating a dub are not exposed. Both of those endpoints take multipart/form-data with a file upload, which this connector's JSON request shape cannot build. You can still watch dubbing jobs you started elsewhere with dubbing.list and dubbing.read.