Browse the API docs
Endpoint reference

Generation

The Crayo Generation API creates images, icons, face swaps, narration and voice changes, and stores each result as an asset. Image endpoints cost 1 image credit and audio endpoints cost 1 voiceover credit per second.

Generate image

POST/v1/image-generator

Generates an image from a text prompt and stores it as an asset you can drop straight into a project scene. Some models accept a reference image to carry over a look, a subject, or a layout.

  • Only the models marked as supporting a reference image read reference_image_url.
Credits:
1 image credit
Rate limit:
Default tier, 2/s and 50/min

Parameters

NameInTypeRequiredDescription
promptbodystringYesWhat to generate. Max 2,000 characters.
modelbodystringNoWhich model renders the image.default black-forest-labs/flux-schnellblack-forest-labs/flux-schnellbytedance/seedream-4.5bytedance/seedream-5-liteideogram-ai/ideogram-v3-turbobria/image-3.2google/nano-bananagoogle/nano-banana-pro
aspect_ratiobodystringNoOutput shape.default 1:11:116:99:164:33:4
reference_image_urlbodystringNoPublic https URL of an image to steer the result. Must be https on port 443. Plain http and non-standard ports are rejected.

Request

curl
curl -X POST "https://api.crayo.ai/v1/image-generator" \
  -H "Authorization: Bearer $CRAYO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "prompt": "a golden retriever surfing a wave at sunset, cinematic",
  "model": "black-forest-labs/flux-schnell",
  "aspect_ratio": "9:16"
}'

Response

200 application/json
{
  "image": "https://cdn-crayo.com/user-uploads/cm7x0v8qa0000abcd/9f1.../image.png",
  "asset": {
    "id": "cm7x1j0aa0000abcd",
    "name": "image",
    "key": "user-uploads/cm7x0v8qa0000abcd/9f1.../image.png",
    "url": "https://cdn-crayo.com/user-uploads/cm7x0v8qa0000abcd/9f1.../image.png",
    "type": "image",
    "category": "generation",
    "size": 482913,
    "createdAt": "2026-08-21T14:02:11.000Z"
  }
}

Errors

  • 400VALIDATION_ERRORprompt is missing, or aspect_ratio is not a supported value.
  • 401MISSING_API_KEYNo Authorization header was sent, or it does not carry a crayo_sk_ key.
  • 401UNAUTHORIZEDThe key sent is malformed, expired, or revoked.
  • 402INSUFFICIENT_CREDITSYou have no image credits left.
  • 429RATE_LIMITEDOver the rate limit. Wait Retry-After seconds.
  • 500SERVER_ERRORSomething failed on our side. Retry with backoff.

Generate icon

POST/v1/icon-generator

Generates a single app-style icon on a transparent background from a short concept, for thumbnails, overlays, and channel art. Pass a badge color and an accent color to match a brand palette.

Credits:
1 image credit
Rate limit:
Default tier, 2/s and 50/min

Parameters

NameInTypeRequiredDescription
conceptbodystringYesThe idea the icon should depict. Max 200 characters.
colorbodystringNoBadge background color as a hex value or a color name. Near-white values are rejected because the glyph would disappear.
accent_colorbodystringNoGlyph color drawn on top of the badge. Must contrast with color.
reference_image_urlbodystringNoPublic https URL of an image to steer the result. Must be https on port 443. Plain http and non-standard ports are rejected.

Request

curl
curl -X POST "https://api.crayo.ai/v1/icon-generator" \
  -H "Authorization: Bearer $CRAYO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "concept": "rocket launch",
  "color": "#1B2A4A"
}'

Response

200 application/json
{
  "success": true,
  "image": "https://cdn-crayo.com/user-uploads/cm7x0v8qa0000abcd/2b8.../icon.png",
  "asset": {
    "id": "cm7x1j0aa0000abcd",
    "name": "rocket launch",
    "key": "user-uploads/cm7x0v8qa0000abcd/9f1.../image.png",
    "url": "https://cdn-crayo.com/user-uploads/cm7x0v8qa0000abcd/9f1.../image.png",
    "type": "image",
    "category": "icon",
    "size": 482913,
    "createdAt": "2026-08-21T14:02:11.000Z"
  }
}

Errors

  • 400VALIDATION_ERRORconcept is empty, or a color value is rejected.
  • 401MISSING_API_KEYNo Authorization header was sent, or it does not carry a crayo_sk_ key.
  • 401UNAUTHORIZEDThe key sent is malformed, expired, or revoked.
  • 402INSUFFICIENT_CREDITSYou have no image credits left.
  • 429RATE_LIMITEDOver the rate limit. Wait Retry-After seconds.
  • 500GENERATION_FAILEDThe icon could not be produced. The credit stays spent.
  • 500SERVER_ERRORSomething failed on our side. Retry with backoff.

Generate icon set

POST/v1/icon-generator/bulk

Generates a matching set of icons in one call. Every icon shares one palette so the set looks like a family. Concepts that fail are listed in the response and the set still returns whatever succeeded.

Credits:
1 image credit per concept
Rate limit:
Default tier, 2/s and 50/min

Parameters

