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.
- Sign in and open your API keys in the ElevenLabs app.
- 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.
- 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.
- 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.
| Action | What it does | On by default |
|---|---|---|
voices.list | Lists and searches the voices on your account | Yes |
voices.read | Retrieves one voice by voice_id | Yes |
shared_voices.search | Searches the public Voice Library | Yes |
models.list | Lists the models available to you | Yes |
subscription.read | Reads your tier, characters used and character limit | Yes |
history.list | Lists past generations | Yes |
history.read | Retrieves one history item | Yes |
dubbing.list | Lists dubbing jobs | Yes |
dubbing.read | Reads one dubbing job's status | Yes |
speech.create | Synthesises speech from text with a chosen voice | No, and it asks for approval |
history.delete | Permanently deletes a history item | No, 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.ioand 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.ioorapi.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/mpegbytes. Permaura parses upstream responses as JSON and hands the agent a JSON result, so a binary body would arrive as200with nothing in it — the audio would simply be dropped.speech.createtherefore calls ElevenLabs' with timestamps variant, which returns JSON containingaudio_base64plus 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.createforwardstext,model_id,language_codeandvoice_settingsin the body, andoutput_formatandenable_loggingin 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/userendpoint returns your API key back in the response body. It is not part of this connector at all —subscription.readgives you the tier, character count and limit without ever putting the key in a response.xi_api_keyis 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/voiceslisting 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.readis the supported way to seecharacter_countagainstcharacter_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.createproduces shows up inhistory.list, text and all. If that is sensitive, prune it withhistory.delete, or passenable_logging=falseon the call. That second option is ElevenLabs' zero-retention mode: the generation is never written to history, sohistory.listandhistory.readwill 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-datawith a file upload, which this connector's JSON request shape cannot build. You can still watch dubbing jobs you started elsewhere withdubbing.listanddubbing.read.