Captik for Business

The Captik API

Send Captik a video from your own systems and get back word-timed captions in Indian languages and English, styled and edited videos, and finished exports up to 4K. The API draws on your business account's credit balance, the same one your team uses in the web editor and the Premiere Pro and DaVinci Resolve plugins.

Anyone can start: create a business account at captik.in/business, add credits (in India: rupees plus GST through Cashfree, with a GST invoice; elsewhere: US dollars through Dodo Payments), create an API key, and call the API. No sales call, no contract.

Overview

The API is a JSON REST API at https://captik.in/api/v1. A typical run:

  1. Upload your video (or give us a link to it) and create a project. Captik transcribes it and times every word.
  2. Read or edit the captions, pick a template and style, run an AI Edit, add sound, graphics or a voiceover.
  3. Start an export and download the finished video when the webhook says it is ready.

Anything that takes longer than a moment (transcription, AI Edits, exports) runs as a job: the call answers at once with the job, and you poll it or wait for the webhook.

Quickstart

  1. Sign in and create a business account at captik.in/business.
  2. Add credits there: India pays in rupees plus GST through Cashfree; everywhere else pays in US dollars through Dodo.
  3. Create an API key in the same dashboard, then:
# 1. Create a project from a video link (or upload one first: POST /uploads)
curl https://captik.in/api/v1/projects \
  -H "Authorization: Bearer $CAPTIK_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: episode-0412" \
  -d '{"video_url": "https://cdn.example.com/episode-0412.mp4", "language": "auto", "script": "roman"}'

# 2. Wait for the job (or the project.ready webhook)
curl https://captik.in/api/v1/jobs/JOB_ID -H "Authorization: Bearer $CAPTIK_API_KEY"

# 3. Download the captions
curl "https://captik.in/api/v1/projects/PROJECT_ID/captions?format=srt" -H "Authorization: Bearer $CAPTIK_API_KEY"

# 4. Export the video with a template, burned in
curl https://captik.in/api/v1/projects/PROJECT_ID/exports \
  -H "Authorization: Bearer $CAPTIK_API_KEY" -H "Content-Type: application/json" \
  -d '{"aspect": "16:9", "resolution": "1080p"}'

Authentication

Every call carries one of your business's API keys:

Authorization: Bearer ck_live_...

Owners and admins create and revoke keys in the business dashboard. A key is shown once, when it is made; Captik stores only a hash of it. Keep keys on your servers, never in an app or a web page. A revoked key stops working within a minute.

Credits and pricing

Your business account holds a prepaid credit balance: one credit is one rupee. Your team's use of the web editor and plugins and your API calls all draw on it. The standard rates, charged by the second of video (your agreement may differ; GET /me shows yours):

  • ₹5.50 a minute of video captioned: transcription, scripts, translation to English, emphasis, styles and cut-outs on that video.
  • ₹5.50 a minute to translate captions into another language.
  • ₹7 a minute of video for each AI Edit.
  • ₹3 a minute of video an AI video tool processes.
  • ₹3.50 a minute of video exported, up to 1080p. A 4K minute counts as 2.5 minutes.
  • ₹7 a minute of generated voiceover.

Adding credits. Owners and admins top up any time in the business dashboard, with a pack or any amount, or from your own systems with POST /credits/checkout, which returns a hosted payment link. In India you pay in rupees through Cashfree, with 18% GST added on top, and Captik issues a GST tax invoice for every top-up (GET /invoices). Elsewhere you pay in US dollars through Dodo Payments, at 65 credits per US dollar; Dodo adds your local sales tax or VAT and sends the invoice. Credits land the moment the payment does, and show in GET /usage at once. When your balance falls under your alert line, we email you and send a balance.low webhook, both with a link to top up.

A job that fails or that you cancel gives its credits back automatically. When a job needs more credits than your balance holds, it is refused with 402 insufficient_credits before any work starts, and uploads and new projects need at least ₹10 of credits. GET /usage lists every charge, refund and top-up, also as CSV.

Jobs

Long work answers 202 with a job:

{
  "id": "6f1c...", "object": "job", "kind": "project.export",
  "status": "running",            // queued | running | succeeded | failed | canceled
  "step": "rendering", "progress": 0.42,
  "project_id": "b2e9...",
  "output": null,                 // set when status is succeeded
  "error": null,                  // { "code", "message" } when status is failed
  "charged_credits": 40,
  "created_at": "...", "started_at": "...", "finished_at": null
}

