# Create Voice

`POST /v1/voices`

Design a voice from a description, or clone one from one of your clips with the speaker's consent. Custom voices are spoken by `spicy-voice-1-custom`.

Send exactly one of `description` (design a voice) or `audio_url` with `consent: true` (clone a voice). Either way you get a voice id, `vc_...`, to pass as `voice` on `POST /v1/audio/speech` with `model: "spicy-voice-1-custom"`.
Design: `description` says what the voice sounds like (gender, age range, pitch, pace, tone, accent). It must describe vocal qualities, not a person: a name or description that names, references or imitates a real person ("sounds like" someone, "the voice of" someone, impressions, celebrities) is a 400 with `code: "real_person"`, and the name, description and preview line are screened like a prompt as well (422 when blocked). A designed voice comes with `preview_url`, a WAV of `preview_text` in the new voice.
Clone: `audio_url` must be one of your own clips from `POST /v1/audio` (browse them with `GET /v1/audio`), at most 10 MB; the clip was transcribed and screened when it was uploaded, and the voice name is screened here. `consent: true` is required: it is your attestation that the voice is your own, or that you hold the speaker's written consent to clone it and to generate speech with it. The attestation is stored with the voice, together with the time, the key and the `user` you send, and returned as `consent_attested_at`. Cloning someone's voice without that consent breaks the acceptable use policy. A noisy sample, or one that does not match its transcript, still makes a voice but returns a `warning`; a clean 10 to 20 second sample gives the closest match.
Price: $0.40 per designed voice and $0.02 per cloned voice, debited once when the voice is created and refunded if creation fails. Speaking with it is billed like any other speech request. `dry_run: true` validates, screens and prices without creating. Sandbox keys get a fixture voice (`vc_sbx_...`) that sandbox speech accepts; nothing is billed.

Base URL: `https://api.spicyapi.com`

## Authorizations

- `Authorization` (string, header, required): Bearer authentication header of the form `Bearer <token>`, where `<token>` is your SpicyAPI key (`sk-spicy-…`). Create one in the dashboard under API Keys.

## Body (application/json)

- `name` (string, required): A label for the voice, at most 60 characters.
- `description` (string, optional): Design: the voice's qualities, at most 2,048 characters. Omit when cloning.
- `preview_text` (string, optional): Design: the line spoken in the preview clip, 1 to 1,024 characters. Defaults to a short neutral line.
- `audio_url` (string, optional): Clone: the `url` of one of your clips from `POST /v1/audio`, at most 10 MB. Omit when designing.
- `consent` (boolean, optional): Clone: must be `true`, your attestation that the voice is your own or that the speaker gave written consent. Anything else is a 400.
- `language` (string, optional): The voice's language: `English` (default), `Chinese`, `German`, `Italian`, `Portuguese`, `Spanish`, `Japanese`, `Korean`, `French` or `Russian`.
- `dry_run` (boolean, optional): When `true`, validates and screens the request and returns `{ object: "dry_run", cost_usd, moderation }` without generating or charging. A blocked prompt still returns the normal 422.
- `user` (string, optional): Your own id for the end user making this request (up to 128 characters, hashed at rest). Send it if your product serves many people: declined-prompt history, strikes and suspensions are then kept per end user, so one person's behaviour never affects another's requests or your account. After 10 severe violations that user gets `403 end_user_suspended`; the id is echoed back as `user` in every screening error so you can act on it.

## Request

```bash
# design a voice
curl --request POST \
  --url https://api.spicyapi.com/v1/voices \
  --header 'Authorization: Bearer $SPICYAPI_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "Mara",
    "description": "Woman in her thirties, low and warm, slightly husky, unhurried, a playful smile in the voice, neutral American accent."
  }'

# clone your own voice from one of your clips
curl --request POST \
  --url https://api.spicyapi.com/v1/voices \
  --header 'Authorization: Bearer $SPICYAPI_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "My voice",
    "audio_url": "https://cdn.spicyapi.com/audio/a1b2c3d4e5f6a7b8/au_3c9f1e7a2b4d6f80a1c2.wav",
    "consent": true
  }'
```

## Response: 200 application/json

Voice

- `id` (string, required): What you pass as `voice`: the preset name, or `vc_...` for your own voices.
- `object` (string, required): Always `voice`.
- `kind` (string, required): `preset`, `designed` or `cloned`.
- `name` (string, required): Display name.
- `models` (string[], required): The speech models that speak this voice; `spicy-voice-1-custom` for your own.
- `description` (string | null, optional): Designed voices: the description they were made from.
- `source_audio_id` (string | null, optional): Cloned voices: the clip (`au_...`) they were cloned from.
- `preview_url` (string | null, optional): Designed voices: a WAV of the preview line in the new voice.
- `consent_attested_at` (integer | null, optional): Cloned voices: Unix timestamp of your consent attestation.
- `created` (integer | null, optional): Unix timestamp. Custom voices only.
- `warning` (string, optional): Clones only, when the sample was noisy or off-transcript and the clone may sound less like the speaker.
- `cost_usd` (number, required): The creation fee, already debited.

```json
{
  "id": "vc_4e1b7c9a2d5f8e0b3c",
  "object": "voice",
  "kind": "designed",
  "name": "Mara",
  "models": ["spicy-voice-1-custom"],
  "description": "Woman in her thirties, low and warm, slightly husky, unhurried, a playful smile in the voice, neutral American accent.",
  "source_audio_id": null,
  "preview_url": "https://cdn.spicyapi.com/audio/a1b2c3d4e5f6a7b8/vc_4e1b7c9a2d5f8e0b3c-preview.wav",
  "consent_attested_at": null,
  "created": 1758553200,
  "cost_usd": 0.4
}
```
