Wedding Projects API

A durable, resumable lifecycle for finishing up to 5,000 selected wedding photographs and delivering one ZIP plus manifest.

Production contract verified · 29 live checks · 2026-08-23

Overview

Base URL: https://api.pixelapi.dev

The API separates project creation, sequential asset uploads, processing, and delivery. Clients should keep the returned project_id, reuse an idempotency_key when retrying creation, and give every file a stable client_asset_id.

Source limit5,000 images per project
Accepted formatsJPEG, PNG, WebP
Maximum file size40 MB per image
Minimum dimensions64 × 64 pixels
Cost1 credit per source image when processing starts
Presetsnatural_warm, true_color, cinematic_soft, reference_match

Authentication

Send the API key as a Bearer token. Keep the real key in an environment variable; the example value below is deliberately non-working.

Authorization: Bearer pxapi_demo_not_a_real_key

Create a project

POST/v1/wedding-projects201
curl -X POST https://api.pixelapi.dev/v1/wedding-projects \
  -H "Authorization: Bearer $PIXELAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Ananya and Rohan - final gallery",
    "preset": "reference_match",
    "idempotency_key": "ananya-rohan-final-v1",
    "preserve_resolution": true,
    "jpeg_quality": 94
  }'
FieldTypeNotes
namestring1–160 characters after whitespace normalization.
presetstringDefaults to natural_warm.
idempotency_keystringOptional, up to 160 characters. Reuse it to recover the same project.
preserve_resolutionbooleanDefaults to true.
jpeg_qualityinteger80–98; default 94.
webhook_urlstringOptional public HTTPS endpoint. Private, credentialed, or non-HTTPS URLs are rejected.
{
  "project_id": "3bf6b390-...",
  "name": "Ananya and Rohan - final gallery",
  "preset": "reference_match",
  "status": "draft",
  "counts": {"total": 0, "completed": 0, "failed": 0,
             "cancelled": 0, "remaining": 0},
  "progress_percent": 0.0,
  "delivery_url": null,
  "manifest_url": null
}

List projects

GET/v1/wedding-projects?limit=20200

limit may be 1–100. Projects are returned newest first and are scoped to the authenticated account.

Get one project

GET/v1/wedding-projects/{project_id}200

Poll this endpoint while status is queued or processing. Terminal states are completed, completed_with_errors, cancelled, and failed.

Upload an asset

POST/v1/wedding-projects/{project_id}/assets201 / 200

Use multipart form data. A new asset returns 201. Reusing the same client_asset_id returns the existing asset with 200, which makes an interrupted upload loop safe to resume.

curl -X POST \
  "https://api.pixelapi.dev/v1/wedding-projects/$PROJECT_ID/assets" \
  -H "Authorization: Bearer $PIXELAPI_API_KEY" \
  -F "file=@approved_reference.jpg" \
  -F "client_asset_id=approved-reference" \
  -F "sort_order=0" \
  -F "role=reference"

curl -X POST \
  "https://api.pixelapi.dev/v1/wedding-projects/$PROJECT_ID/assets" \
  -H "Authorization: Bearer $PIXELAPI_API_KEY" \
  -F "[email protected]" \
  -F "client_asset_id=source-00001" \
  -F "sort_order=0" \
  -F "role=source"

Upload only while the project is draft. Reference Match requires a reference asset before start. A new reference becomes the project's current reference.

List assets

GET/v1/wedding-projects/{project_id}/assets200

Query parameters: offset from 0, limit from 1–500, and optional status. Each asset includes its stable IDs, role, order, dimensions, status, attempt count, output URL, and error message.

Delete a draft asset

DELETE/v1/wedding-projects/{project_id}/assets/{asset_id}204

Deletion is allowed only while the project is a draft. After processing starts, use cancellation or retry instead of altering the asset list.

Start processing

POST/v1/wedding-projects/{project_id}/start202
curl -X POST \
  "https://api.pixelapi.dev/v1/wedding-projects/$PROJECT_ID/start" \
  -H "Authorization: Bearer $PIXELAPI_API_KEY" \
  -H "Content-Type: application/json" -d '{}'

The account must have enough credits for every source. Repeating start on an already-started or terminal project returns the current project and does not create a second run.

Cancel

POST/v1/wedding-projects/{project_id}/cancel202

A draft becomes cancelled immediately. An active project records a cancellation request and stops between assets. Credits reserved for unfinished work are refunded according to completed count. Calling cancel on a terminal project is idempotent.

Retry failed assets

POST/v1/wedding-projects/{project_id}/retry202

Retry is available only after the current run reaches a terminal state. An empty object retries every failed source; provide selected asset UUIDs to retry a subset.

# Retry every failed source
{"asset_ids": null}

# Retry selected failed sources
{"asset_ids": ["5e39f8f9-...", "1ad4794a-..."]}

If there are no matching failed images, the endpoint returns 409 and no credits are deducted.

Manifest and delivery ZIP

GET/v1/wedding-projects/{project_id}/manifest200

The authenticated manifest endpoint works throughout the project. On completion, delivery_url points to the ZIP and manifest_url points to the packaged public manifest. The ZIP contains manifest.json plus ordered JPEGs inside finished/.

Delivery validation: the live contract test downloaded two finished JPEGs, opened the delivery ZIP, and verified its manifest plus both ordered output files.

Errors and limits

StatusMeaning
401 / 403Authentication missing or rejected.
402Insufficient credits to start or retry.
404Project or asset does not exist for this account.
409Lifecycle conflict: no source/reference, upload after start, early retry, or no failed images.
413File exceeds 40 MB or project reached 5,000 sources.
422Invalid preset, field, UUID, image, dimensions, or JPEG quality.