API Documentation
Programmatic access to Scriptube for transcript extraction at scale.
Authentication
All API requests require authentication using an API key. Get your key from API Keys in your dashboard.
Header Format
Include your API key in the X-API-Key header with every request:
X-API-Key: sk_live_your_api_key_here
Key Scopes
API keys can have different permission levels:
| Scope | Description |
|---|---|
full |
Read and write access. Can submit new transcription jobs. |
read |
Read-only access. Can view transcripts and usage, but cannot submit new jobs. |
Base URL
All API endpoints are relative to:
https://scriptube.me/api/v1
Endpoints
Submit YouTube URLs for transcript extraction. URLs are processed asynchronously.
Request Body
| Parameter | Type | Description |
|---|---|---|
| urls required | array | List of YouTube video URLs or playlist URLs to process |
Code Examples
curl -X POST https://scriptube.me/api/v1/transcripts \
-H "X-API-Key: sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"urls": [
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"https://www.youtube.com/watch?v=VIDEO_ID_2"
]
}'
import requests
API_KEY = "sk_live_your_api_key"
BASE_URL = "https://scriptube.me/api/v1"
response = requests.post(
f"{BASE_URL}/transcripts",
headers={
"X-API-Key": API_KEY,
"Content-Type": "application/json"
},
json={
"urls": [
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"https://www.youtube.com/watch?v=VIDEO_ID_2"
]
}
)
data = response.json()
batch_id = data["batch_id"]
print(f"Batch submitted: {batch_id}")
const API_KEY = "sk_live_your_api_key";
const BASE_URL = "https://scriptube.me/api/v1";
const response = await fetch(`${BASE_URL}/transcripts`, {
method: "POST",
headers: {
"X-API-Key": API_KEY,
"Content-Type": "application/json"
},
body: JSON.stringify({
urls: [
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"https://www.youtube.com/watch?v=VIDEO_ID_2"
]
})
});
const data = await response.json();
console.log(`Batch submitted: ${data.batch_id}`);
{
"batch_id": "550e8400-e29b-41d4-a716-446655440000",
"batch_number": 1,
"status": "pending",
"url_count": 2,
"message": "Batch submitted for processing. Poll GET /api/v1/transcripts/{batch_id} for results."
}
Get the status and results of a specific transcript batch.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
| batch_id required | uuid | The batch ID returned from POST /transcripts |
Code Examples
curl https://scriptube.me/api/v1/transcripts/550e8400-e29b-41d4-a716-446655440000 \ -H "X-API-Key: sk_live_your_api_key"
import requests
API_KEY = "sk_live_your_api_key"
batch_id = "550e8400-e29b-41d4-a716-446655440000"
response = requests.get(
f"https://scriptube.me/api/v1/transcripts/{batch_id}",
headers={"X-API-Key": API_KEY}
)
data = response.json()
print(f"Status: {data['status']}")
for item in data["items"]:
if item["status"] == "completed":
print(f"Video: {item['title']}")
print(f"Transcript: {item['transcript_text'][:200]}...")
const API_KEY = "sk_live_your_api_key";
const batchId = "550e8400-e29b-41d4-a716-446655440000";
const response = await fetch(
`https://scriptube.me/api/v1/transcripts/${batchId}`,
{ headers: { "X-API-Key": API_KEY } }
);
const data = await response.json();
console.log(`Status: ${data.status}`);
data.items.forEach(item => {
if (item.status === "completed") {
console.log(`Video: ${item.title}`);
console.log(`Transcript: ${item.transcript_text.slice(0, 200)}...`);
}
});
{
"batch_id": "550e8400-e29b-41d4-a716-446655440000",
"batch_number": 1,
"status": "completed",
"created_at": "2026-02-04T12:00:00Z",
"completed_at": "2026-02-04T12:01:30Z",
"items": [
{
"video_id": "dQw4w9WgXcQ",
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"title": "Rick Astley - Never Gonna Give You Up",
"channel": "Rick Astley",
"status": "completed",
"transcript_text": "We're no strangers to love...",
"transcript_language": "en",
"duration_seconds": 213,
"error": null
}
]
}
List all transcript batches for your account.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| limit | integer | Number of batches to return (1-100, default: 20) |
| offset | integer | Number of batches to skip (default: 0) |
Code Example (cURL)
curl "https://scriptube.me/api/v1/transcripts?limit=10&offset=0" \ -H "X-API-Key: sk_live_your_api_key"
Check your current usage and remaining quota.
Code Example (cURL)
curl https://scriptube.me/api/v1/usage \ -H "X-API-Key: sk_live_your_api_key"
{
"plan": "pro",
"credits_balance": 1850,
"credits_monthly": 2000,
"daily_used": 45,
"daily_limit": 600,
"daily_remaining": 555,
"total_processed": 8500
}
List all available subscription plans and their limits.
Code Example (cURL)
curl https://scriptube.me/api/v1/plans \ -H "X-API-Key: sk_live_your_api_key"
{
"plans": [
{
"slug": "free",
"title": "Free",
"description": "Get started for free",
"price_monthly_cents": 0,
"credits_monthly": 20,
"videos_per_day": 50,
"max_batch_size": 20,
"api_enabled": false
},
{
"slug": "pro",
"title": "Pro",
"description": "For power users",
"price_monthly_cents": 699,
"credits_monthly": 2000,
"videos_per_day": 600,
"max_batch_size": 300,
"api_enabled": true
}
]
}
Export batch transcripts in JSON, CSV, or plain text format.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
| batch_id required | uuid | The batch ID to export |
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| format | string | Export format: json, csv, or txt (default: json) |
Code Example (cURL)
curl "https://scriptube.me/api/v1/transcripts/550e8400-e29b-41d4-a716-446655440000/export?format=json" \ -H "X-API-Key: sk_live_your_api_key" \ -o transcripts.json
Health check endpoint. No authentication required.
Code Example (cURL)
curl https://scriptube.me/api/v1/health
{
"status": "ok",
"version": "1.0.0"
}
Rate Limits & Quotas
Plan Limits
Your API usage is subject to your subscription plan limits:
| Plan | Credits/Mo | Videos/Day | Max Batch | Concurrent | Webhooks | API |
|---|---|---|---|---|---|---|
| Free | 20 | 50 | 20 | 1 | β | β |
| Starter | 500 | 200 | 100 | 3 | β | β |
| Pro | 2,000 | 600 | 300 | 5 | 5 | β |
| Business | 6,500 | 2,000 | 1,000 | 10 | 10 | β |
| Unlimited | 20,000 | β | 4,000 | 999999 | 25 | β |
Credit Costs
Each action consumes credits from your monthly allocation:
| Action | Cost |
|---|---|
| YouTube transcript (captions) | 4 credits |
| AI transcription (ElevenLabs) | 10 credits/minute |
| Translation | 12 credits per 1K chars |
Credit Packs (Top-Up)
Need more credits? Purchase credit packs anytime. Credits never expire.
| Pack | Credits | Price | Per Credit |
|---|---|---|---|
| Micro Pack | 120 | $3.00 | $0.0250 |
| Standard Pack | 300 | $7.00 | $0.0233 |
| Bulk Pack | 700 | $15.00 | $0.0214 |
| Max Pack | 1,500 | $30.00 | $0.0200 |
Purchase via dashboard or POST /api/billing/credits/checkout
Rate Limiting
API requests are also subject to per-minute rate limiting to ensure service stability:
- General API requests: 100 requests/minute
- Batch submission: Based on plan limits
Checking Your Usage
Use the GET /api/v1/usage endpoint to check your current usage and remaining quota programmatically.
Error Handling
The API uses standard HTTP status codes to indicate success or failure:
| Code | Description |
|---|---|
| 200 | Success - Request completed successfully |
| 202 | Accepted - Batch submitted for processing |
| 401 | Unauthorized - Missing or invalid API key |
| 403 | Forbidden - API key lacks required permissions or email not verified |
| 404 | Not Found - Resource doesn't exist |
| 422 | Unprocessable Entity - Invalid request body or exceeded batch size limit |
| 429 | Too Many Requests - Rate limit or quota exceeded |
| 500 | Internal Server Error - Something went wrong on our end |
Error Response Format
Error responses include a detail field with a human-readable message:
{
"detail": "Daily limit reached. You have 0 videos remaining today."
}
Bring Your Own Key (BYOK)
Use your own API keys for third-party services to get better rates, higher limits, or more control over your usage.
Supported Services
| Service | Key Type | Used For |
|---|---|---|
| ElevenLabs | API Key | Audio transcription when captions aren't available |
| OpenAI | API Key | Whisper transcription (coming soon) |
| YouTube | Data API Key | Playlist expansion, video metadata |
How BYOK Works
- Add your key β Go to Settings β API Keys and add your service API key
- Keys are encrypted β All keys are encrypted with AES-256 before storage
- Activate the key β Select which key to use (you can store multiple per service)
- Automatic usage β When processing videos, your key is used instead of our shared pool
Benefits
- No credit cost β BYOK requests don't consume your Scriptube credits for that service
- Higher limits β Use your own quota instead of shared limits
- Better rates β If you have a discounted API plan, you keep those savings
- Full control β Monitor usage directly in the service's dashboard
Managing BYOK Keys via API
List all your stored API keys (key values are masked).
curl -X GET https://scriptube.me/api/v1/byok \ -H "X-API-Key: sk_live_your_api_key"
{
"keys": [
{
"id": "byok_abc123",
"service": "elevenlabs",
"name": "My ElevenLabs Key",
"masked_key": "sk_...x7c",
"is_active": true,
"created_at": "2024-01-15T10:30:00Z"
}
]
}
Add a new API key for a supported service.
| Parameter | Type | Description |
|---|---|---|
| service required | string | Service name: elevenlabs, openai, or youtube |
| api_key required | string | Your API key for the service |
| name | string | Optional friendly name for this key |
curl -X POST https://scriptube.me/api/v1/byok \
-H "X-API-Key: sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"service": "elevenlabs",
"api_key": "sk_your_elevenlabs_key",
"name": "Production Key"
}'
Delete a stored API key.
curl -X DELETE https://scriptube.me/api/v1/byok/byok_abc123 \ -H "X-API-Key: sk_live_your_api_key"
Activate a key to use it for processing. Only one key per service can be active.
curl -X POST https://scriptube.me/api/v1/byok/byok_abc123/activate \ -H "X-API-Key: sk_live_your_api_key"
Integrations
Connect Scriptube to your favorite automation tools for seamless workflow integration.
Zapier Integration
Automate transcript extraction with Zapier's 5,000+ app connections.
Available Actions
| Action | Description |
|---|---|
| Submit URLs | Submit YouTube URLs for transcript extraction |
| Get Batch Status | Check the status of a batch job |
| Get Transcripts | Retrieve completed transcripts |
| Check Usage | Get current usage stats and remaining quota |
Example Zap: YouTube to Google Docs
- Trigger: New video in YouTube playlist
- Action 1: Scriptube β Submit URL
- Action 2: Delay β Wait 2 minutes
- Action 3: Scriptube β Get Transcripts
- Action 4: Google Docs β Create document with transcript
Zapier Setup
1. In Zapier, search for "Webhooks by Zapier"
2. Choose "Custom Request" action
3. Configure:
- Method: POST
- URL: https://scriptube.me/api/v1/transcripts
- Headers:
X-API-Key: your_api_key
Content-Type: application/json
- Body: {"urls": ["{{youtube_url}}"]}
4. Test and enable your Zap
n8n Integration
Self-hosted workflow automation with full API access.
HTTP Request Node Setup
{
"method": "POST",
"url": "https://scriptube.me/api/v1/transcripts",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"headers": {
"X-API-Key": "={{ $credentials.apiKey }}"
},
"body": {
"urls": ["{{ $json.youtube_url }}"]
}
}
{
"method": "GET",
"url": "https://scriptube.me/api/v1/batches/{{ $json.batch_id }}",
"headers": {
"X-API-Key": "={{ $credentials.apiKey }}"
}
}
{
"method": "GET",
"url": "https://scriptube.me/api/v1/batches/{{ $json.batch_id }}/transcripts",
"headers": {
"X-API-Key": "={{ $credentials.apiKey }}"
}
}
Example n8n Workflow
βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ β Trigger βββββΆβ Submit to βββββΆβ Wait & βββββΆβ Save to β β (Schedule/ β β Scriptube β β Poll β β Notion/ β β Webhook) β β β β Status β β Sheets β βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ
Webhooks
Receive real-time notifications when your transcripts are ready. Perfect for n8n, Zapier, or custom integrations.
Webhook Limits by Plan
| Plan | Webhooks | Rate Limit |
|---|---|---|
| Free | β | β |
| Starter | β | β |
| Pro | 5 | 30 deliveries/min |
| Business | 10 | 120 deliveries/min |
| Unlimited | 25 | 300 deliveries/min |
Register a Webhook
/api/v1/webhooks
{
"url": "https://your-n8n-instance.com/webhook/abc123",
"events": ["batch.completed", "batch.failed"],
"secret": "your-hmac-secret" // Optional: for signature verification
}
List Your Webhooks
/api/v1/webhooks
Delete a Webhook
/api/v1/webhooks/{webhook_id}
Test a Webhook
/api/v1/webhooks/{webhook_id}/test
Available Events
| Event | Description |
|---|---|
batch.created |
Fired when a new batch is created |
batch.started |
Fired when batch processing begins |
batch.completed |
Fired when all items in a batch are processed |
batch.failed |
Fired when a batch fails completely |
item.completed |
Fired when a single video transcript is ready |
item.failed |
Fired when a single video fails to process |
transcript.ready |
Fired when transcript text is available |
credits.low |
Fired when credits drop below 20% of plan allocation |
credits.depleted |
Fired when credits reach zero |
subscription.updated |
Fired when plan changes (upgrade/downgrade) |
Webhook Payload Format
{
"event": "batch.completed",
"timestamp": "2024-01-15T10:35:00Z",
"data": {
"batch_id": "batch_abc123",
"batch_number": 42,
"status": "completed",
"item_count": 5,
"completed_count": 5,
"failed_count": 0
}
}
Signature Verification (HMAC-SHA256)
If you provide a secret when registering, we'll sign payloads with HMAC-SHA256.
Verify the X-Webhook-Signature header:
import hmac, hashlib
def verify_signature(payload, signature, secret):
expected = hmac.new(
secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
Need Help?
If you have questions or run into issues, we're here to help.