Poll GET /jobs/:id (every few seconds is fine) or use webhooks. POST /jobs/:id/cancel stops a job and returns its credits. Jobs survive restarts on our side: one that is interrupted resumes from its last step.

Webhooks

Set an https endpoint in the business dashboard and Captik will POST these events to it:

  • project.ready, project.failed: a new project was transcribed (or could not be).
  • export.ready: an export finished; the payload has the download link.
  • job.succeeded, job.failed, job.canceled: any job ended.
  • balance.low: your balance fell under your alert line.
  • webhook.test: sent by POST /webhooks/test.

Each call is signed with your webhook secret. Check the signature, and treat the Captik-Delivery id as idempotent: a delivery that does not get a 2xx answer within 10 seconds is retried, with backoff, 8 tries over about a day. Each retry goes to your webhook URL as it is then: change it and the events still owed follow; remove it and they stop.

No server yet? Set https://captik.in/api/webhook-test as your webhook and send a test event: it answers 200 to every call, so you see a delivery succeed. It stores nothing.

POST /your/endpoint
Captik-Event: export.ready
Captik-Delivery: 1d0c...
Captik-Signature: t=1731400000,v1=5f2b...   // HMAC-SHA256 of "<t>.<raw body>"

{ "id": "1d0c...", "type": "export.ready", "created_at": "...", "data": { ... } }

Verifying in Node.js:

import crypto from 'node:crypto';

function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;   // older than 5 minutes
  const want = crypto.createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(want, 'hex'), Buffer.from(parts.v1, 'hex'));
}

And in Python:

import hmac, hashlib, time

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    if abs(time.time() - int(parts["t"])) > 300:
        return False
    want = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(want, parts["v1"])

Errors

Errors share one shape, with a request_id to quote to us:

{ "error": { "code": "insufficient_credits", "message": "...", "details": { "needed_credits": 120, "available_credits": 35 } }, "request_id": "req_..." }
400invalid_requestThe body or a parameter is not right; details lists what.
401unauthorizedNo key, or a key that is not valid.
402insufficient_creditsTop up, then retry.
403business_suspendedThe account is paused. Contact us.
404not_foundNo such id in your business.
409conflict / idempotency_conflictA simultaneous change, or a reused Idempotency-Key.
429rate_limitedToo many requests; wait Retry-After seconds.
500 / 503internal_error / unavailableOur side. Retry with backoff; it is logged.

Limits and retries

  • Up to 600 requests a minute per key. Over that, 429 with Retry-After.
  • Send an Idempotency-Key header (any unique string, up to 200 characters) on calls that start work. Repeating the call with the same key returns the first job instead of starting and charging a second one.
  • Videos up to 20 GB and 6 hours. Any common format; iPhone HEVC is converted for you before export.
  • Download links last 24 hours; ask for the job or the project's exports again for a fresh one.

Endpoints

Account

GET/me

Your business: balance, what you can spend now (with any credit line), your rates, seats and webhook settings.

{
  "object": "business", "id": "…", "name": "…", "status": "active",
  "balance_credits": 182450.5, "available_credits": 182450.5, "overdraft_credits": 0,
  "low_balance_alert_credits": 1000,
  "rates": { "currency": "INR", "credit_value_inr": 1, "caption_per_minute": 5.5, "export_per_minute": 3.5,
             "export_4k_weight": 2.5, "voiceover_per_minute": 7, "ai_edit_per_minute": 7, "tools_per_minute": 3 },
  "seats": { "used": 3, "limit": 10 },
  "webhook": { "url": "https://…", "events": ["job.succeeded", "…"] }
}
GET/usage?from=2026-11-01&to=2026-12-01&format=json|csv

Every charge, refund and top-up in a date range, newest first, with the range's totals on the first page. Plain dates are midnight IST; "to" is not included. format=csv downloads the whole range as a spreadsheet.

Uploads

Send us the file directly, or skip this and give POST /projects a video_url instead.

POST/uploads

Get somewhere to put your video. Up to 100 MB: one PUT to the url returned. Larger files (up to 20 GB) come back as a multipart upload: PUT each part to its url, then call /uploads/complete.

