REST API

Programmatic access to Cap via the REST API

The Cap Developer API provides programmatic access to videos created through your developer apps. It is designed for server-to-server integrations, automated workflows, and building custom recording experiences on top of Cap.

There are two APIs:

  • REST API (/api/developer/v1) -- Server-side management of videos and usage, authenticated with secret keys (csk_).
  • SDK API (/api/developer/sdk/v1) -- Client-side video creation and uploads, authenticated with public keys (cpk_).

Authentication

Getting Your API Keys

API keys are managed through the Developer dashboard, not the general Settings page.

  1. Go to Cap.so/dashboard/developers.
  2. Click Create App and give it a name and environment (development or production).
  3. Two keys are generated for each app:
    • Public key (cpk_...) -- Safe to use in client-side code. Used with the SDK API.
    • Secret key (csk_...) -- Must be kept private. Used with the REST API.
  4. Store both keys securely. You can regenerate them from the app settings, which revokes the previous pair.

Using Your Keys

Include the appropriate key in the Authorization header as a Bearer token:

Authorization: Bearer csk_your_secret_key_here

For the SDK API, use the public key instead:

Authorization: Bearer cpk_your_public_key_here

Keep your secret key private. Never expose it in client-side code, commit it to version control, or share it publicly.

Base URL

REST API (secret key):

https://cap.so/api/developer/v1

SDK API (public key):

https://cap.so/api/developer/sdk/v1

If you are self-hosting Cap, replace Cap.so with your custom domain.

Error Handling

All error responses return a JSON object with an error string:

{
  "error": "Video not found"
}

Standard HTTP status codes are used:

Status CodeDescription
200Success
400Bad request -- missing or invalid parameters
401Unauthorized -- invalid, missing, or revoked API key
402Payment required -- insufficient credits
403Forbidden -- origin not allowed (SDK API in production)
404Not found -- the requested resource does not exist
500Internal server error

Pagination

List endpoints support pagination via query parameters:

ParameterTypeDefaultMaxDescription
limitinteger50100Number of items to return
offsetinteger0--Number of items to skip

The response does not include pagination metadata. To paginate, increment offset by limit until the returned array has fewer items than limit.


REST API Endpoints

All REST API endpoints require a secret key (csk_) in the Authorization header.

List Videos

Retrieve videos created by your app.

GET /api/developer/v1/videos

Query parameters:

ParameterTypeRequiredDescription
userIdstringNoFilter by external user ID
limitintegerNoNumber of results (default 50, max 100)
offsetintegerNoNumber of results to skip (default 0)

Example request:

curl https://cap.so/api/developer/v1/videos?limit=10 \
  -H "Authorization: Bearer csk_your_secret_key_here"

Example response:

{
  "data": [
    {
      "id": "abc123def456",
      "appId": "app_789",
      "externalUserId": "user_42",
      "name": "Product Demo",
      "duration": 124.5,
      "width": 1920,
      "height": 1080,
      "fps": 30,
      "s3Key": "developer/app_789/abc123def456/result.mp4",
      "transcriptionStatus": "COMPLETE",
      "metadata": null,
      "deletedAt": null,
      "createdAt": "2025-06-15T10:30:00.000Z",
      "updatedAt": "2025-06-15T10:32:00.000Z"
    }
  ]
}

Get Video

Retrieve a single video by ID.

GET /api/developer/v1/videos/:id

Path parameters:

ParameterTypeDescription
idstringThe video ID

Example request:

curl https://cap.so/api/developer/v1/videos/abc123def456 \
  -H "Authorization: Bearer csk_your_secret_key_here"

Example response:

{
  "data": {
    "id": "abc123def456",
    "appId": "app_789",
    "externalUserId": "user_42",
    "name": "Product Demo",
    "duration": 124.5,
    "width": 1920,
    "height": 1080,
    "fps": 30,
    "s3Key": "developer/app_789/abc123def456/result.mp4",
    "transcriptionStatus": "COMPLETE",
    "metadata": null,
    "deletedAt": null,
    "createdAt": "2025-06-15T10:30:00.000Z",
    "updatedAt": "2025-06-15T10:32:00.000Z"
  }
}

Get Video Status

Check whether a video is fully processed and ready for playback.

GET /api/developer/v1/videos/:id/status

Path parameters:

ParameterTypeDescription
idstringThe video ID

Example request:

curl https://cap.so/api/developer/v1/videos/abc123def456/status \
  -H "Authorization: Bearer csk_your_secret_key_here"

Example response:

{
  "data": {
    "id": "abc123def456",
    "duration": 124.5,
    "width": 1920,
    "height": 1080,
    "transcriptionStatus": "COMPLETE",
    "ready": true
  }
}

The ready field is true when both duration and width are present, indicating the video has been fully uploaded and processed.

The transcriptionStatus field can be one of: PROCESSING, COMPLETE, ERROR, SKIPPED, or NO_AUDIO.

Delete Video

Soft-delete a video. The video is marked as deleted and excluded from future queries.

DELETE /api/developer/v1/videos/:id

Path parameters:

ParameterTypeDescription
idstringThe video ID

Example request:

curl -X DELETE https://cap.so/api/developer/v1/videos/abc123def456 \
  -H "Authorization: Bearer csk_your_secret_key_here"

Example response:

{
  "success": true
}

Get Usage

Retrieve your app's credit balance and aggregate video statistics.

GET /api/developer/v1/usage

Example request:

