Audio Generation
Generate speech, sound effects, ambience, and music.
List voices
GET /api/v1/audio/voices
Scope: audio:read
Returns the voices you can pass as voice_id when generating speech. No X-Workspace-Id header. The list can change. A voice id that is not in this list still works if it already exists on the connected account.
Example
curl https://powerpost.ai/api/v1/audio/voices \
-H "x-api-key: pp_live_sk_YOUR_KEY"Response
{
"voices": [
{
"id": "VOICE_ID",
"name": "Sarah",
"gender": "female",
"accent": "american",
"language": "en",
"preview_url": "https://example.com/sarah.mp3"
}
]
}| Field | Type | Description |
|---|---|---|
id | string | Pass this as provider_options.voice_id |
name | string | Display name |
gender | string | null | Voice gender, when the catalog has one |
accent | string | null | Accent, when the catalog has one |
language | string | null | Language label, when the catalog has one |
preview_url | string | null | Short sample of the voice. It can expire. |
Errors
| Code | Description |
|---|---|
| 401 | Invalid API key |
| 403 | API key is missing the audio:read scope |
| 429 | Rate limit exceeded |
| 500 | Voice list could not be loaded |
Generate audio
POST /api/v1/audio/generate
Scope: audio:generate
Generate speech, sound effects, ambient backgrounds, or music as an MP3. The request returns immediately with an id. Poll Get generation until the job is completed or failed.
Audio generation requires at least one credit purchase on the account. Signup credits are not enough. See Purchase required.
Request body
Generic fields stay at the top level. Mode-specific settings go in provider_options. Do not send a provider. PowerPost uses the current one. Older requests that still include provider keep working.
| Field | Type | Required | Description |
|---|---|---|---|
mode | string | No | speech (default), sound_effect, or music. Existing requests without a mode still generate speech. |
text | string | Yes | Speech script, or a description of the effect or music. There is a character limit, and music allows less text than speech. |
duration_seconds | number | Effects/music only | How long the clip should be. Required for effects and music. The API rejects a length it does not allow. |
output_format | string | No | mp3. That is also the default. |
provider_options | object | Yes | Provider-specific settings (see below) |
Speech settings
| Field | Type | Required | Description |
|---|---|---|---|
voice_id | string | Yes | Voice id from List voices. |
model | string | No | Speech model. Leave it out to use the current default. |
stability | number | No | From 0 to 1 (default: 0.5) |
language_code | string | No | Two-letter ISO 639-1 code (en, he, …) |
seed | integer | No | Best-effort deterministic seed. Identical output is not guaranteed. |
text_normalization | string | No | auto, on, or off (default: auto) |
Use an id from List voices. A voice id that is not listed still works if it already exists on the connected account.
Credits
Audio generation uses credits. You are charged when the job starts. If the job fails, the credits are refunded. The start response includes credits_used and remaining_credits.
Sound effects and ambience
Use mode: "sound_effect" for effects, environmental sounds, or background ambience. No voice is needed.
{
"mode": "sound_effect",
"text": "Gentle rain falling on leaves with distant thunder",
"duration_seconds": 10,
"provider_options": {
"loop": true,
"prompt_influence": 0.3
}
}model, loop, and prompt_influence are optional. An empty provider_options object uses the current defaults. prompt_influence runs from 0 to 1. Looping makes the file suitable for seamless repetition. It does not extend the duration or repeat the sound in a video.
Music
Use mode: "music" for background music or songs. Instrumental music is the default.
{
"mode": "music",
"text": "Warm, gentle piano with soft strings for a calm product introduction",
"duration_seconds": 30,
"provider_options": {
"force_instrumental": true
}
}model and force_instrumental are optional. force_instrumental defaults to instrumental music. Set it to false to allow vocals. An empty provider_options object uses the current defaults. If music is not enabled, or the settings do not belong to this mode, the request is rejected before you are charged.
All modes share the same status endpoint, media library, and refund flow. Use the resulting audio.media_id with Video audio to place music or effects in a video. Music can take several minutes.
PowerPost sends music text as the prompt and duration_seconds as the length. The file comes back as an MP3.
Speech text
You can put delivery direction in text:
- Audio tags such as
[whispers],[excited], or[sighs] - Ellipses, punctuation, capitalization, and line breaks for pauses and emphasis
- Do not use SSML
<break>tags. They are not supported. - Pick a voice that fits the delivery. Tags behave differently on different voices.
One voice per request. For more than one speaker, generate a separate job per voice.
Example
curl -X POST https://powerpost.ai/api/v1/audio/generate \
-H "x-api-key: pp_live_sk_YOUR_KEY" \
-H "X-Workspace-Id: YOUR_WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{
"text": "[warmly] Welcome to PowerPost.",
"output_format": "mp3",
"provider_options": {
"voice_id": "YOUR_VOICE_ID",
"stability": 0.5,
"language_code": "en"
}
}'Response
{
"audio_generation_id": "22222222-2222-4222-8222-222222222222",
"status": "processing",
"status_url": "/api/v1/audio/generations/22222222-2222-4222-8222-222222222222",
"created_at": "2026-09-04T18:30:00Z",
"credits_used": 1,
"remaining_credits": 46
}| Field | Type | Description |
|---|---|---|
audio_generation_id | string | Id to poll for this job |
status | string | Always processing on a successful start |
status_url | string | Relative URL to poll for results |
created_at | string | ISO 8601 timestamp |
credits_used | number | Credits deducted |
remaining_credits | number | Balance after deduction |
Errors
| Code | Description |
|---|---|
| 400 | Invalid request body |
| 401 | Invalid API key |
| 402 | Insufficient credits (INSUFFICIENT_CREDITS) |
| 402 | Purchase required (MEDIA_REQUIRES_PURCHASE) |
| 403 | API key is missing the audio:generate scope |
| 429 | Rate limit exceeded |
Get generation
GET /api/v1/audio/generations/{id}
Scope: audio:read
Poll until status is completed or failed.
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string | The audio generation id |
Example
curl https://powerpost.ai/api/v1/audio/generations/22222222-2222-4222-8222-222222222222 \
-H "x-api-key: pp_live_sk_YOUR_KEY" \
-H "X-Workspace-Id: YOUR_WORKSPACE_ID"Response (processing)
{
"audio_generation_id": "22222222-2222-4222-8222-222222222222",
"status": "processing",
"model": "eleven_v3",
"error": null,
"created_at": "2026-09-04T18:30:00Z",
"updated_at": "2026-09-04T18:30:01Z",
"audio": null
}Response (completed)
{
"audio_generation_id": "22222222-2222-4222-8222-222222222222",
"status": "completed",
"model": "eleven_v3",
"error": null,
"created_at": "2026-09-04T18:30:00Z",
"updated_at": "2026-09-04T18:30:08Z",
"audio": {
"audio_id": "33333333-3333-4333-8333-333333333333",
"media_id": "33333333-3333-4333-8333-333333333333",
"url": "https://temporary-signed-url.example/audio.mp3",
"file_name": "33333333-3333-4333-8333-333333333333.mp3",
"file_size": 123456,
"mime_type": "audio/mpeg",
"duration": 4.2
}
}Response (failed)
{
"audio_generation_id": "22222222-2222-4222-8222-222222222222",
"status": "failed",
"model": "eleven_v3",
"error": {
"code": "AUDIO_GENERATION_FAILED",
"message": "Audio generation failed"
},
"created_at": "2026-09-04T18:30:00Z",
"updated_at": "2026-09-04T18:30:08Z",
"audio": null
}Response fields
| Field | Type | Description |
|---|---|---|
audio_generation_id | string | Audio generation id |
status | string | processing, completed, or failed |
model | string | Model used for this job |
error | object | null | Present when status is failed |
created_at | string | ISO 8601 timestamp |
updated_at | string | ISO 8601 timestamp |
audio | object | null | Output file when status is completed |
Audio object
| Field | Type | Description |
|---|---|---|
audio_id | string | Generated audio asset id. Same value as media_id. |
media_id | string | Workspace media library id. |
url | string | null | Signed MP3 link. It expires. |
file_name | string | Stored file name |
file_size | number | Size in bytes |
mime_type | string | audio/mpeg |
duration | number | null | Length in seconds, when known |
Status values
| Status | Description |
|---|---|
processing | Audio is being generated |
completed | MP3 is ready |
failed | Generation failed; credits are refunded |
audio.url is a signed link and it expires. Keep audio_generation_id and call this endpoint
again for a fresh URL. Completed audio is also stored in the workspace media library as
media_type: audio. You cannot pass media_id on posts yet; no publish destination accepts a
raw MP3. Use Video audio to mix it into a publishable MP4. If the media item is deleted, the generation remains in history and audio becomes
null, matching image and video generations.
Errors
| Code | Description |
|---|---|
| 401 | Invalid API key |
| 403 | API key is missing the audio:read scope |
| 404 | Audio generation not found |
| 429 | Rate limit exceeded |