/api/v1/images/generate-headshotsGenerate Headshots
Submit a set of portrait photos to generate 60 professional AI headshots. The job runs asynchronously and delivers results to your callback URL when complete.
This is an async endpoint. You will receive an immediate response with a headshots_id, and your callback URL will be called with the 60 generated images once processing is complete (estimated 1–2 hours).
Prompt for Vibe Coder
Skip the docs — paste this prompt into your AI agent and let it handle the integration.
Base URL
https://api.runflow.ioAuthentication
Include your API key in the request header:
| Header | Type | Required | Description |
|---|---|---|---|
x-api-key | string | Yes | Your Runflow API key |
Request Body
You can send input images in one of two ways. callback_url is required in both cases.
| Field | Type | Required | Description |
|---|---|---|---|
callback_url | string | Yes | URL that receives the completed headshots webhook |
images | File[] | Yes | One or more image files (JPEG, PNG, WebP). Send as repeated form fields. |
| Field | Type | Required | Description |
|---|---|---|---|
callback_url | string | Yes | URL that receives the completed headshots webhook |
input_images | string[] | Yes | Array of publicly accessible image URLs |
Examples
curl -X POST https://api.runflow.io/api/v1/images/generate-headshots \
-H "x-api-key: YOUR_API_KEY" \
-F "callback_url=https://yourapp.com/webhook/headshots" \
-F "images=@/path/to/photo1.jpg" \
-F "images=@/path/to/photo2.jpg" \
-F "images=@/path/to/photo3.jpg"Response
Returns immediately with a headshots_id to track the job. Processing runs in the background.
{
"success": true,
"data": {
"headshots_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}| Field | Type | Description |
|---|---|---|
success | boolean | true when the job was accepted successfully |
data.headshots_id | string (UUID) | Unique identifier for this headshot generation job |
Webhook Callback
When all 60 headshots are ready (estimated 1–2 hours), Runflow will send a POST request to your callback_url with the following payload:
{
"event": "headshots.completed",
"headshots_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"image_urls": [
"https://cdn.runflow.io/headshots/out_001.jpg",
"https://cdn.runflow.io/headshots/out_002.jpg",
"..."
]
}The image_urls expire after 24 hours. Make sure your webhook handler saves the URLs to your own storage immediately upon receipt.
| Field | Type | Description |
|---|---|---|
event | string | Always headshots.completed |
headshots_id | string (UUID) | Matches the ID from the initial API response |
image_urls | string[] | 60 generated headshot URLs. Expire after 24 hours — store immediately. |
Webhook handler example
// Example Express.js webhook handler
app.post("/webhook/headshots", async (req, res) => {
const { event, headshots_id, image_urls } = req.body;
if (event === "headshots.completed") {
// Store image_urls immediately — they expire in 24 hours
await db.saveHeadshots({ headshots_id, image_urls });
}
res.sendStatus(200);
});