curl https://cap.so/api/developer/v1/usage \
  -H "Authorization: Bearer csk_your_secret_key_here"

Example response:

{
  "data": {
    "balanceMicroCredits": 500000,
    "balanceDollars": "5.00",
    "totalVideos": 23,
    "totalDurationMinutes": 87.5
  }
}

Credits are tracked in micro-credits (1 dollar = 100,000 micro-credits). Video creation costs 5,000 micro-credits per minute of video duration.


SDK API Endpoints

The SDK API is designed for client-side use in browsers and apps. All SDK API endpoints require a public key (cpk_) in the Authorization header.

For production apps, the Origin header must match one of the allowed domains configured in your app settings. Development apps skip origin validation.

Create Video

Create a new video record and get URLs for sharing and embedding.

POST /api/developer/sdk/v1/videos/create

Request body (JSON):

FieldTypeRequiredDescription
namestringNoVideo name (defaults to "Untitled")
userIdstringNoYour external user ID for filtering
metadataobjectNoArbitrary metadata to store with the video

Example request:

curl -X POST https://cap.so/api/developer/sdk/v1/videos/create \
  -H "Authorization: Bearer cpk_your_public_key_here" \
  -H "Content-Type: application/json" \
  -d '{"name": "User Recording", "userId": "user_42"}'

Example response:

{
  "videoId": "abc123def456",
  "s3Key": "developer/app_789/abc123def456/result.mp4",
  "shareUrl": "https://cap.so/dev/abc123def456",
  "embedUrl": "https://cap.so/embed/abc123def456?sdk=1"
}

Returns a 402 error if the app has insufficient credits (minimum 5,000 micro-credits required).

Multipart Upload

After creating a video, use multipart upload to upload the video file. This is a multi-step process.

Initiate Upload

POST /api/developer/sdk/v1/upload/multipart/initiate

Request body (JSON):

FieldTypeRequiredDescription
videoIdstringYesThe video ID from the create step
contentTypestringNoMIME type (defaults to "video/mp4")

Example response:

{
  "uploadId": "multipart-upload-id"
}

Get Presigned Part URL

Get a presigned URL to upload a single part.

POST /api/developer/sdk/v1/upload/multipart/presign-part

Request body (JSON):

FieldTypeRequiredDescription
videoIdstringYesThe video ID
uploadIdstringYesThe upload ID from the initiate step
partNumbernumberYesPart number (starting from 1)

Example response:

{
  "presignedUrl": "https://s3.amazonaws.com/..."
}

Upload the part data by sending a PUT request to the returned presignedUrl. Save the ETag header from the response for the completion step.

Complete Upload

Finalize the upload after all parts have been uploaded.

POST /api/developer/sdk/v1/upload/multipart/complete

Request body (JSON):

FieldTypeRequiredDescription
videoIdstringYesThe video ID
uploadIdstringYesThe upload ID
partsarrayYesArray of uploaded parts
parts[].partNumbernumberYesThe part number
parts[].etagstringYesThe ETag returned when the part was uploaded
parts[].sizenumberYesThe size of the part in bytes
durationInSecsnumberNoVideo duration in seconds (used for billing)
widthnumberNoVideo width in pixels
heightnumberNoVideo height in pixels
fpsnumberNoVideo frame rate

Example response:

{
  "success": true
}

When durationInSecs is provided, credits are debited at 5,000 micro-credits per minute.

Abort Upload

Cancel an in-progress multipart upload.

POST /api/developer/sdk/v1/upload/multipart/abort

Request body (JSON):

FieldTypeRequiredDescription
videoIdstringYesThe video ID
uploadIdstringYesThe upload ID to abort

Example response:

{
  "success": true
}

SDKs

Cap provides official SDK packages to simplify integration:

  • @cap/sdk-recorder -- Recording SDK for capturing video in web applications. Includes React bindings.
  • @cap/sdk-embed -- Embedding SDK for displaying Cap videos. Available for React and vanilla JavaScript.

Video Object Reference

The full video object returned by list and get endpoints:

FieldTypeDescription
idstringUnique video identifier
appIdstringThe developer app that owns this video
externalUserIdstring | nullYour external user identifier
namestringVideo display name
durationnumber | nullDuration in seconds (null until upload completes)
widthnumber | nullVideo width in pixels (null until upload completes)
heightnumber | nullVideo height in pixels (null until upload completes)
fpsnumber | nullFrames per second (null until upload completes)
s3Keystring | nullStorage key for the video file
transcriptionStatusstring | nullOne of: PROCESSING, COMPLETE, ERROR, SKIPPED, NO_AUDIO
metadataobject | nullCustom metadata provided during creation
deletedAtstring | nullDeletion timestamp (null for active videos)
createdAtstringCreation timestamp (ISO 8601)
updatedAtstringLast update timestamp (ISO 8601)

Best Practices

  • Use secret keys server-side only. The csk_ key should never appear in client-side code. Use cpk_ public keys for browser integrations.
  • Poll video status after upload. After completing a multipart upload, poll GET /videos/:id/status until ready is true before displaying the video.
  • Store your keys securely. Use environment variables or a secrets manager.
  • Set up allowed domains for production. Production apps require an Origin header matching a configured domain. Add your domains in the Developer dashboard.
  • Monitor your credit balance. Use the usage endpoint to track remaining credits and set up auto top-up in the Developer dashboard to avoid service interruptions.
  • Paginate large result sets. Use limit and offset to retrieve videos in batches. When the returned array length is less than limit, you have reached the end.