NameInTypeRequiredDescription
conceptsbodystring[]NoThe icons to generate. Accepts an array or a comma-separated string. Duplicates are dropped. Omit it to get the default starter set. Max 12 concepts per request, each up to 200 characters.
colorbodystringNoShared badge background color for the whole set.
accent_colorbodystringNoShared glyph color for the whole set.
reference_image_urlbodystringNoPublic https URL of an image to steer the result. Must be https on port 443. Plain http and non-standard ports are rejected.

Request

curl
curl -X POST "https://api.crayo.ai/v1/icon-generator/bulk" \
  -H "Authorization: Bearer $CRAYO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "concepts": [
    "rocket launch",
    "camera",
    "trophy"
  ],
  "color": "#1B2A4A"
}'

Response

200 application/json
{
  "success": true,
  "requested": 3,
  "generated": 3,
  "failed": [],
  "assets": [
    {
      "id": "cm7x1j0aa0000abcd",
      "name": "rocket launch",
      "key": "user-uploads/cm7x0v8qa0000abcd/9f1.../image.png",
      "url": "https://cdn-crayo.com/user-uploads/cm7x0v8qa0000abcd/9f1.../image.png",
      "type": "image",
      "category": "generation",
      "size": 482913,
      "createdAt": "2026-08-21T14:02:11.000Z",
      "concept": "rocket launch"
    }
  ]
}

Errors

  • 400VALIDATION_ERRORconcepts is not a list, or there are more than 12 of them.
  • 401MISSING_API_KEYNo Authorization header was sent, or it does not carry a crayo_sk_ key.
  • 401UNAUTHORIZEDThe key sent is malformed, expired, or revoked.
  • 402INSUFFICIENT_CREDITSYour image balance is below the number of concepts.
  • 429RATE_LIMITEDOver the rate limit. Wait Retry-After seconds.
  • 500GENERATION_FAILEDEvery concept failed. Credits stay spent.
  • 500SERVER_ERRORSomething failed on our side. Retry with backoff.

Face swap

POST/v1/face-swap

Places the face from one image onto a target image and stores the result as an asset. Both images are read from public https URLs, so host them yourself or import them as assets first and use the asset url.

Credits:
1 image credit
Rate limit:
Default tier, 2/s and 50/min

Parameters

NameInTypeRequiredDescription
face_image_urlbodystringYesPublic https URL of the image holding the face to use. Must be https on port 443.
target_image_urlbodystringYesPublic https URL of the image to place the face into. Must be https on port 443.
promptbodystringNoOptional direction for the blend, for example lighting or expression.
clean_upbodybooleanNoRun an extra pass to smooth blend artifacts.default false

Request

curl
curl -X POST "https://api.crayo.ai/v1/face-swap" \
  -H "Authorization: Bearer $CRAYO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "face_image_url": "https://example.com/faces/host.jpg",
  "target_image_url": "https://example.com/scenes/podcast.jpg"
}'

Response

200 application/json
{
  "image": "https://cdn-crayo.com/user-uploads/cm7x0v8qa0000abcd/7d3.../image.png",
  "asset": {
    "id": "cm7x1j0aa0000abcd",
    "name": "Face Swap",
    "key": "user-uploads/cm7x0v8qa0000abcd/9f1.../image.png",
    "url": "https://cdn-crayo.com/user-uploads/cm7x0v8qa0000abcd/9f1.../image.png",
    "type": "image",
    "category": "face-swap",
    "size": 482913,
    "createdAt": "2026-08-21T14:02:11.000Z"
  }
}

Errors

  • 400VALIDATION_ERRORAn image URL is missing or is not a public https URL.
  • 401MISSING_API_KEYNo Authorization header was sent, or it does not carry a crayo_sk_ key.
  • 401UNAUTHORIZEDThe key sent is malformed, expired, or revoked.
  • 402INSUFFICIENT_CREDITSYou have no image credits left.
  • 429RATE_LIMITEDOver the rate limit. Wait Retry-After seconds.
  • 500SERVER_ERRORSomething failed on our side. Retry with backoff.

Generate voiceover

POST/v1/voiceover-generator

Turns a script into narration audio and stores it as an asset. The returned asset id is what you pass as narration.asset_id on a project, and duration_seconds tells you how long to make the visuals.

  • Cost is estimated from the script length at roughly 750 characters per minute, and charged before the audio is produced.
Credits:
1 voiceover credit per second of narration
Rate limit:
Default tier, 2/s and 50/min

Parameters

NameInTypeRequiredDescription
scriptbodystringYesThe words to speak. Max 5000 characters.
voice_idbodystringYesA voice_id from GET /v1/voices.
titlebodystringNoName for the resulting asset. Trimmed to 25 characters.
settingsbodyobjectNoDelivery controls for the voice.
settings.stabilitybodyintegerNoHigher values read more evenly, lower values vary more. 0 to 100.default 50
settings.similaritybodyintegerNoHow closely the read tracks the original voice. 0 to 100.default 75
settings.exaggerationbodyintegerNoHow much expression to put into the read. 0 to 100.default 50
settings.speedbodynumberNoPlayback speed multiplier. 0.7 to 1.2.default 1