{ "filename": "episode-0412.mp4", "content_type": "video/mp4", "size_bytes": 2147483648 }
// up to 100 MB
{ "upload": { "object": "upload", "key": "uploads/…/….mp4", "method": "PUT", "url": "https://…",
              "headers": { "Content-Type": "video/mp4" }, "expires_at": "…" } }
// larger
{ "upload": { "key": "…", "method": "MULTIPART", "upload_id": "…", "part_size": 67108864,
              "parts": [ { "part_number": 1, "url": "https://…" }, … ], "expires_at": "…", "complete_url": "…" } }
POST/uploads/complete

Finish a multipart upload. Send the ETag each part PUT answered with (or leave parts out and we read them from storage).

{ "key": "uploads/…", "upload_id": "…", "parts": [ { "part_number": 1, "etag": "\"…\"" } ] }

Projects

A project is one video and everything done to it.

POST/projectsreturns a job

Bring a video in and caption it: Captik downloads it (for a video_url), transcribes the speech, times every word and makes caption lines. Charged at the caption rate for the video's length. Send an Idempotency-Key so a retry never makes a second project.

{
  "video_key": "uploads/…",              // from POST /uploads, or:
  "video_url": "https://cdn.example.com/ep.mp4",
  "title": "Episode 412",
  "language": "auto",                     // or a code from GET /languages, e.g. "hi-IN"
  "script": "native",                     // native | roman | english
  "template": "TEMPLATE_ID",              // optional, from GET /templates
  "metadata": { "show": "…", "episode": "412" }
}
202 { "project": { "id": "…", "status": "processing", … }, "job": { "id": "…", "kind": "project.ingest", … } }
// job steps: downloading → extracting_audio → transcribing → aligning → captioning
// job output: { "project_id", "words", "lines", "duration_seconds", "language", "script", "warnings"? }
GET/projects?status=&limit=&before=

Your projects, newest first: { object: "list", data, has_more, next_before }.

GET/projects/:id

One project: status (processing | ready | failed), source details, language, script, template, a summary of the edit (including stock_credits), your metadata, and its latest job.

PATCH/projects/:id

Rename it or change its metadata (keys you send are merged; null removes one).

{ "title": "Episode 412 (final)", "metadata": { "status": "approved" } }
DELETE/projects/:id

Delete a project. Its open jobs are cancelled.

Captions

GET/projects/:id/captions?format=json|srt|vtt|txt

The captions. SRT and VTT follow the caption lines with real word timings. Add download=1 to get a file. 409 project_not_ready while it is still processing.

{ "object": "captions", "project_id": "…", "language": "hi-IN", "script": "roman", "template": "…",
  "words": [ { "id": "1", "text": "namaste", "start_ms": 820, "end_ms": 1240, "emphasis": false, "low_confidence": false } ],
  "lines": [ { "start_ms": 820, "end_ms": 2310, "text": "namaste doston", "word_ids": ["1", "2"] } ] }
PATCH/projects/:id/captions

Fix captions: change some words, replace them all, or regroup the lines. Words are in time order, without overlaps, and contain no spaces; lines cover every word in order.

{ "update": [ { "id": "14", "text": "Captik", "emphasis": true } ] }
// or { "words": [ { "text": "…", "start_ms": 0, "end_ms": 400 }, … ], "lines": [ { "word_ids": ["1","2","3"] } ] }
// or { "lines": [ { "word_ids": ["1","2"] }, { "word_ids": ["3","4","5"] } ] }
POST/projects/:id/translatereturns a job

Switch the script (native, roman, english: free) or translate the captions into another language (charged at the caption rate). Timings are carried over line by line.

{ "script": "roman" }
// or
{ "language": "ta-IN", "from": "original" }

Catalogue

The ids the other calls take.

GET/languages

The spoken languages we transcribe (with their scripts) and the languages captions can be translated into.

GET/templates?category=

Every caption template: { id, name, category, needs_cutout, tags }. Templates that draw behind the speaker make a cut-out automatically at export.

GET/looks

The AI Edits looks: { id, name, needs_cutout, bold }.

GET/music

The music beds you can put under a video or an AI Edit.

GET/sounds

The sound-effect library and the automatic sound-design styles.

