Video Transcription API Documentation
Transcribe social media videos programmatically with a single API call.
Last updated: February 2026
Base URL
https://soscripted.com/api/publicAuthentication
All API requests require a Bearer token in the Authorization header. You can generate an API key from your API Keys dashboard.
Authorization: Bearer sk_your_api_key_herePOST /transcribe
Submit a video URL for transcription. The API will process the video and return the transcript. Each request costs 1 credit.
Request Body
| Field | Type | Description |
|---|---|---|
| url | string | Video URL from a supported platform (YouTube, TikTok, Instagram, Facebook, Twitter/X, LinkedIn, Pinterest) |
POST /api/public/transcribe HTTP/1.1
Host: soscripted.com
Authorization: Bearer sk_your_api_key_here
Content-Type: application/json
{
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}Response (JSON)
By default, the API blocks until transcription completes and returns a JSON response.
{
"ok": true,
"caption": {
"text": "Full transcript text here...",
"segments": [
{ "start": 0.0, "end": 2.5, "text": "Hello world" },
{ "start": 2.5, "end": 5.0, "text": "This is a transcript" }
]
}
}{
"error": "Error description"
}Response (SSE Streaming)
To receive real-time progress updates, include Accept: text/event-stream in your request headers.
event: progress
data: {"stage":"downloading","pct":10}
event: progress
data: {"stage":"transcribing","pct":50}
event: final
data: {"ok":true,"caption":{"text":"...","segments":[...]}}
event: done
data: {"ok":true}Status Codes
| Code | Description |
|---|---|
| 200 | Transcription completed successfully |
| 400 | Bad request (missing URL or unsupported platform) |
| 401 | Unauthorized (missing or invalid API key) |
| 402 | Insufficient credits |
| 500 | Transcription failed |
| 504 | Timeout (transcription took too long) |
Library API
Access your saved transcripts programmatically. Save transcripts from the dashboard, then retrieve them via the API for your AI agents, knowledge bases, or workflows.
GET /library
List saved transcripts with search, pagination, and collection filtering.
| Parameter | Type | Description |
|---|---|---|
| search | string | Full-text search across titles and content |
| collectionId | string | Filter by collection |
| page | number | Page number (default: 1) |
| limit | number | Items per page (default: 20, max: 100) |
| format | string | "summary" (default) or "full" (includes segments) |
curl "https://soscripted.com/api/public/library?search=marketing&limit=10" \
-H "Authorization: Bearer sk_your_api_key_here"GET /library/:id
Get a single saved transcript. Use the format query parameter to get different output formats.
| Format | Description |
|---|---|
| (default) | JSON with segments, timestamps, and plain text |
| txt | Plain text (all segments joined) |
| srt | SRT subtitle format |
| vtt | WebVTT subtitle format |
| json | Structured JSON with parsed timestamps |
| timestamps | Text with [MM:SS] prefixes |
# Get full JSON
curl "https://soscripted.com/api/public/library/clx123abc" \
-H "Authorization: Bearer sk_your_api_key_here"
# Get plain text only
curl "https://soscripted.com/api/public/library/clx123abc?format=txt" \
-H "Authorization: Bearer sk_your_api_key_here"
# Get SRT subtitles
curl "https://soscripted.com/api/public/library/clx123abc?format=srt" \
-H "Authorization: Bearer sk_your_api_key_here"Batch Import API
Import entire channels, playlists, or profiles in a single request. Videos are transcribed in the background and credits are reserved upfront.
POST /batch-import
Start a batch import from a channel, playlist, or profile URL. Credits are reserved based on the estimated number of videos.
| Field | Type | Description |
|---|---|---|
| url | string | Channel, playlist, or profile URL |
| collectionId | string? | Save transcripts to this collection |
| maxVideos | number? | Limit the number of videos to import |
| autoSave | boolean? | Automatically save transcripts to library (default: true) |
POST /api/public/batch-import HTTP/1.1
Host: soscripted.com
Authorization: Bearer sk_your_api_key_here
Content-Type: application/json
{
"url": "https://www.youtube.com/@MrBeast",
"collectionId": "clx456def",
"maxVideos": 50,
"autoSave": true
}{
"ok": true,
"data": {
"id": "batch_abc123",
"sourceType": "youtube_channel",
"sourceName": "MrBeast",
"estimatedVideos": 50,
"creditsReserved": 50,
"status": "processing",
"createdAt": "2026-02-24T12:00:00Z"
}
}GET /batch-import
List your batch imports with pagination.
| Parameter | Type | Description |
|---|---|---|
| page | number | Page number (default: 1) |
| limit | number | Items per page (default: 20, max: 100) |
curl "https://soscripted.com/api/public/batch-import?page=1&limit=20" \
-H "Authorization: Bearer sk_your_api_key_here"GET /batch-import/:id
Get details of a specific batch import, including individual item statuses.
curl "https://soscripted.com/api/public/batch-import/batch_abc123" \
-H "Authorization: Bearer sk_your_api_key_here"{
"ok": true,
"data": {
"id": "batch_abc123",
"sourceType": "youtube_channel",
"sourceName": "MrBeast",
"estimatedVideos": 50,
"completedVideos": 32,
"failedVideos": 1,
"creditsReserved": 50,
"creditsUsed": 32,
"status": "processing",
"items": [
{
"id": "item_001",
"videoUrl": "https://youtube.com/watch?v=abc",
"title": "Video Title",
"status": "completed",
"transcriptId": "clx789ghi"
},
{
"id": "item_002",
"videoUrl": "https://youtube.com/watch?v=def",
"title": "Another Video",
"status": "processing",
"transcriptId": null
}
]
}
}Webhooks API
Receive real-time notifications when events occur in your account. Register webhook endpoints and SoScripted will send HTTP POST requests with event payloads to your URL.
POST /webhooks
Register a new webhook endpoint. The response includes the full signing secret -- store it securely, as it will not be shown again.
| Field | Type | Description |
|---|---|---|
| url | string | HTTPS endpoint URL to receive events |
| events | string[] | Event types to subscribe to |
| secret | string? | Custom signing secret (auto-generated if omitted) |
Available Events
| Event | Description |
|---|---|
| transcript.completed | A transcription finished successfully |
| transcript.failed | A transcription failed |
| batch.completed | A batch import finished (all items processed) |
| monitor.new_video | A monitored channel published a new video |
POST /api/public/webhooks HTTP/1.1
Host: soscripted.com
Authorization: Bearer sk_your_api_key_here
Content-Type: application/json
{
"url": "https://your-app.com/webhooks/soscripted",
"events": ["transcript.completed", "batch.completed"]
}{
"ok": true,
"webhook": {
"id": "wh_abc123",
"url": "https://your-app.com/webhooks/soscripted",
"events": ["transcript.completed", "batch.completed"],
"secret": "whsec_a1b2c3d4e5f6...",
"active": true,
"createdAt": "2026-02-24T12:00:00Z"
}
}GET /webhooks
List all registered webhooks for your account.
curl "https://soscripted.com/api/public/webhooks" \
-H "Authorization: Bearer sk_your_api_key_here"{
"ok": true,
"webhooks": [
{
"id": "wh_abc123",
"url": "https://your-app.com/webhooks/soscripted",
"events": ["transcript.completed", "batch.completed"],
"active": true,
"createdAt": "2026-02-24T12:00:00Z"
}
]
}PATCH /webhooks/:id
Update a webhook endpoint. All fields are optional -- only include the fields you want to change.
| Field | Type | Description |
|---|---|---|
| url | string? | New endpoint URL |
| events | string[]? | Replace subscribed events |
| active | boolean? | Enable or disable the webhook |
curl -X PATCH "https://soscripted.com/api/public/webhooks/wh_abc123" \
-H "Authorization: Bearer sk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"active": false}'DELETE /webhooks/:id
Permanently delete a webhook endpoint.
curl -X DELETE "https://soscripted.com/api/public/webhooks/wh_abc123" \
-H "Authorization: Bearer sk_your_api_key_here"POST /webhooks/:id/test
Send a test event to your webhook endpoint to verify it is reachable and correctly configured.
curl -X POST "https://soscripted.com/api/public/webhooks/wh_abc123/test" \
-H "Authorization: Bearer sk_your_api_key_here"{
"ok": true,
"deliveryId": "del_xyz789",
"statusCode": 200
}GET /webhooks/:id/deliveries
View recent delivery attempts for a webhook, including response status codes and timestamps. Useful for debugging failed deliveries.
| Parameter | Type | Description |
|---|---|---|
| page | number | Page number (default: 1) |
| limit | number | Items per page (default: 20, max: 100) |
curl "https://soscripted.com/api/public/webhooks/wh_abc123/deliveries?page=1&limit=20" \
-H "Authorization: Bearer sk_your_api_key_here"{
"ok": true,
"deliveries": [
{
"id": "del_xyz789",
"event": "transcript.completed",
"statusCode": 200,
"success": true,
"attemptedAt": "2026-02-24T12:05:00Z"
},
{
"id": "del_xyz790",
"event": "batch.completed",
"statusCode": 500,
"success": false,
"attemptedAt": "2026-02-24T12:03:00Z",
"nextRetryAt": "2026-02-24T12:08:00Z"
}
],
"pagination": { "page": 1, "limit": 20, "total": 2 }
}Channel Monitors API
Automatically watch channels for new videos and transcribe them as they are published. Set a monthly credit budget to control costs.
POST /monitors
Create a new channel monitor. The monitor will periodically check the channel for new videos and auto-transcribe them.
| Field | Type | Description |
|---|---|---|
| channelUrl | string | Channel or profile URL to monitor |
| collectionId | string? | Save new transcripts to this collection |
| checkInterval | string? | How often to check: "hourly", "daily" (default), or "weekly" |
| videoTypes | string[]? | Filter by type: "video", "short", "live", "reel", "story" |
| monthlyBudget | number? | Max credits to spend per month on this monitor |
POST /api/public/monitors HTTP/1.1
Host: soscripted.com
Authorization: Bearer sk_your_api_key_here
Content-Type: application/json
{
"channelUrl": "https://www.youtube.com/@mkbhd",
"collectionId": "clx456def",
"checkInterval": "daily",
"videoTypes": ["video"],
"monthlyBudget": 30
}{
"ok": true,
"data": {
"id": "mon_abc123",
"channelUrl": "https://www.youtube.com/@mkbhd",
"channelName": "MKBHD",
"platform": "youtube",
"collectionId": "clx456def",
"checkInterval": "daily",
"videoTypes": ["video"],
"monthlyBudget": 30,
"creditsUsedThisMonth": 0,
"autoTranscribe": true,
"active": true,
"lastCheckedAt": null,
"createdAt": "2026-02-24T12:00:00Z"
}
}GET /monitors
List all your channel monitors with pagination.
| Parameter | Type | Description |
|---|---|---|
| page | number | Page number (default: 1) |
| limit | number | Items per page (default: 20, max: 100) |
curl "https://soscripted.com/api/public/monitors?page=1&limit=20" \
-H "Authorization: Bearer sk_your_api_key_here"{
"ok": true,
"data": [
{
"id": "mon_abc123",
"channelUrl": "https://www.youtube.com/@mkbhd",
"channelName": "MKBHD",
"platform": "youtube",
"checkInterval": "daily",
"monthlyBudget": 30,
"creditsUsedThisMonth": 12,
"active": true,
"lastCheckedAt": "2026-02-24T06:00:00Z"
}
],
"pagination": { "page": 1, "limit": 20, "total": 1 }
}PATCH /monitors/:id
Update a channel monitor. All fields are optional -- only include the fields you want to change.
| Field | Type | Description |
|---|---|---|
| active | boolean? | Enable or pause the monitor |
| checkInterval | string? | "hourly", "daily", or "weekly" |
| collectionId | string? | Change the target collection |
| videoTypes | string[]? | Update the video type filter |
| monthlyBudget | number? | Update the monthly credit budget |
| autoTranscribe | boolean? | Auto-transcribe new videos or just notify |
curl -X PATCH "https://soscripted.com/api/public/monitors/mon_abc123" \
-H "Authorization: Bearer sk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"checkInterval": "hourly", "monthlyBudget": 50}'DELETE /monitors/:id
Permanently delete a channel monitor. Previously transcribed videos are not affected.
curl -X DELETE "https://soscripted.com/api/public/monitors/mon_abc123" \
-H "Authorization: Bearer sk_your_api_key_here"Webhook Payloads & Verification
All webhook deliveries include a signature header for verification. The payload is signed with your webhook secret using HMAC-SHA256.
Signature Verification
Each delivery includes an X-SoScripted-Signature header containing the HMAC-SHA256 hex digest of the raw request body.
import crypto from "crypto";
function verifyWebhook(body, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(body, "utf-8")
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// In your webhook handler:
app.post("/webhooks/soscripted", (req, res) => {
const signature = req.headers["x-soscripted-signature"];
const isValid = verifyWebhook(req.rawBody, signature, WEBHOOK_SECRET);
if (!isValid) {
return res.status(401).json({ error: "Invalid signature" });
}
const event = req.body;
console.log("Event type:", event.event);
// Handle the event...
res.status(200).json({ received: true });
});import hmac
import hashlib
def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode("utf-8"),
body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
# In your webhook handler (Flask example):
@app.route("/webhooks/soscripted", methods=["POST"])
def handle_webhook():
signature = request.headers.get("X-SoScripted-Signature", "")
if not verify_webhook(request.data, signature, WEBHOOK_SECRET):
return {"error": "Invalid signature"}, 401
event = request.json
print("Event type:", event["event"])
# Handle the event...
return {"received": True}, 200transcript.completed
Fired when a transcription completes successfully, whether from a single request, batch import, or channel monitor.
{
"event": "transcript.completed",
"timestamp": "2026-02-24T12:05:00Z",
"data": {
"jobId": "job_abc123",
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"title": "Video Title",
"platform": "youtube",
"transcriptId": "clx789ghi",
"duration": 245,
"wordCount": 1830,
"source": "api",
"batchId": null,
"monitorId": null
}
}transcript.failed
Fired when a transcription fails after all retry attempts are exhausted.
{
"event": "transcript.failed",
"timestamp": "2026-02-24T12:05:00Z",
"data": {
"jobId": "job_def456",
"url": "https://www.youtube.com/watch?v=invalid",
"platform": "youtube",
"error": "Video not found or is private",
"source": "api",
"batchId": null,
"monitorId": null
}
}batch.completed
Fired when all items in a batch import have been processed (completed or failed).
{
"event": "batch.completed",
"timestamp": "2026-02-24T14:30:00Z",
"data": {
"batchId": "batch_abc123",
"sourceType": "youtube_channel",
"sourceName": "MrBeast",
"totalVideos": 50,
"completedVideos": 48,
"failedVideos": 2,
"creditsUsed": 48
}
}monitor.new_video
Fired when a monitored channel publishes a new video. If autoTranscribe is enabled, a transcription job is started automatically.
{
"event": "monitor.new_video",
"timestamp": "2026-02-24T15:00:00Z",
"data": {
"monitorId": "mon_abc123",
"channelName": "MKBHD",
"platform": "youtube",
"videoUrl": "https://www.youtube.com/watch?v=newvideo",
"videoTitle": "New Video Title",
"publishedAt": "2026-02-24T14:55:00Z",
"autoTranscribe": true,
"jobId": "job_ghi789"
}
}Code Examples
JavaScript (JSON response)
const response = await fetch("https://soscripted.com/api/public/transcribe", {
method: "POST",
headers: {
"Authorization": "Bearer sk_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
}),
});
const data = await response.json();
if (data.ok) {
console.log("Transcript:", data.caption.text);
} else {
console.error("Error:", data.error);
}JavaScript (SSE streaming)
const response = await fetch("https://soscripted.com/api/public/transcribe", {
method: "POST",
headers: {
"Authorization": "Bearer sk_your_api_key_here",
"Content-Type": "application/json",
"Accept": "text/event-stream",
},
body: JSON.stringify({
url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
}),
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop() || "";
for (const line of lines) {
if (line.startsWith("data: ")) {
const data = JSON.parse(line.slice(6));
console.log("Event:", data);
}
}
}Python (JSON response)
import requests
response = requests.post(
"https://soscripted.com/api/public/transcribe",
headers={
"Authorization": "Bearer sk_your_api_key_here",
"Content-Type": "application/json",
},
json={"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"},
timeout=600,
)
data = response.json()
if data.get("ok"):
print("Transcript:", data["caption"]["text"])
else:
print("Error:", data.get("error"))Python (SSE streaming)
import requests
import json
response = requests.post(
"https://soscripted.com/api/public/transcribe",
headers={
"Authorization": "Bearer sk_your_api_key_here",
"Content-Type": "application/json",
"Accept": "text/event-stream",
},
json={"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"},
stream=True,
)
for line in response.iter_lines(decode_unicode=True):
if line.startswith("data: "):
data = json.loads(line[6:])
print("Event:", data)
if "caption" in data:
print("Transcript:", data["caption"]["text"])Supported Platforms
Related Resources
Start building with the API
Free account includes 3 credits. Generate an API key from your dashboard and start transcribing in seconds.