API Reference
The AI Interview API allows you to programmatically create campaigns, manage invites, and retrieve interview data.
Base URL
https://api.interviewrelay.com
Authentication
All API requests require authentication using an API key. See Authentication for details.
curl https://api.interviewrelay.com/api/campaigns \
-H "Authorization: Bearer YOUR_API_KEY"
Common Headers
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Campaigns
Create Campaign
/api/campaignsCreate a new interview campaign
Request Body:
| Name | Type | Description |
|---|---|---|
name* | string | Campaign name (internal use) |
script_id* | string | UUID of published script |
project_id* | string | UUID of project |
invite_valid_hours | number | Hours until invite expires (default: 168 = 7 days) |
Example Request:
curl -X POST https://api.interviewrelay.com/api/campaigns \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Q4 Customer Feedback",
"script_id": "550e8400-e29b-41d4-a716-446655440000",
"project_id": "660e8400-e29b-41d4-a716-446655440001",
"invite_valid_hours": 168
}'
Response (201 Created):
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"name": "Q4 Customer Feedback",
"script_id": "550e8400-e29b-41d4-a716-446655440000",
"project_id": "660e8400-e29b-41d4-a716-446655440001",
"status": "active",
"created_at": "2024-10-20T10:00:00Z"
}
List Campaigns
/api/campaignsRetrieve all campaigns
Query Parameters:
| Name | Type | Description |
|---|---|---|
project_id | string | Filter by project UUID |
status | string | Filter by status: active, completed, archived |
limit | number | Number of results (default: 50, max: 100) |
offset | number | Pagination offset (default: 0) |
Example:
curl "https://api.interviewrelay.com/api/campaigns?project_id=abc123&limit=10" \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
{
"campaigns": [
{
"id": "campaign-1",
"name": "Q4 Feedback",
"status": "active",
"invites_sent": 50,
"completed": 32,
"created_at": "2024-10-01T00:00:00Z"
}
],
"total": 1,
"limit": 10,
"offset": 0
}
Get Campaign Details
/api/campaigns/:idGet detailed information about a campaign
Example:
curl https://api.interviewrelay.com/api/campaigns/campaign-123 \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
{
"id": "campaign-123",
"name": "Q4 Customer Feedback",
"script_id": "script-456",
"project_id": "project-789",
"status": "active",
"created_at": "2024-10-01T00:00:00Z",
"stats": {
"invites_sent": 100,
"started": 65,
"completed": 48,
"completion_rate": 0.74
}
}
Invites
Create Invite
/api/campaigns/:id/invitesSend interview invites to participants
Request Body:
| Name | Type | Description |
|---|---|---|
emails* | string[] | Array of participant email addresses |
send_email | boolean | Whether to send email (default: true) |
custom_message | string | Optional custom email message |
Example:
curl -X POST https://api.interviewrelay.com/api/campaigns/campaign-123/invites \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"emails": ["user1@example.com", "user2@example.com"],
"send_email": true
}'
Response (201 Created):
{
"invites": [
{
"id": "invite-1",
"email": "user1@example.com",
"token": "inv_abc123",
"url": "https://interviewrelay.com/interview/inv_abc123",
"expires_at": "2024-10-27T10:00:00Z"
},
{
"id": "invite-2",
"email": "user2@example.com",
"token": "inv_def456",
"url": "https://interviewrelay.com/interview/inv_def456",
"expires_at": "2024-10-27T10:00:00Z"
}
],
"sent": 2,
"failed": 0
}
Get Invite Details
/api/invites/:tokenRetrieve invite information by token
Example:
curl https://api.interviewrelay.com/api/invites/inv_abc123 \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
{
"id": "invite-1",
"email": "user@example.com",
"token": "inv_abc123",
"status": "pending",
"campaign_id": "campaign-123",
"expires_at": "2024-10-27T10:00:00Z",
"created_at": "2024-10-20T10:00:00Z"
}
Sessions
List Sessions
/api/sessionsRetrieve interview sessions
Query Parameters:
| Name | Type | Description |
|---|---|---|
campaign_id | string | Filter by campaign UUID |
status | string | Filter by status: completed, in_progress, abandoned |
start_date | string | ISO 8601 date (filter sessions after this date) |
end_date | string | ISO 8601 date (filter sessions before this date) |
Example:
curl "https://api.interviewrelay.com/api/sessions?campaign_id=campaign-123&status=completed" \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
{
"sessions": [
{
"id": "session-1",
"campaign_id": "campaign-123",
"participant_email": "user@example.com",
"status": "completed",
"duration_minutes": 12,
"started_at": "2024-10-20T10:00:00Z",
"completed_at": "2024-10-20T10:12:00Z"
}
],
"total": 1
}
Get Session Details
/api/sessions/:idGet detailed session information
Example:
curl https://api.interviewrelay.com/api/sessions/session-123 \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
{
"id": "session-123",
"campaign_id": "campaign-456",
"participant_email": "user@example.com",
"status": "completed",
"duration_minutes": 12,
"started_at": "2024-10-20T10:00:00Z",
"completed_at": "2024-10-20T10:12:00Z",
"transcript_url": "https://api.interviewrelay.com/api/session/session-123/transcript",
"audio_url": "https://api.interviewrelay.com/api/session/session-123/audio"
}
Get Transcript
/api/session/:id/transcriptDownload session transcript
Example:
curl https://api.interviewrelay.com/api/session/session-123/transcript \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
{
"session_id": "session-123",
"started_at": "2024-10-20T10:00:00Z",
"completed_at": "2024-10-20T10:12:00Z",
"turns": [
{
"timestamp": 0,
"speaker": "ai",
"text": "Hello! Thank you for joining today.",
"sentiment": "neutral"
},
{
"timestamp": 3.5,
"speaker": "participant",
"text": "Hi, happy to be here.",
"sentiment": "positive"
}
]
}
Download PDF
/api/session/:id/pdfDownload formatted PDF transcript
Example:
curl https://api.interviewrelay.com/api/session/session-123/pdf \
-H "Authorization: Bearer YOUR_API_KEY" \
--output transcript.pdf
Projects
Create Project
/api/projectsCreate a new project
Request Body:
| Name | Type | Description |
|---|---|---|
name* | string | Project name |
description | string | Optional project description |
List Projects
/api/projectsRetrieve all projects
Billing
Get Credit Balance
/api/billing/creditsCheck current credit balance
Returns the starter, monthly, and top-up pool totals for the caller's primary organization (authentication required).
Response:
{
"starter_credits": 600,
"monthly_credits": 820,
"topup_credits": 4000,
"total_credits": 5420,
"monthly_credits_amount": 1000,
"monthly_credits_reset_at": "2025-02-01T00:00:00.000Z",
"currency": "eur",
"last_low_balance_warning_at": null,
"updated_at": "2025-01-07T12:30:00.000Z",
"low_balance_warning": {
"shouldWarn": false,
"severity": "info",
"message": ""
},
"needs_topup": false,
"estimated_sessions_remaining": 54
}
Get Usage
/api/billing/usageRetrieve billing usage details
Query Parameters:
| Name | Type | Description |
|---|---|---|
start_date | string | ISO 8601 date |
end_date | string | ISO 8601 date |
Admin Credit Summary
Requires admin privileges. Intended for internal observability tooling.
/api/admin/credits/summaryAggregate credit balances, alerts, and recent transactions
Response:
{
"summary": {
"totalOrganizations": 42,
"totalStarterCredits": 25200,
"totalMonthlyCredits": 318000,
"totalTopupCredits": 127500,
"totalCredits": 470700,
"lowBalanceCount": 4,
"criticalBalanceCount": 1
},
"lowBalanceOrganizations": [
{
"organizationId": "org-123",
"organizationName": "Acme Labs",
"organizationSlug": "acme-labs",
"starter": 0,
"monthly": 20,
"topup": 15,
"total": 35,
"monthlyCreditsAmount": 1000,
"monthlyCreditsResetAt": "2025-02-01T00:00:00.000Z",
"updatedAt": "2025-01-07T08:12:00.000Z",
"severity": "critical"
}
],
"recentTransactions": [
{
"id": "txn-789",
"organizationId": "org-456",
"organizationName": "Bright Water",
"organizationSlug": "bright-water",
"amountCredits": 10000,
"creditType": "topup",
"transactionType": "purchase",
"description": "Credit top-up: 10,000 credits (€100.00)",
"balanceAfterCredits": 15200,
"paymentIntentId": "pi_test_123",
"createdAt": "2025-01-07T10:15:00.000Z"
}
],
"alerts": [
{
"organizationId": "org-123",
"severity": "critical",
"message": "Acme Labs has only 35 credits remaining"
}
]
}
Rate Limiting
API requests are limited to:
- Free Plan: 100 requests/hour
- Starter: 1,000 requests/hour
- Professional: 10,000 requests/hour
- Enterprise: Custom limits
Rate limit headers are included in all responses:
X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 9847
X-RateLimit-Reset: 1634567890
When rate limited, the API returns 429 Too Many Requests. Implement exponential backoff in your client.
Error Codes
| Code | Description | |------|-------------| | 200 | Success | | 201 | Created | | 400 | Bad Request - Invalid parameters | | 401 | Unauthorized - Invalid API key | | 403 | Forbidden - Insufficient permissions | | 404 | Not Found | | 429 | Too Many Requests - Rate limited | | 500 | Internal Server Error |
Error Response Format:
{
"error": {
"code": "INVALID_PARAMETER",
"message": "The 'email' field is required",
"details": {
"field": "email",
"expected": "string"
}
}
}
Pagination
List endpoints support pagination:
curl "https://api.your-domain.com/api/campaigns?limit=50&offset=100" \
-H "Authorization: Bearer YOUR_API_KEY"
Response includes:
{
"data": [...],
"pagination": {
"total": 247,
"limit": 50,
"offset": 100,
"has_more": true
}
}
Best Practices
Handle Errors Gracefully
try {
const response = await fetch('https://api.interviewrelay.com/api/campaigns', {
headers: { Authorization: `Bearer ${API_KEY}` }
});
if (!response.ok) {
const error = await response.json();
console.error('API Error:', error);
// Handle error...
}
const data = await response.json();
// Process data...
} catch (error) {
console.error('Network error:', error);
}
Use Webhooks for Real-time Updates
Instead of polling for session completion, use webhooks for instant notifications.
Cache Responses
Cache static data like projects and scripts to reduce API calls:
const cache = new Map();
async function getProject(id) {
if (cache.has(id)) {
return cache.get(id);
}
const project = await fetchProject(id);
cache.set(id, project);
return project;
}
SDKs and Libraries
Official SDKs:
- JavaScript/TypeScript:
@ai-interview/sdk - Python: Coming soon
- Ruby: Coming soon
Community SDKs:
- Check our GitHub for community contributions
Examples
See the Examples section for complete working code samples.
Support
Need help with the API?
- Authentication Guide
- Webhooks Guide
- Email: support@interviewrelay.com