GET/voices

Voiceover voices, reading styles and the speed range.

Style and edit

These change the project at once and answer with the new settings. Nothing is charged for them.

PATCH/projects/:id/style

Template, colours, sizes, one or two lines, where the captions sit, emphasis, and per-caption changes by line index. GET returns the current style.

{
  "template": "TEMPLATE_ID",
  "colors": { "dominant": "#FFFFFF", "accent": "#FFD400", "text": "#FFFFFF" },
  "font_scale": 1.1, "lines": "double",
  "position": { "x": 50, "y": 78, "width": 80 },        // % of the frame
  "captions": [ { "index": 3, "template": "OTHER_ID", "font": "Bebas Neue" } ],
  "font": "FONT_ID"                                    // your font's id, or a Google or built-in family; null = the template's
}
POST/fonts

Add one of your own fonts: a .ttf, .otf, .woff or .woff2 up to 5 MB, sent as a multipart "file" or as a link. Use its id (or its family) as "font" in /style. Free.

// multipart/form-data: file=@BrandSans.woff2, name=Brand Sans
// or
{ "url": "https://example.com/BrandSans.woff2", "name": "Brand Sans" }
{ "id": "…", "object": "font", "name": "Brand Sans", "family": "BrandSans", "format": "woff2", "size_bytes": 48210, "created_at": "…" }
GET/fonts

Your fonts, and the Google and built-in families /style takes by name.

DELETE/fonts/:id

Remove one of your fonts. Captions that used it go back to their template's font at the next export.

POST/projects/:id/cuts

Remove pauses, filler words ("um", "matlab") and repeated takes. Answers with the cuts made and the edited length.

{ "remove_pauses": { "min_ms": 600 }, "filler_words": true, "repeats": true }
{ "cuts": [[12040, 12890], ...], "removed_ms": 48210, "source_duration_ms": 1500000, "edited_duration_ms": 1451790 }
POST/projects/:id/sound

Automatic sound design, music bed and levels, or mute the original audio.

{ "auto_sound_effects": true, "sound_effects_level": 0.8, "music": "off", "music_level": 0.6, "mute_original": false }

AI Edits, graphics, voiceover, cut-out

POST/projects/:id/ai-editreturns a job

A full AI Edit in one of the looks: Captik watches the video, cuts it, and adds zooms, b-roll, sound and music. Every Customize switch of the editor is here. Send instructions to ask the director for a change, as in the editor. "broll": false takes the stock clips over the talk off; "stock_media": false keeps every stock photo and clip out of the edit, the look's own scenes included (use it for OTT, broadcast or anything that needs rights-cleared pictures; the scenes are drawn without pictures).

{
  "look": "LOOK_ID",
  "customize": { "hook": "3 mistakes new founders make", "zoom": "subtle", "broll": false,
                 "stock_media": false, "sounds": true, "cta": false, "accent": "#FF4D00" },
  "music": "off",
  "graphics": true,
  "instructions": "calmer, fewer zooms"
}
// job output
{ "planned": true, "scenes": 42, "sound_effects": 31, "hook": "...", "music": "off",
  "stock_credits": [ { "kind": "video", "creator": "...", "url": "https://www.pexels.com/video/...",
                       "source": "pexels", "shown": [ { "start_ms": 81200, "end_ms": 83600 } ] } ],
  "notes": [] }
POST/projects/:id/graphicsreturns a job

Motion graphics: auto plans them for the talk's moments, or place your own from the library with items. GET lists what is placed.

{ "auto": true }
// or
{ "items": [ { "template": "GRAPHIC_ID", "start_ms": 30000, "duration_ms": 4000, "params": { "title": "..." } } ], "replace": false }
POST/projects/:id/voiceoverreturns a job

Generate a voiceover from text and place it on the video. Charged at the voiceover rate. GET lists voiceovers.

{ "text": "...", "voice": "warm", "style": "natural", "speed": 1, "start_ms": 0, "volume": 1 }
POST/projects/:id/cutoutreturns a job

Cut the speaker out of the background (for templates and looks that draw behind the person). Exports make one automatically when they need it; this lets you prepare it ahead. GET returns its status.

Tools

