API Reference

API Documentation

Everything you need to integrate Editing Machine into your applications, agents, and workflows.

Base URL: https://api.editingmachine.com/api/v1Version: v1OpenAPI Spec

Quick Start

Get up and running with the Editing Machine API in under 5 minutes. Projects follow a four-step lifecycle: create a project, attach footage, execute, then poll for status. Production Credits are only applied to your available production capacity when you execute.

1. Get your API key

Log in to your Editing Machine account and navigate to Automation → API Keys. Generate a new key and store it securely.

2. Create a project

Creating a project returns a signed price_quote showing the Production Credits required — no production capacity is used yet.

Create a project
curl -X POST https://api.editingmachine.com/api/v1/projects \
  -H "Authorization: Bearer em_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "recipe_id": 1,
    "project_name": "My Video Project",
    "brand_id": 5
  }'

3. Attach footage

Attach a source file by URL
curl -X POST https://api.editingmachine.com/api/v1/projects/42/assets \
  -H "Authorization: Bearer em_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://example.com/footage.mp4" }'

4. Execute the project

Pass the quote_id from step 2 to lock in the capacity requirement. The quoted Production Credits are applied here.

Start execution
curl -X POST https://api.editingmachine.com/api/v1/projects/42/execute \
  -H "Authorization: Bearer em_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ "quote_id": "eyJ...signed..." }'

5. Poll for status

Get project status
curl https://api.editingmachine.com/api/v1/projects/42 \
  -H "Authorization: Bearer em_xxxxxxxxxxxx"

When the status reads complete, the response includes output_urls with the finished deliverables.

Authentication

All API requests require a Bearer token in the Authorization header. API keys are scoped to your account and can be revoked at any time from the dashboard.

Header format

Authorization header
Authorization: Bearer em_xxxxxxxxxxxx

Keys are issued in the dashboard under Automation → API Keys. All keys use the single em_* format and run against live infrastructure — there is no separate test or sandbox key.

Keep keys secure

Never expose API keys in client-side code, public repos, or logs. Use environment variables and server-side requests only.

Endpoints

POST/api/v1/projects

Create a project. Returns a signed quote for the required Production Credits — no production capacity is used yet.

Request body

recipe_idinteger*ID of a published recipe to run
project_namestringOptional human-readable name for the project
brand_idintegerOptional brand ID used by Brand Knowledge for style consistency

Response

201 Created
{
  "id": 42,
  "status": "created",
  "recipe": { "name": "YouTube Long-Form", "type": "purpose" },
  "credits_estimated": 5,
  "price_quote": {
    "quote_id": "eyJ...signed...",
    "credits": 5,
    "fingerprint": "a1b2c3...",
    "expires_at": "2026-03-25T10:15:00.000Z"
  },
  "created_at": "2026-03-25T10:00:00.000Z"
}

For backward compatibility, the credits_estimated and price_quote.credits fields represent Production Credits.

price_quote.quote_id is a server-signed token that locks in the price shown at creation. You must pass it to /execute. Tampered, expired, or stale quotes (pricing has drifted) are rejected — re-create the project to get a fresh one.

POST/api/v1/projects/:id/assets

Attach source footage to a project by URL. Returns immediately while the file imports in the background.

Request body

urlstring*Publicly accessible URL of the source video or image file

Response

202 Accepted
{
  "asset_id": "import-a1b2c3d4",
  "filename": "footage.mp4",
  "status": "importing",
  "size_bytes": null
}
POST/api/v1/projects/:id/execute

Start the project. The quoted Production Credits are applied to your available production capacity here. Project must be in created or draft status.

Request body

quote_idstring*The signed quote_id returned from project creation

Response

200 OK
{
  "id": 42,
  "status": "queued",
  "credits_deducted": 5,
  "credits_remaining": 245
}

The legacy credits_deducted and credits_remaining response fields report Production Credits.

GET/api/v1/projects/:id

Poll a project's current status, progress, and output URLs.

200 OK
{
  "id": 42,
  "status": "processing",
  "progress_percent": 65,
  "output_urls": [],
  "created_at": "2026-03-25T10:00:00.000Z",
  "updated_at": "2026-03-25T10:30:00.000Z"
}

Status values

createdprocessingcompleterevisionfailed

Webhooks

Receive real-time notifications when project status changes. Register an endpoint with POST /api/v1/webhooks specifying the URL and events you want to subscribe to.

Register a webhook

POST /api/v1/webhooks
{
  "url": "https://your-app.example.com/webhooks/editing-machine",
  "events": [
    "project.started",
    "project.completed",
    "project.failed",
    "project.awaiting_client_input"
  ]
}

Event types

project.startedExecution has begun on the project
project.completedProject is finished. output_urls is populated with deliverables
project.failedExecution failed. Error details included in the payload
project.awaiting_client_inputThe Director needs the client to respond before continuing

Example payload

POST to your registered URL
{
  "event": "project.completed",
  "project_id": 42,
  "timestamp": "2026-03-25T12:00:00.000Z",
  "data": {
    "status": "complete",
    "output_urls": ["https://..."]
  }
}

Signature verification

Every webhook request includes a signature header so you can verify it came from Editing Machine:

Signature header
X-Webhook-Signature: <hex HMAC-SHA256 of the raw request body>

The value is a raw HMAC-SHA256 hex digest of the request body using your webhook secret — no sha256= prefix. Your secret is shown in the dashboard alongside your API keys. Always verify signatures before processing webhook data.

Status Codes

200
OK — Request succeeded
201
Created — Resource created successfully
202
Accepted — Request accepted for asynchronous processing
400
Bad Request — Invalid body or parameters
401
Unauthorized — Missing, invalid, or expired API key
402
Payment Required — Insufficient Production Credits
404
Not Found — Resource not found or not owned by your account
409
Conflict — Project already executing/completed, or quote_stale (pricing drifted since the quote was issued)
410
Gone — quote_expired (signed quote is past its expires_at; re-create the project)
429
Too Many Requests — Rate-limit or concurrent-job limit exceeded
500
Internal Server Error — Something went wrong on our end

Error response format

Errors are returned as a flat object with a machine-readable code and a human-readable message:

Error response
{
  "error": "quote_expired",
  "message": "Price quote expired. Re-create the project to get a fresh quote."
}

Rate limits

Rate limits are per API key and tiered by plan. Concurrent jobs are also capped — projects beyond your limit will return 429 until one finishes.

Tier
Requests/min
Concurrent Jobs
Free
5
1
Core
15
3
Studio
30
5
Scale
60
10

Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers.

Source of truth

The live OpenAPI spec is generated directly from server code and kept in sync by a CI drift check. If anything here disagrees with the spec, the spec is right.

Ready to start building?

Get your API key and run your first project in minutes.