Request

curl
curl -X POST "https://api.crayo.ai/v1/voiceover-generator" \
  -H "Authorization: Bearer $CRAYO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "script": "Three habits that quietly ruin your mornings. Number one starts before you even wake up.",
  "voice_id": "v_9f2c41ab77d0e315",
  "title": "Hook narration",
  "settings": {
    "stability": 50,
    "similarity": 75,
    "exaggeration": 50,
    "speed": 1
  }
}'

Response

200 application/json
{
  "success": true,
  "asset": {
    "id": "cm7x1j5bb0002abcd",
    "name": "Hook narration",
    "key": "user-uploads/cm7x0v8qa0000abcd/4c2.../hook-narration.mp3",
    "url": "https://cdn-crayo.com/user-uploads/cm7x0v8qa0000abcd/4c2.../hook-narration.mp3",
    "type": "audio",
    "category": "voiceover",
    "length": 18.4,
    "size": 294912,
    "createdAt": "2026-08-21T14:03:02.000Z"
  },
  "duration_seconds": 18.4
}

Errors

  • 400INVALID_VOICEvoice_id is not in the voice catalog.
  • 400VALIDATION_ERRORThe script is too long, or a setting is out of range.
  • 401MISSING_API_KEYNo Authorization header was sent, or it does not carry a crayo_sk_ key.
  • 401UNAUTHORIZEDThe key sent is malformed, expired, or revoked.
  • 402INSUFFICIENT_CREDITSYour voiceover balance is below the script length.
  • 429RATE_LIMITEDOver the rate limit. Wait Retry-After seconds.
  • 500SERVER_ERRORSomething failed on our side. Retry with backoff.

Change voice

POST/v1/voice-changer

Re-performs the speech in an audio or video asset you own with a different voice, keeping the original timing and delivery. The source has to be one of your own assets so the duration, and therefore the cost, is known before the job runs.

  • Credits are charged up front from the asset duration, before the conversion starts.
Credits:
1 voiceover credit per second of the source asset
Rate limit:
Default tier, 2/s and 50/min

Parameters

NameInTypeRequiredDescription
asset_idbodystringYesAn audio or video asset you own, with a known duration. Duration drives the credit charge, so assets with unknown length are rejected.
voice_idbodystringYesA voice_id from GET /v1/voices.
remove_background_noisebodybooleanNoStrip background noise from the source before converting.default false

Request

curl
curl -X POST "https://api.crayo.ai/v1/voice-changer" \
  -H "Authorization: Bearer $CRAYO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "asset_id": "cm7x1k2p40001abcd",
  "voice_id": "v_9f2c41ab77d0e315",
  "remove_background_noise": true
}'

Response

200 application/json
{
  "success": true,
  "asset": {
    "id": "cm7x1j5bb0002abcd",
    "name": "voice-changed",
    "key": "user-uploads/cm7x0v8qa0000abcd/4c2.../hook-narration.mp3",
    "url": "https://cdn-crayo.com/user-uploads/cm7x0v8qa0000abcd/4c2.../hook-narration.mp3",
    "type": "audio",
    "category": "voice-changer",
    "length": 18.4,
    "size": 294912,
    "createdAt": "2026-08-21T14:03:02.000Z"
  }
}

Errors

  • 400INVALID_VOICEvoice_id is not in the voice catalog.
  • 400INVALID_ASSET_TYPEThe asset is an image rather than audio or video.
  • 400INVALID_ASSETThe asset has no known duration. Upload it again.
  • 401MISSING_API_KEYNo Authorization header was sent, or it does not carry a crayo_sk_ key.
  • 401UNAUTHORIZEDThe key sent is malformed, expired, or revoked.
  • 402INSUFFICIENT_CREDITSYour voiceover balance is below the media duration.
  • 404NOT_FOUNDNo asset with that id belongs to your account.
  • 429RATE_LIMITEDOver the rate limit. Wait Retry-After seconds.
  • 500SERVER_ERRORSomething failed on our side. Retry with backoff.
New to the Crayo API? See what it is forUse cases, pricing and the console walkthrough live on the API feature page.

FAQs

Frequent questions

Image, icon and face swap calls cost 1 image credit each, and the bulk icon endpoint costs 1 image credit per concept. Narration costs 1 voiceover credit per second of audio and the voice changer costs 1 voiceover credit per second of the source asset.

Only ids returned by GET /v1/voices. The voiceover generator and the voice changer reject any other voice_id, so resolve a voice from the catalog first.

POST /v1/image-generator accepts black-forest-labs/flux-schnell, bytedance/seedream-4.5, bytedance/seedream-5-lite, ideogram-ai/ideogram-v3-turbo, bria/image-3.2, google/nano-banana and google/nano-banana-pro, with aspect ratios 1:1, 16:9, 9:16, 4:3 and 3:4.

Before the audio is produced. The cost is estimated from the script length at roughly 750 characters per minute. The voice changer charges up front from the asset duration, which is why its source must be an asset you own.

Still have questions?

Contact our 24/7 support team for any concerns or inquiries.

Get in touch