The editor's tools, one call each. A tool runs as a job and leaves its result on the project; the export draws it. Tools that work per clip take every clip of your video unless "clips" picks some: { "clip_ids": [...] } (GET /projects/:id/tools lists them) or { "from_ms", "to_ms" } (the video is split there first). Each job is charged once at the tools rate, for the seconds of video it works on. Undo is free. The sound tools take up to 5 minutes of video per call: do a longer one in stretches with from_ms / to_ms.

GET/tools

Every tool: its id, where it runs, whether it takes "clips", and its options as JSON Schema.

{ "object": "list", "data": [ { "id": "reduce-noise", "name": "Reduce noise", "group": "voice", "runs": "server",
  "per_clip": true, "description": "…", "options": { "type": "object", "properties": { "strength": { "enum": ["light", "strong"] } } } }, … ] }
GET/projects/:id/tools

The clips of the video, and what each tool has set (null when nothing).

{ "object": "tools", "project_id": "…",
  "clips": [ { "id": "c_main", "own_video": true, "start_ms": 0, "end_ms": 61200 } ],
  "tools": [ { "id": "stabilize", "name": "Stabilize", "runs": "server", "applied": { "clips": [ { "clip_id": "c_main", "level": "recommended" } ] } }, … ] }
POST/projects/:id/tools/:toolreturns a job

Run a tool. The body is its options, plus "clips" if you want only some of the video.

{ "strength": "strong", "clips": { "from_ms": 0, "to_ms": 30000 } }
// job output
{ "object": "tool_result", "tool": "reduce-noise", "project_id": "…",
  "clips": [ { "clip_id": "c_main", "audio_item_id": "a_…", "duration_ms": 30000, "tools": ["reduce_noise"] } ],
  "applied": { … } }
DELETE/projects/:id/tools/:tool

Undo: take off what that tool set. Answers { removed, applied }.

POST/projects/:id/tools/reduce-noisereturns a job

Takes out hiss, hum, fans and room noise, keeping the voice.

{ "strength": "light | strong" }
POST/projects/:id/tools/enhance-voicereturns a job

Studio voice: noise out, rumble cut, clearer, levelled and loud.

{ "intensity": 25 | 50 | 75 | 100 }   // 75 by default
POST/projects/:id/tools/normalize-loudnessreturns a job

Brings the sound to a set loudness: default (-23 LUFS), tiktok (-12) or youtube (-14).

{ "target": "default | tiktok | youtube" }
POST/projects/:id/tools/voice-changerreturns a job

Changes the voice. The sound tools stack: each works on the last one's result. Undoing any of them gives the clip its original sound back.

{ "voice": "chipmunk | high | low | giant | robot | radio | megaphone | echo | hall | phone" }
POST/projects/:id/tools/beat-detectionreturns a job

Finds the beats of the music in the sound. It returns them only; nothing on the video changes.

// job output
{ "clips": [ { "clip_id": "c_main", "bpm": 118.5, "beats": [ { "source_ms": 512, "edit_ms": 512 }, … ] } ] }
POST/projects/:id/tools/auto-adjustreturns a job

Makes the colours better with a tone curve that follows the footage.

{ "intensity": 80 }   // 0 to 100
POST/projects/:id/tools/color-matchreturns a job

Gives the clips the colours of a reference: another clip, a moment or a stretch of the same video, or a picture.

{ "reference": { "at_ms": 41000 }, "intensity": 80 }
// or { "reference": { "clip_id": "c_…" } }, { "reference": { "from_ms": 0, "to_ms": 5000 } },
//    { "reference": { "image_url": "https://example.com/look.jpg" } }
POST/projects/:id/tools/reduce-image-noisereturns a job

Smooths grain and low-light noise, keeping edges.

{ "strength": 50 }   // 1 to 100
POST/projects/:id/tools/split-scenesreturns a job

Finds where the footage cuts to another shot and splits the video into clips there.

{ "mode": "scene | shot" }   // scene: only big changes, at least 2 s apart
POST/projects/:id/tools/stabilizereturns a job

Smooths out shaky footage. More stable crops in a little more.

{ "level": "recommended | minimum | most" }
POST/projects/:id/tools/remove-flickerreturns a job

Evens out lights that flicker or brightness that pumps. Use weak if the picture changes fast, strong if it changes slowly.

