API Responses
Understanding VocaFuse API response formats, HTTP status codes, pagination, and filtering.
Response Format
Success Response
Successful responses return the requested data directly:
{
"id": "606cf8f5-b294-4b9c-ad0e-3afeb99c6804",
"tenant_id": "63f8fa32-0740-4263-9bed-578156b3526b",
"status": "completed",
"created_at": "2025-10-06T17:33:31",
"updated_at": "2025-10-06T17:33:45",
"uri": "/v1/recordings/606cf8f5-b294-4b9c-ad0e-3afeb99c6804"
}
For list endpoints, the response includes pagination metadata:
{
"recordings": [...],
"uri": "/v1/recordings?page=0&limit=10",
"first_page_uri": "/v1/recordings?page=0&limit=10",
"next_page_uri": "/v1/recordings?page=1&limit=10",
"previous_page_uri": null,
"page": 0,
"page_size": 10,
"total": 25
}
Error Response
Error responses include a structured error object:
{
"error": {
"code": 2001,
"message": "user_id is required in request body",
"type": "ValidationError",
"details": {
"field": "user_id",
"reason": "missing required field"
}
}
}
See the complete Error Reference for all error codes and handling strategies.
HTTP Status Codes
VocaFuse uses standard HTTP status codes to indicate request success or failure:
Success Codes (2xx)
| Status | Description |
|---|---|
| 200 OK | Request succeeded, response body contains data |
| 201 Created | Resource created successfully |
| 204 No Content | Request succeeded, no response body (typically for DELETE) |
Client Error Codes (4xx)
| Status | Description |
|---|---|
| 400 Bad Request | Invalid parameters or malformed request |
| 401 Unauthorized | Invalid or missing API credentials |
| 403 Forbidden | Valid credentials but insufficient permissions |
| 404 Not Found | Resource doesn't exist or not accessible |
| 413 Payload Too Large | File size exceeds maximum limit (25MB) |
| 429 Too Many Requests | Rate limit exceeded (see Rate Limits) |
Server Error Codes (5xx)
| Status | Description |
|---|---|
| 500 Internal Server Error | Unexpected server error |
| 503 Service Unavailable | Service temporarily unavailable |
Pagination
All list endpoints (Voice Notes, API Keys, Webhooks) return paginated results to improve performance and manageability.
Query Parameters
Control pagination using these query parameters:
| Parameter | Type | Default | Maximum | Description |
|---|---|---|---|---|
page | integer | 0 | - | Page number (0-indexed) |
limit | integer | 50 | 100 | Number of results per page |
Example:
# Get page 2 with 25 results per page
curl "https://api.vocafuse.com/v1/recordings?page=1&limit=25" \
-H "X-VocaFuse-API-Key: sk_live_..." \
-H "X-VocaFuse-API-Secret: ..."
Response Metadata
Every paginated response includes these metadata fields:
| Field | Type | Description |
|---|---|---|
page | integer | Current page number (0-indexed) |
page_size | integer | Number of results in this response |
total | integer | Total number of resources matching the query |
uri | string | URI for the current page |
first_page_uri | string | URI for the first page |
next_page_uri | string | URI for next page (null if this is the last page) |
previous_page_uri | string | URI for previous page (null if this is the first page) |
Example Paginated Response
{
"recordings": [
{
"id": "3d219a45-af16-4e2f-b018-dd8e44b4cf12",
"status": "transcribed",
"created_at": "2025-10-06T17:33:31"
}
],
"uri": "/v1/recordings?page=1&limit=10",
"first_page_uri": "/v1/recordings?page=0&limit=10",
"next_page_uri": "/v1/recordings?page=2&limit=10",
"previous_page_uri": "/v1/recordings?page=0&limit=10",
"page": 1,
"page_size": 10,
"total": 25
}
Iterating Through Pages
- Python
- Node.js
- cURL
from vocafuse import Client
client = Client(
api_key='sk_live_...',
api_secret='...'
)
# Method 1: Manual pagination
page = 0
while True:
response = client.recordings.list(page=page, limit=50)
for recording in response['recordings']:
print(f"Voice note: {recording['id']}")
# Check if there's a next page
if response['next_page_uri'] is None:
break
page += 1
# Method 2: Iterate all results (SDK handles pagination)
for recording in client.recordings.list_all():
print(f"Voice note: {recording['id']}")
const { Client } = require('vocafuse-node');
const client = new Client({
apiKey: process.env.VOCAFUSE_API_KEY,
apiSecret: process.env.VOCAFUSE_API_SECRET,
});
// Method 1: Manual pagination
async function listWithManualPagination() {
let page = 0;
while (true) {
const response = await client.recordings.list({ page, limit: 50 });
for (const recording of response.data) {
console.log('Voice note:', recording.id);
}
if (!response.pagination?.has_more) {
break;
}
page += 1;
}
}
// Method 2: Iterate all results (SDK handles pagination)
async function listAllRecordings() {
for await (const recording of client.recordings.iterate({ limit: 50 })) {
console.log('Voice note:', recording.id);
}
}
# Get first page
curl "https://api.vocafuse.com/v1/recordings?page=0&limit=50" \
-H "X-VocaFuse-API-Key: sk_live_..." \
-H "X-VocaFuse-API-Secret: ..."
# Get second page
curl "https://api.vocafuse.com/v1/recordings?page=1&limit=50" \
-H "X-VocaFuse-API-Key: sk_live_..." \
-H "X-VocaFuse-API-Secret: ..."
Best Practices
- Use reasonable page sizes - Start with 50, adjust based on your needs
- Don't skip pages - Process sequentially to avoid missing data
- Check
next_page_uri- Use it to detect the last page rather than calculating total pages - Handle empty results - The last page may have fewer than
limitresults - Cache when appropriate - For data that doesn't change frequently
Filtering
Many list endpoints support filtering via query parameters to narrow down results.
Common Filter Parameters
| Endpoint | Available Filters | Example |
|---|---|---|
| Voice Notes | status, date_from, date_to | ?status=transcribed&date_from=2025-10-01 |
| API Keys | status | ?status=active |
| Webhooks | status | ?status=active |
Date Filtering
Use ISO 8601 date format (YYYY-MM-DD) for date filters:
- Python
- Node.js
- cURL
from datetime import datetime, timedelta
# Get voice notes from last 7 days
seven_days_ago = (datetime.now() - timedelta(days=7)).strftime('%Y-%m-%d')
recordings = client.recordings.list(date_from=seven_days_ago)
# Get voice notes from specific date range
recordings = client.recordings.list(
date_from='2025-10-01',
date_to='2025-10-31'
)
const { Client } = require('vocafuse-node');
const client = new Client({
apiKey: process.env.VOCAFUSE_API_KEY,
apiSecret: process.env.VOCAFUSE_API_SECRET,
});
// Get voice notes from last 7 days
async function listLast7Days() {
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
.toISOString()
.slice(0, 10); // YYYY-MM-DD
const recordings = await client.recordings.list({
dateFrom: sevenDaysAgo,
});
return recordings.data;
}
// Get voice notes from specific date range
async function listFromRange() {
const recordings = await client.recordings.list({
dateFrom: '2025-10-01',
dateTo: '2025-10-31',
});
return recordings.data;
}
# Get voice notes from last 7 days
curl "https://api.vocafuse.com/v1/recordings?date_from=2025-10-02" \
-H "X-VocaFuse-API-Key: sk_live_..." \
-H "X-VocaFuse-API-Secret: ..."
# Get voice notes from specific date range
curl "https://api.vocafuse.com/v1/recordings?date_from=2025-10-01&date_to=2025-10-31" \
-H "X-VocaFuse-API-Key: sk_live_..." \
-H "X-VocaFuse-API-Secret: ..."
Status Filtering
Filter resources by their processing status:
- Python
- Node.js
- cURL
# Get only completed voice notes
completed = client.recordings.list(status='transcribed')
# Get failed voice notes
failed = client.recordings.list(status='failed')
# Get processing voice notes
processing = client.recordings.list(status='processing')
const { Client } = require('vocafuse-node');
const client = new Client({
apiKey: process.env.VOCAFUSE_API_KEY,
apiSecret: process.env.VOCAFUSE_API_SECRET,
});
async function listByStatus() {
// Get only completed voice notes
const completed = await client.recordings.list({ status: 'transcribed' });
// Get failed voice notes
const failed = await client.recordings.list({ status: 'failed' });
// Get processing voice notes
const processing = await client.recordings.list({ status: 'processing' });
return { completed: completed.data, failed: failed.data, processing: processing.data };
}
# Get only completed voice notes
curl "https://api.vocafuse.com/v1/recordings?status=transcribed" \
-H "X-VocaFuse-API-Key: sk_live_..." \
-H "X-VocaFuse-API-Secret: ..."
Combining Filters
Combine multiple filters to narrow results:
- Python
- Node.js
- cURL
# Get completed voice notes from last 7 days
recordings = client.recordings.list(
status='transcribed',
date_from='2025-10-02',
limit=100
)
# Get failed voice notes from October
recordings = client.recordings.list(
status='failed',
date_from='2025-10-01',
date_to='2025-10-31'
)
const { Client } = require('vocafuse-node');
const client = new Client({
apiKey: process.env.VOCAFUSE_API_KEY,
apiSecret: process.env.VOCAFUSE_API_SECRET,
});
async function listCompletedLast7Days() {
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
.toISOString()
.slice(0, 10);
const recordings = await client.recordings.list({
status: 'transcribed',
dateFrom: sevenDaysAgo,
limit: 100,
});
return recordings.data;
}
async function listFailedInOctober() {
const recordings = await client.recordings.list({
status: 'failed',
dateFrom: '2025-10-01',
dateTo: '2025-10-31',
});
return recordings.data;
}
# Get completed voice notes from last 7 days
curl "https://api.vocafuse.com/v1/recordings?status=transcribed&date_from=2025-10-02&limit=100" \
-H "X-VocaFuse-API-Key: sk_live_..." \
-H "X-VocaFuse-API-Secret: ..."
Rate Limits
API rate limits vary by plan to ensure service stability:
| Plan | Rate Limit | Burst Limit |
|---|---|---|
| Free | 10 req/min | 20 req/min |
| Pro | 100 req/min | 200 req/min |
| Enterprise | Custom | Custom |
Rate Limit Headers
Every API response includes rate limit information:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1642252800
Rate Limit Error
When you exceed the rate limit, you'll receive a 429 status:
{
"success": false,
"error": {
"code": 4003,
"message": "Rate limit exceeded. Try again in 60 seconds.",
"type": "RateLimitError",
"details": {
"retry_after": 60
}
}
}
Handling Rate Limits
- Python
- Node.js
import time
from vocafuse import Client, RateLimitError
client = Client(api_key='sk_live_...', api_secret='...')
try:
recordings = client.recordings.list()
except RateLimitError as e:
# Wait for the specified retry_after duration
wait_time = e.retry_after
print(f'Rate limited. Waiting {wait_time} seconds...')
time.sleep(wait_time)
# Retry the request
recordings = client.recordings.list()
import { Client, RateLimitError } from 'vocafuse-node';
const client = new Client({
apiKey: process.env.VOCAFUSE_API_KEY,
apiSecret: process.env.VOCAFUSE_API_SECRET,
});
async function listRecordingsWithRetry() {
try {
return await client.recordings.list();
} catch (error) {
if (error instanceof RateLimitError && error.retryAfter) {
console.error(`Rate limited. Waiting ${error.retryAfter} seconds...`);
await new Promise(resolve => setTimeout(resolve, error.retryAfter * 1000));
return client.recordings.list();
}
throw error;
}
}
Best Practices:
- Implement exponential backoff for retries
- Respect the
retry_aftervalue in error responses - Cache responses when appropriate
- Use webhooks instead of polling for status updates
- Monitor rate limit headers to avoid hitting limits
Next Steps
- Explore specific API endpoints:
- Learn about Error Handling
- Set up Webhooks to avoid polling