Schedule icon
Request icon
Return icon
Switch icon
Log icon
SlackIncomingWebhook icon

ElevenLabs Character Quota Sentinel

Read the ElevenLabs subscription every 6 hours, generate nothing, and alert Slack before text-to-speech runs out of characters or the plan lapses.

Categories
AI

Voice agents, audiobook pipelines, IVR prompts and read-aloud features built on ElevenLabs all draw from one monthly character quota. When it runs out, or a payment fails and the subscription stops being active, every text-to-speech request starts failing at once, often in the middle of a batch job or a live call. ElevenLabs shows usage on its subscription page, but nothing pages the team as the quota runs down. This blueprint turns a scheduled, read-only call to the ElevenLabs API into a quota gate: io.kestra.plugin.core.http.Request reads the subscription, one jq query works out the share used, the characters left and the days until reset, and the result routes to a quiet log or a Slack alert.

How it works

  1. get_subscription (io.kestra.plugin.core.http.Request) calls GET /v1/user/subscription with the xi-api-key header. It is a read: no audio is generated and no plan is changed. Retries cover short network blips, and allowFailed plus allowFailure keep an API error from aborting the flow so it can be reported instead.
  2. summarize_quota (io.kestra.plugin.core.debug.Return) first guards for a missing or non-200 response (UNREACHABLE). Otherwise one jq query computes character_count / character_limit, the characters left, and the days until next_character_count_reset_unix, and reads tier and status. A subscription status other than active, trialing or free is CRITICAL; usage at or above critical_used_pct is CRITICAL; at or above warning_used_pct is WARNING; otherwise HEALTHY.
  3. route_by_quota (io.kestra.plugin.core.flow.Switch) branches on that classification: HEALTHY logs quietly, WARNING posts a Slack note, CRITICAL and UNREACHABLE page Slack. A defaults fallback logs anything unexpected.
  4. log_audit_result (io.kestra.plugin.core.log.Log) writes one audit line per run with the HTTP status and the full summary.
  5. The flow-level errors block pages Slack if the flow itself fails, and the quota_check trigger runs every 6 hours, shipped disabled: true.

What you get

  • A read-only quota check with no custom scripting and no extra plugin to install.
  • A status output (HEALTHY / WARNING / CRITICAL / UNREACHABLE) other flows can gate on, for example to pause a bulk narration job or switch to a fallback voice when the quota is nearly gone.
  • Slack messages with the share used, the characters left, the tier and the days to reset.
  • An audit line on every run, separate from Slack.

Who it's for

  • Teams running voice agents, read-aloud accessibility features, podcasts or audiobook pipelines on ElevenLabs.
  • Developers running batch text-to-speech jobs in Kestra who need to know the quota will last.
  • Product owners who want an early warning before upgrading the plan.

Why orchestrate this with Kestra

The quota lives on a settings page and usage spikes come from your own batch jobs, often ones already running in Kestra. Kestra turns a plain, read-only API call into a scheduled, typed classification with retries, a failure path and an execution history, and the status output lets the very flows that use the quota hold back before it runs out.

Prerequisites

  • An ElevenLabs account (the free tier works for testing) and an API key from the profile settings.
  • A Slack incoming webhook for the WARNING, CRITICAL, UNREACHABLE and flow-failure alerts.

Secrets

  • ELEVENLABS_API_KEY: an ElevenLabs API key with permission to read the user subscription.
  • SLACK_WEBHOOK: Slack incoming webhook used for every alert branch and the flow-failure alert.

In Kestra OSS, secrets are supplied as environment variables prefixed SECRET_ and base64-encoded, for example SECRET_ELEVENLABS_API_KEY=$(echo -n 'sk_xxxxxxxx' | base64), and read back with {{ secret('ELEVENLABS_API_KEY') }}. Use the Enterprise secrets backend for encryption at rest and access control.

Quick start

  1. Create an ElevenLabs API key and add ELEVENLABS_API_KEY and SLACK_WEBHOOK as secrets.
  2. Run the flow manually and compare the share used and characters left in the logs with the subscription page.
  3. Lower warning_used_pct below your current usage to see the WARNING path, then set it back.
  4. Enable quota_check.

How to extend

  • Store each run's character_count in a KV store to compute the daily burn rate and alert when the quota will run out before the reset date.
  • Gate a bulk narration flow on status == HEALTHY with a Flow trigger.
  • Add a call to the usage endpoint to break usage down by voice or by API key.
  • Alert only when the status changes, using a KV store.

Inputs

  • warning_used_pct: type FLOAT, default 80.0.
  • critical_used_pct: type FLOAT, default 95.0.

Outputs

  • status: one of HEALTHY, WARNING, CRITICAL, UNREACHABLE.
  • Example path: {{ fromJson(outputs.summarize_quota.value).chars_left }} for the characters left this period.

Links

Pitfalls

  • Plans with usage-based billing can go past the character limit and charge for the extra; treat CRITICAL as "expensive from now on" rather than "stopped" in that case.
  • Days to reset are computed from next_character_count_reset_unix against the Kestra server clock in UTC.
  • The set of subscription status values that count as healthy (active, trialing, free) is a judgement call; add others if your plan reports a different value while working normally.
  • This flow only reads; it never generates audio or changes the plan.
See How

New to Kestra?

Use blueprints to kickstart your first workflows.