{ "mode": "timelapse | flash", "level": "weak | rec | strong" }
POST/projects/:id/tools/retouchreturns a job

Retouches faces. Values 0-100; leave them out for the automatic retouch. The faces are found once per stretch of video and reused by the next Retouch or Relight. If no face is found, the job still succeeds and its output says so.

{ "clear": 50, "smooth": 45, "whitening": 15, "blemishes": 0, "dewrinkle": 0, "even": 0, "smile_lines": 0, "dark_circles": 35, "bright_eyes": 25, "teeth": 35 }
POST/projects/:id/tools/relightreturns a job

Adds light: soft light on the face, coloured backlights, moving creative light. Makes the cut-out first when the project has none, so the light falls on the person.

{ "preset": "soft_face | warm_atmosphere | water_light | morning_sun | neon_bicolor | yellow_purple | teal_backlight | blue_backlight | green_side | red_purple_stroke | mysterious_purple | dark_night_green | rainbow_spot | color_swipe | multicolor_switch | metallic_laser | color_rotation | multicolor_flicker" }
POST/projects/:id/tools/auto-reframereturns a job

Changes the clips' shape and keeps the person in frame as they move. Replaces Stabilize, Camera tracking and AI movement on those clips. Another ratio on the same clips needs no second look.

{ "ratio": "9:16 | 16:9 | 1:1 | 4:3 | 3:4 | 2.35:1 | 2:1 | 1.85:1 | 5.8-inch", "stability": "flexible | normal | stable", "speed": "fast | normal | slow" }
POST/projects/:id/tools/camera-trackingreturns a job

Follows a face, body, hand or an area you pick, and holds it where it was on the picked frame. Use box to pick which one (fractions of the picture); "custom" needs a box.

{ "target": "face | body | hand | custom", "at_ms": 2000, "box": { "x": 0.4, "y": 0.1, "w": 0.2, "h": 0.25 },
  "fit_to_canvas": false, "lock_size": false, "blur_canvas": false }
POST/projects/:id/tools/ai-movementreturns a job

Camera moves on the beats and gestures (dynamic, soft, zoom, shake) or follows the speech, pushing in on each sentence and punching in on emphasised words. Another preset on the same clips needs no second look.

{ "preset": "dynamic | soft | zoom | shake | speech", "scale": 50, "rotation": 50, "distance": 50, "strength": 50 }
POST/projects/:id/tools/camera-followreturns a job

Measures how the camera moves, so an AI edit's scenes and a room look's words stay in place on handheld footage. Makes the cut-out first when needed. A still or unreliable camera keeps everything where it was planned. An AI edit export measures this itself when it has not been done.

{ "again": false }
// job output
{ "camera_moves": true, "trusted": true, "measured_seconds": 30, "samples": 300, "person_grid": true }
POST/projects/:id/tools/person-gridsreturns a job

Tracks where the person is in every frame, from the cut-out. AI edits and rebuilt looks use it to place their scenes; a depth look uses it to blur and dim the background behind the person. Exports also do this themselves when it is missing.

{ "aspect": "original | 9:16 | 16:9 | 1:1 | 4:5" }   // the export frame the depth grids are for; default the project's

Exports

POST/projects/:id/exportsreturns a job

Render the finished video with everything above. Charged at the export rate for the edited length (4K counts 2.5x). The export.ready webhook carries the link.

{ "aspect": "original | 9:16 | 16:9 | 1:1 | 4:5", "resolution": "720p | 1080p | 4k", "quality": "best | small", "burn_captions": true }
// job output
{ "render_job_id": "...", "url": "https://...", "expires_at": "...", "width": 1920, "height": 1080,
  "duration_seconds": 1451.8, "stock_credits": [ ... ], "notes": [] }
GET/projects/:id/exports

This project's exports, with fresh 24-hour download links.

Jobs

GET/jobs?status=&kind=&project_id=&limit=&before=

Your jobs, newest first.

GET/jobs/:id

One job: status, step, progress, output or error, credits charged.

POST/jobs/:id/cancel

Stop a queued or running job (an export it started is cancelled too) and return its credits.

Webhooks

POST/webhooks/test

Send a signed webhook.test event to your endpoint, to check your receiver.

Questions, or want a higher limit? Write to support@captik.in. We are quick to reply to business customers.