curl -X POST https://api.vibepeak.ai/v1/real-estate/property-showcase/edit \
-H "Authorization: Bearer vpk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"image_url": "https://vibepeak-property-showcase-production.s3.eu-west-1.amazonaws.com/showcases/4d7fbd2c-8675-4fa9-aa62-570d4088b8a5/showcase_luxury_vertical_1788184569063.jpg",
"prompt": "replace the For Sale label with Sold",
"dominant_color": "#1A4D2E",
"font": "Montserrat",
"language": "es",
"webhook_url": "https://yourserver.com/webhooks/vibepeak"
}'
const response = await fetch('https://api.vibepeak.ai/v1/real-estate/property-showcase/edit', {
method: 'POST',
headers: {
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
image_url: 'https://vibepeak-property-showcase-production.s3.eu-west-1.amazonaws.com/showcases/4d7fbd2c-8675-4fa9-aa62-570d4088b8a5/showcase_luxury_vertical_1788184569063.jpg',
prompt: 'replace the For Sale label with Sold',
dominant_color: '#1A4D2E',
font: 'Montserrat',
language: 'es',
webhook_url: 'https://yourserver.com/webhooks/vibepeak'
})
});
const job = await response.json();
console.log(`Job created: ${job.job_id}`);
import requests
response = requests.post(
'https://api.vibepeak.ai/v1/real-estate/property-showcase/edit',
headers={
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
json={
'image_url': 'https://vibepeak-property-showcase-production.s3.eu-west-1.amazonaws.com/showcases/4d7fbd2c-8675-4fa9-aa62-570d4088b8a5/showcase_luxury_vertical_1788184569063.jpg',
'prompt': 'replace the For Sale label with Sold',
'dominant_color': '#1A4D2E',
'font': 'Montserrat',
'language': 'es',
'webhook_url': 'https://yourserver.com/webhooks/vibepeak'
}
)
job = response.json()
print(f"Job created: {job['job_id']}")
{
"job_id": "3301b1dc-9d3f-4754-8a22-08956432b812",
"status": "pending",
"message": "Property showcase edit request accepted for async processing",
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "At least one of prompt, dominant_color, font or language is required",
"details": {
"field": "prompt",
"issues": [
{ "path": "prompt", "message": "At least one of prompt, dominant_color, font or language is required" }
]
},
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Either source_result_id or image_url is required",
"details": {
"field": "source_result_id",
"issues": [
{ "path": "source_result_id", "message": "Either source_result_id or image_url is required" }
]
},
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "prompt must be at most 250 characters",
"details": {
"field": "prompt",
"issues": [
{ "path": "prompt", "message": "prompt must be at most 250 characters" }
]
},
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "image_url must be a valid URL",
"details": {
"field": "image_url",
"issues": [
{ "path": "image_url", "message": "image_url must be a valid URL" }
]
},
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "SSRF_BLOCKED",
"message": "Image URL points to a private network which is not allowed.",
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Not enough credits to process the request.",
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "FORBIDDEN",
"message": "image_url must be the URL of a property showcase you generated",
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "INVALID_CONTENT_TYPE",
"message": "Request Content-Type must be application/json",
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
Images
Edit Property Showcase
Edit an existing property showcase image with a natural-language prompt and style overrides
POST
/
v1
/
real-estate
/
property-showcase
/
edit
curl -X POST https://api.vibepeak.ai/v1/real-estate/property-showcase/edit \
-H "Authorization: Bearer vpk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"image_url": "https://vibepeak-property-showcase-production.s3.eu-west-1.amazonaws.com/showcases/4d7fbd2c-8675-4fa9-aa62-570d4088b8a5/showcase_luxury_vertical_1788184569063.jpg",
"prompt": "replace the For Sale label with Sold",
"dominant_color": "#1A4D2E",
"font": "Montserrat",
"language": "es",
"webhook_url": "https://yourserver.com/webhooks/vibepeak"
}'
const response = await fetch('https://api.vibepeak.ai/v1/real-estate/property-showcase/edit', {
method: 'POST',
headers: {
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
image_url: 'https://vibepeak-property-showcase-production.s3.eu-west-1.amazonaws.com/showcases/4d7fbd2c-8675-4fa9-aa62-570d4088b8a5/showcase_luxury_vertical_1788184569063.jpg',
prompt: 'replace the For Sale label with Sold',
dominant_color: '#1A4D2E',
font: 'Montserrat',
language: 'es',
webhook_url: 'https://yourserver.com/webhooks/vibepeak'
})
});
const job = await response.json();
console.log(`Job created: ${job.job_id}`);
import requests
response = requests.post(
'https://api.vibepeak.ai/v1/real-estate/property-showcase/edit',
headers={
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
json={
'image_url': 'https://vibepeak-property-showcase-production.s3.eu-west-1.amazonaws.com/showcases/4d7fbd2c-8675-4fa9-aa62-570d4088b8a5/showcase_luxury_vertical_1788184569063.jpg',
'prompt': 'replace the For Sale label with Sold',
'dominant_color': '#1A4D2E',
'font': 'Montserrat',
'language': 'es',
'webhook_url': 'https://yourserver.com/webhooks/vibepeak'
}
)
job = response.json()
print(f"Job created: {job['job_id']}")
{
"job_id": "3301b1dc-9d3f-4754-8a22-08956432b812",
"status": "pending",
"message": "Property showcase edit request accepted for async processing",
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "At least one of prompt, dominant_color, font or language is required",
"details": {
"field": "prompt",
"issues": [
{ "path": "prompt", "message": "At least one of prompt, dominant_color, font or language is required" }
]
},
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Either source_result_id or image_url is required",
"details": {
"field": "source_result_id",
"issues": [
{ "path": "source_result_id", "message": "Either source_result_id or image_url is required" }
]
},
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "prompt must be at most 250 characters",
"details": {
"field": "prompt",
"issues": [
{ "path": "prompt", "message": "prompt must be at most 250 characters" }
]
},
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "image_url must be a valid URL",
"details": {
"field": "image_url",
"issues": [
{ "path": "image_url", "message": "image_url must be a valid URL" }
]
},
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "SSRF_BLOCKED",
"message": "Image URL points to a private network which is not allowed.",
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Not enough credits to process the request.",
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "FORBIDDEN",
"message": "image_url must be the URL of a property showcase you generated",
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "INVALID_CONTENT_TYPE",
"message": "Request Content-Type must be application/json",
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
Edits an existing property showcase image through the image-edit flow. You provide the URL of the image to edit plus at least one editing directive (a prompt and/or style overrides). Editing runs asynchronously — the request returns a job ID immediately and the edited image is delivered to your
See Error Handling for more details.
webhook_url.
At least one of prompt, dominant_color, font, or language must be supplied — a request with no changes is rejected with a VALIDATION_ERROR.
Set a
webhook_url. Showcase jobs are not pollable: Get Task covers video tasks only and returns 404 TASK_NOT_FOUND for a showcase job_id. The webhook is the only way to receive output_image_url.Request Body
string
required
URL of the property showcase image to edit. This must be the result URL (
output_image_url) of a property showcase you previously generated — you cannot edit arbitrary images. A URL that doesn’t belong to one of your showcases returns FORBIDDEN.Omitting
image_url returns the message Either source_result_id or image_url is required. source_result_id is an internal identifier used by the VibePeak dashboard and is not available to API clients — always send image_url.Image URLs cannot point to private/internal networks (SSRF protection). A blocked URL returns
SSRF_BLOCKED.string
Natural-language editing instruction, e.g.
"replace the For Sale label with Sold". Maximum 250 characters.string
Dominant color to apply to the showcase, e.g.
"#1A4D2E" or "navy".string
Font to apply to the showcase text, e.g.
"Montserrat".string
Language used to render the showcase copy. One of
en, es, de, fr, it, pt. Forwarded to the generation service so the rendered text matches the requested locale.You must send at least one of
prompt, dominant_color, font, or language. An edit request with none of these is rejected with a VALIDATION_ERROR.string
URL to receive a webhook notification when the job completes. Must be a valid HTTPS URL, at most 2048 characters. May be
null. See Webhooks for details.The webhook is the only way to receive the edited image. Edit jobs are not exposed through Get Task. Without a
webhook_url you cannot retrieve output_image_url.Webhook URLs must use HTTPS and cannot point to private/internal networks (SSRF protection). A non-HTTPS or private URL is rejected with
VALIDATION_ERROR and the message Webhook URL must be HTTPS and cannot point to private networks.webhook_url on its own does not count as an editing directive — you still need at least one of prompt, dominant_color, font or language.Response
string
required
Unique identifier for the edit job. Use this to check status or correlate the webhook.
string
required
Initial job status. Always
pending for new jobs.string
required
Human-readable confirmation that the request was accepted for async processing.
string
required
Unique identifier for this request, useful for support and debugging.
curl -X POST https://api.vibepeak.ai/v1/real-estate/property-showcase/edit \
-H "Authorization: Bearer vpk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"image_url": "https://vibepeak-property-showcase-production.s3.eu-west-1.amazonaws.com/showcases/4d7fbd2c-8675-4fa9-aa62-570d4088b8a5/showcase_luxury_vertical_1788184569063.jpg",
"prompt": "replace the For Sale label with Sold",
"dominant_color": "#1A4D2E",
"font": "Montserrat",
"language": "es",
"webhook_url": "https://yourserver.com/webhooks/vibepeak"
}'
const response = await fetch('https://api.vibepeak.ai/v1/real-estate/property-showcase/edit', {
method: 'POST',
headers: {
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
image_url: 'https://vibepeak-property-showcase-production.s3.eu-west-1.amazonaws.com/showcases/4d7fbd2c-8675-4fa9-aa62-570d4088b8a5/showcase_luxury_vertical_1788184569063.jpg',
prompt: 'replace the For Sale label with Sold',
dominant_color: '#1A4D2E',
font: 'Montserrat',
language: 'es',
webhook_url: 'https://yourserver.com/webhooks/vibepeak'
})
});
const job = await response.json();
console.log(`Job created: ${job.job_id}`);
import requests
response = requests.post(
'https://api.vibepeak.ai/v1/real-estate/property-showcase/edit',
headers={
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json'
},
json={
'image_url': 'https://vibepeak-property-showcase-production.s3.eu-west-1.amazonaws.com/showcases/4d7fbd2c-8675-4fa9-aa62-570d4088b8a5/showcase_luxury_vertical_1788184569063.jpg',
'prompt': 'replace the For Sale label with Sold',
'dominant_color': '#1A4D2E',
'font': 'Montserrat',
'language': 'es',
'webhook_url': 'https://yourserver.com/webhooks/vibepeak'
}
)
job = response.json()
print(f"Job created: {job['job_id']}")
{
"job_id": "3301b1dc-9d3f-4754-8a22-08956432b812",
"status": "pending",
"message": "Property showcase edit request accepted for async processing",
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "At least one of prompt, dominant_color, font or language is required",
"details": {
"field": "prompt",
"issues": [
{ "path": "prompt", "message": "At least one of prompt, dominant_color, font or language is required" }
]
},
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Either source_result_id or image_url is required",
"details": {
"field": "source_result_id",
"issues": [
{ "path": "source_result_id", "message": "Either source_result_id or image_url is required" }
]
},
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "prompt must be at most 250 characters",
"details": {
"field": "prompt",
"issues": [
{ "path": "prompt", "message": "prompt must be at most 250 characters" }
]
},
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "image_url must be a valid URL",
"details": {
"field": "image_url",
"issues": [
{ "path": "image_url", "message": "image_url must be a valid URL" }
]
},
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "SSRF_BLOCKED",
"message": "Image URL points to a private network which is not allowed.",
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Not enough credits to process the request.",
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "FORBIDDEN",
"message": "image_url must be the URL of a property showcase you generated",
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
{
"error": {
"code": "INVALID_CONTENT_TYPE",
"message": "Request Content-Type must be application/json",
"request_id": "req_ZfI8Az4uwbSqXlzKUAtDg"
}
}
Webhook Payload
If you provide awebhook_url, VibePeak sends a POST request when the job finishes, carrying X-VibePeak-Event, X-VibePeak-Signature and X-VibePeak-Timestamp headers. Delivery is attempted up to 3 times with exponential backoff; a 4xx response from your endpoint stops the retries. See Webhooks for signature verification.
Edit jobs use the same payload shape as generation jobs, with kind set to edit. An edit has no template, so template_id is an empty string.
Completed
{
"event": "showcase.completed",
"job_id": "3301b1dc-9d3f-4754-8a22-08956432b812",
"status": "succeeded",
"kind": "edit",
"template_id": "",
"output_image_url": "https://vibepeak-property-showcase-production.s3.eu-west-1.amazonaws.com/showcases/4d7fbd2c-8675-4fa9-aa62-570d4088b8a5/edit_vertex_1788184618383.jpg",
"error": null,
"created_at": "2026-08-31T13:56:53.109+00:00",
"completed_at": "2026-08-31T13:57:11.529+00:00"
}
Failed
{
"event": "showcase.failed",
"job_id": "3301b1dc-9d3f-4754-8a22-08956432b812",
"status": "failed",
"kind": "edit",
"template_id": "",
"output_image_url": null,
"error": "An unexpected error occurred while generating the property showcase. Please try again later.",
"created_at": "2026-08-31T13:56:53.109+00:00",
"completed_at": "2026-08-31T13:57:11.529+00:00"
}
On failure
error is always the fixed string above — the underlying provider message is never exposed. Use request_id from the edit call when contacting support.Error Codes
| Code | Status | Description |
|---|---|---|
VALIDATION_ERROR | 400 | Invalid request parameters, missing source image, missing editing directive, prompt over 250 characters, or invalid image/webhook URL |
SSRF_BLOCKED | 400 | image_url points to a private/internal network or is otherwise not allowed |
INVALID_JSON | 400 | Request body is not valid JSON |
INVALID_API_KEY | 401 | Invalid or missing API key |
INSUFFICIENT_CREDITS | 402 | Not enough credits to process the request |
FORBIDDEN | 403 | image_url is not the result of a property showcase you generated |
PLAN_REQUIRED | 403 | Plan doesn’t include API access |
NOT_FOUND | 404 | The referenced source showcase result does not exist |
INVALID_CONTENT_TYPE | 415 | Content-Type header is missing or is not application/json |
CONCURRENCY_LIMIT_EXCEEDED | 429 | Concurrent job limit reached |
EXTERNAL_SERVICE_ERROR | 502 | The image edit service could not be reached; the job is marked failed |
Error shape.
VALIDATION_ERROR responses carry a details object of the form { "field": "<dotted.path>", "issues": [{ "path": "<dotted.path>", "message": "..." }] } — field is the first failing path and issues lists every failure. All other error codes return no details.Credits
This endpoint charges 2 credits per request for accounts without an annual plan. Accounts on an annual plan are not charged (0 credits). Credits are charged upon successful job creation and are not refunded if the edit fails.Test mode is not supported on this endpoint. Unlike the video endpoints, a
vpk_test_ key is not sandboxed here — the request runs the real generation pipeline and charges credits. Use it only when you intend to generate a real image. See Test Mode.Next Steps
After creating a job:- Wait for the webhook: your
webhook_urlreceives ashowcase.completedorshowcase.failednotification. Verify theX-VibePeak-Signatureheader as described in Webhooks. - Download the image: read
output_image_urlfrom theshowcase.completedpayload.
output_image_url can be passed straight back into this endpoint to chain another edit.
There is no polling endpoint for showcase jobs. Get Task serves video tasks only and returns
404 TASK_NOT_FOUND for a showcase job_id. If you do not set a webhook_url, the edited image cannot be retrieved.
