---
title: "Create job with payment options"
method: POST
path: "/api/v1/jobs"
tags: ["Jobs"]
---

# Create job with payment options

`POST /api/v1/jobs`

## Request

- Base URL: `https://api.weftly.ai`
- URL: `https://api.weftly.ai/api/v1/jobs`
- Auth: one of:
  - API key in header `Authorization`
  - API key in header `Authorization`

Creates a job of any supported job_type and returns payment options + the next endpoint to call.

Three flow shapes by job_type:

1. **Upload-based** (`transcribe`, `summarize`, `find_clips`): pass `filename` + `content_type`. Response includes Stripe SPT checkout URL and MPP deposit info. After payment, GET /api/v1/jobs/{id}/upload-url, PUT the bytes, then POST /api/v1/jobs/{id}/complete-upload.

2. **Upload-based, card only** (`clips_from_video`, `clips_youtube`): a chain — finds clips in a video AND cuts them under one payment. Pass `filename` + `content_type` same as above, but the response includes a Stripe checkout URL ONLY — no MPP deposit info. These job types authorize a Stripe card hold for the worst case before the final price is known (it depends on how many clips are found and delivered), which MPP push settlement cannot express. Same upload steps as above once the hold is authorized; MPP-only callers should use `find_clips` then the relevant `extract_*` derivative instead (see shape 3).

3. **No-upload derivatives** (`extract_clip`, `extract_vertical_clip`): pass `source_job_id` + segments (or `start`/`end` for extract_vertical_clip). MPP-only payment (no Stripe). After payment, POST /api/v1/jobs/{id}/process — do NOT call /upload-url or /complete-upload, both will fail.

4. **No-upload, edit-driven** (`edit_from_transcript`): pass `source_job_id` + `edited_transcript` (the full edited copy of the `edit` transcript format, get it via ?format=edit). Validated against the parent's word-level transcript BEFORE any job or payment is created — an invalid edit returns 422 with the failing lines and creates nothing. Same POST /api/v1/jobs/{id}/process trigger as shape 3 — do NOT call /upload-url or /complete-upload.

For clip workflows: call `find_clips` ($2.00) once, then `extract_clip` / `extract_vertical_clip` against the find_clips job_id (within its 72h `expires_at`). Do not call `transcribe` first — find_clips includes a transcript.

## Request body

- CreateJobRequest
  - `job_type` 'transcribe' | 'summarize' | 'find_clips' | 'extract_clip' | 'extract_vertical_clip' | 'clips_vertical' | 'clips_from_video' | 'clips_youtube' | 'edit_from_transcript': Type of job to run
  - `filename` string
  - `content_type` string
  - `query` string
  - `source_job_id` string, uuid
  - `segments` ExtractClipSegment[]
    - `start` number, required
    - `end` number, required
    - `label` string
  - `include_transcript` boolean
  - `title` string
  - `start` number
  - `end` number
  - `profile` 'tiktok-primary' | 'tiktok-primary-720p' | 'instagram-reels' | 'instagram-stories': extract_vertical_clip. Encoding profile to use. tiktok-primary (default): 1080×1920 H.264 fast preset, CRF 22, 6 Mbps cap. tiktok-primary-720p: 720×1280, CBR 3 Mbps — half-resolution mobile-optimized, ~40% faster wall time. instagram-reels: 1080×1920 H.264 slow preset, CBR 4 Mbps. instagram-stories: same encode shape as instagram-reels. All four apply loudness normalization to -14 LUFS / -1.5 dBTP. This also sets the per-clip duration cap (see VERTICAL_CLIP_MAX_SECONDS_BY_PROFILE).
  - `subject` 'center' | 'manual' | 'auto' | 'subject_id' | 'follow': extract_vertical_clip: reframing strategy — "center" (default), "manual", "auto", "subject_id", or "follow". See /.well-known/weftly-subjects-v1.schema.json.
  - `subject_id` string
  - `subject_box` SubjectBox
    - `x` number, required: Box top-left x in source pixels.
    - `y` number, required: Box top-left y in source pixels.
    - `w` number, required: Box width in source pixels.
    - `h` number, required: Box height in source pixels.
  - `t_ref` number
  - `subject_x_offset` number
  - `captions` boolean: extract_vertical_clip. Burn word-level captions onto the clip (docs/vertical-clip-captions-plan.md). Defaults to true. Best-effort: a missing or unusable source transcript renders without captions rather than failing the job.
  - `edited_transcript` string: edit_from_transcript. The full edited copy of the `edit` transcript format, with every [NNNN] marker kept. Max 262144 UTF-8 bytes.
  - `thread_id` string, uuid: The chat thread this job belongs to, if created from a /chat handoff. Optional. Ownership is enforced at payment-settle time, not here — see notifyThreadPaid.

## Response `201`

Job created

- CreateJobResponse
  - `job_id` string, uuid, required
  - `job_type` 'transcribe' | 'summarize' | 'find_clips' | 'extract_clip' | 'extract_vertical_clip' | 'clips_vertical' | 'clips_from_video' | 'clips_youtube' | 'edit_from_transcript', required: Type of job to run
  - `payment_status` 'pending' | 'authorized' | 'paid' | 'refunded' | 'paid_by_parent', required
  - `price_cents` integer, required
  - `checkout_url` string, uri: Stripe SPT hosted checkout URL. Returned for upload-based jobs (transcribe, summarize, find_clips). Not returned for no-upload derivative jobs (extract_clip, extract_vertical_clip), which are MPP-only.
  - `stripe_checkout_session_id` string: Stripe checkout session id paired with checkout_url. Same conditions as checkout_url.
  - `source_job_id` string, uuid: For derivative jobs (extract_clip, extract_vertical_clip), echoes back the parent job id this job cuts from.
  - `next_endpoint` 'upload-url' | 'process': Which endpoint to call after payment. 'upload-url' for transcribe/summarize/find_clips (then PUT bytes, then complete-upload). 'process' for extract_clip/extract_vertical_clip (no upload, /process verifies payment and starts the job in one call).
  - `mpp` MppDepositInfo
    - `deposit_address` string, required
    - `network` string, required
    - `amount` string, required
    - `currency` string, required

## Other responses

- `400`: Invalid request
- `402`: Payment required

---

[API](https://skmtc.dev/weftly/apis/weftly-api.md) · [All operations](https://skmtc.dev/weftly/apis/weftly-api/llms.txt) · [OpenAPI document](https://skmtc.dev/weftly/apis/weftly-api/revisions/159cec179228?raw)
