Getting Started
Mukhtabir API
The Mukhtabir REST API gives your organization programmatic access to the full interview lifecycle — from creating structured AI-powered interviews to retrieving deep evaluation analytics.
Interview Management
Create, configure, publish, and manage AI interview templates at scale.
Candidate Workflows
Invite candidates, track completion, and manage access tokens automatically.
AI Evaluations
Retrieve structured evaluation scores, strengths, and improvement areas in JSON.
Real-time Webhooks
Receive instant notifications when interviews start, complete, or evaluations are generated.
The API is designed for enterprise integrations with HR platforms such as Greenhouse, Workday, Lever, and SAP SuccessFactors. It follows REST conventions, uses JSON for all request and response bodies, and is fully versioned under /api/v1/.
Auth
Authentication
All API requests are authenticated using API keys. Keys are scoped to specific operations and tied to your organization account.
API Key Format
Authorization: Bearer mk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6Keys follow the format mk_{environment}_{32-char-random}. Live keys start with mk_live_; test keys start with mk_test_.
Available Scopes
| Scope | Access |
|---|---|
interviews:read | View interviews, questions, and criteria |
interviews:write | Create, update, and publish interviews |
interviews:delete | Delete interviews |
questions:write | Add, update, and delete interview questions and followups |
criteria:write | Add, update, and delete evaluation criteria |
candidates:read | View candidate profiles and status |
candidates:write | Register candidates and send invitations |
feedback:read | Access evaluation scores and transcripts |
webhooks:manage | Create and manage webhook subscriptions |
analytics:read | View aggregated analytics |
DELETE /api/v1/api-keys/{id}.Creating API Keys
API keys are created by organization admins through the Mukhtabir dashboard or via the API key management endpoint. The full plaintext key is shown only once at creation time — store it securely in your secrets manager.
POST /api/v1/api-keys
Authorization: Bearer <session-token>
{
"name": "Greenhouse Production",
"scopes": ["interviews:read", "interviews:write", "candidates:write", "feedback:read"],
"environment": "live"
}
// Response
{
"success": true,
"data": {
"id": "uuid",
"name": "Greenhouse Production",
"key_prefix": "mk_live_a1b2",
"plaintext_key": "mk_live_a1b2c3d4...", // ← shown only once
"scopes": ["interviews:read", "interviews:write", ...],
"environment": "live",
"created_at": "2026-03-11T10:00:00Z",
"warning": "Store this key securely. It will not be shown again."
}
}Environments
Base URL & Versioning
https://mukhtabir.hbku.edu.qa/api/v1Use keys starting with mk_live_
https://mukhtabir.hbku.edu.qa/api/v1Use keys starting with mk_test_
The API is versioned under /api/v1/. When breaking changes are introduced a new version (e.g. /api/v2/) will be released with a minimum 6-month overlap. Non-breaking additions (new optional fields, new endpoints) are made to the current version without a version bump.
API Reference
Endpoints
All responses use a consistent JSON envelope. Click any endpoint to expand its details.
// Success response envelope
{
"success": true,
"data": { ... },
"meta": {
"request_id": "req_lf3k2_abc123",
"timestamp": "2026-03-11T10:00:00Z"
}
}
// Error response envelope
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Human-readable description",
"details": [{ "field": "email", "issue": "required" }]
},
"meta": { "request_id": "req_lf3k2_abc123" }
}Interviews
Questions & Evaluation Criteria
Candidates
Results & Feedback
Webhook Management
API Key Management
Events
Webhook Events
Mukhtabir delivers signed HTTP POST requests to your registered URL whenever key lifecycle events occur.
| Event | Trigger |
|---|---|
interview.created | A new interview is created via API or dashboard |
interview.published | An interview is published and becomes accessible |
interview.started | A candidate begins their interview session |
interview.completed | The AI call ends and feedback is created |
evaluation.generated | The AI evaluation is fully scored and stored |
candidate.invited | A candidate invitation is issued |
Payload Format
// evaluation.generated example
{
"event": "evaluation.generated",
"timestamp": "2026-03-11T11:36:12Z",
"data": {
"feedback_id": "7b2c4d...",
"total_score": 82.5,
"category_scores": [
{ "name": "Technical Knowledge", "score": 88 },
{ "name": "Problem Solving", "score": 80 },
{ "name": "Communication", "score": 79 }
]
}
}
// interview.completed example
{
"event": "interview.completed",
"timestamp": "2026-03-11T11:35:00Z",
"data": {
"interview_id": "550e8400-...",
"feedback_id": "7b2c4d...",
"candidate_email": "candidate@company.com"
}
}Signature Verification
Every delivery is signed with HMAC-SHA256 using the webhook secret returned at registration time. Verify the signature before processing any payload.
// Node.js signature verification
import { createHmac } from "crypto";
function verifyWebhook(body, signature, timestamp, secret) {
const data = `${timestamp}.${body}`;
const expected = createHmac("sha256", secret)
.update(data)
.digest("hex");
return signature === expected;
}
// Express route handler
app.post("/webhooks/mukhtabir", express.raw({ type: "*/*" }), (req, res) => {
const sig = req.headers["x-mukhtabir-signature"];
const timestamp = req.headers["x-mukhtabir-timestamp"];
const secret = process.env.MUKHTABIR_WEBHOOK_SECRET;
if (!verifyWebhook(req.body.toString(), sig, timestamp, secret)) {
return res.status(401).send("Invalid signature");
}
const event = JSON.parse(req.body);
console.log("Event:", event.event, event.data);
res.sendStatus(200);
});Delivery Headers
X-Mukhtabir-SignatureHMAC-SHA256 of timestamp.body using webhook secretX-Mukhtabir-EventEvent type (e.g. evaluation.generated)X-Mukhtabir-Delivery-IdUnique delivery UUID for idempotencyX-Mukhtabir-TimestampUnix timestamp when the event was dispatchedX-Mukhtabir-Delivery-Id header to implement idempotency — store processed delivery IDs to avoid handling the same event twice during retries.Retry Policy
Failed deliveries are retried up to 5 times with exponential back-off: 30s → 2min → 15min → 1h → 4h. After 5 failures the delivery is marked exhausted. View delivery history via GET /api/v1/webhooks/{id}/deliveries.
ATS Integration Example
End-to-End Integration Workflow
A typical workflow integrating Mukhtabir with an ATS like Greenhouse or Lever.
POST /api/v1/interviewsYour ATS creates a structured AI interview template for the open role.
POST /api/v1/interviews/{id}/publishFinalize and publish the interview to make it accessible.
POST /api/v1/interviews/{id}/inviteATS passes candidate email/name. Mukhtabir returns a unique interview URL.
Your ATS sends the URL to the candidateThe time-limited link is sent to the candidate through your existing email flow.
interview.completed webhook firesMukhtabir notifies your ATS that the AI call has ended.
evaluation.generated webhook firesScores, strengths, and assessment delivered to your webhook endpoint.
GET /api/v1/feedback/{id}ATS retrieves the full evaluation, updates the candidate's scorecard, and moves them to the next pipeline stage.
Compatible Systems
Limits
Rate Limits
Rate limits are enforced per organization. Responses include standard rate limit headers so you can monitor your usage.
| Plan | Requests / min | Requests / hour |
|---|---|---|
| Free | 100 | 5,000 |
| Starter | 500 | 25,000 |
| Enterprise | 10,000 | 500,000 |
Rate Limit Headers
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 94
X-RateLimit-Reset: 1741694460
X-Request-Id: req_lf3k2_abc123
// When limit is exceeded:
HTTP/1.1 429 Too Many Requests
Retry-After: 42
Content-Type: application/json
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. Please try again later."
}
}Compliance
Security & Data Protection
The Mukhtabir API is built for enterprise environments with strict security and data protection requirements.
TLS 1.3 Encryption
All API traffic is encrypted in transit. HTTP requests are rejected. Webhook URLs must use HTTPS.
Scoped API Keys
Keys are SHA-256 hashed before storage. Plaintext never persisted. Fine-grained scope control per key.
Full Audit Trail
Every API request is logged to a dedicated audit table with org ID, key ID, endpoint, and latency.
PII Protection
Webhook payloads never include transcripts or raw PII. Sensitive fields are masked in logs.
Rate Limiting
Per-organization rate limits at multiple layers. Burst protection prevents abuse.
GDPR / QFC Compliance
Data minimization, right to erasure support, and compliance with QFC Data Protection regulations.
Code Examples
Complete Examples
Full interview-to-evaluation workflows in your language of choice.
# Create an interview
curl -X POST https://mukhtabir.hbku.edu.qa/api/v1/interviews \
-H "Authorization: Bearer mk_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"role": "Senior Software Engineer",
"type": "technical",
"level": "senior",
"duration": 30,
"techstack": ["Python", "Django", "PostgreSQL"],
"max_score": 100,
"visibility": "restricted"
}'
# Invite a candidate
curl -X POST https://mukhtabir.hbku.edu.qa/api/v1/interviews/{id}/invite \
-H "Authorization: Bearer mk_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"email": "candidate@company.com",
"name": "Sarah Al-Rashid",
"expires_in_hours": 72
}'
# Retrieve evaluation results
curl -X GET https://mukhtabir.hbku.edu.qa/api/v1/feedback/{feedbackId} \
-H "Authorization: Bearer mk_live_your_api_key_here"Webhook Verification Example
# Python webhook verification with Flask
import hmac, hashlib, json
from flask import Flask, request, abort
app = Flask(__name__)
WEBHOOK_SECRET = "whsec_your_secret_here"
@app.route("/webhooks/mukhtabir", methods=["POST"])
def handle_webhook():
sig = request.headers.get("X-Mukhtabir-Signature", "")
timestamp = request.headers.get("X-Mukhtabir-Timestamp", "")
body = request.get_data(as_text=True)
data = f"{timestamp}.{body}"
expected = hmac.new(
WEBHOOK_SECRET.encode(),
data.encode(),
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(sig, expected):
abort(401)
event = json.loads(body)
print(f"Event: {event['event']}")
if event["event"] == "evaluation.generated":
feedback_id = event["data"]["feedback_id"]
score = event["data"]["total_score"]
print(f"Candidate scored {score}/100 — fetching full results...")
# fetch_full_evaluation(feedback_id)
return "", 200Help
Developer Support
Our team is available to help you design and implement your Mukhtabir integration. Whether you need help with a custom ATS connector, data mapping, or enterprise procurement, reach out through any of the channels below.
Integration Support
api-support@mukhtabir.hbku.edu.qa
Response within 1 business day
Enterprise Sales
sales@voramind.org
Custom plans, SLAs, and onboarding
Bug Reports
security@mukhtabir.hbku.edu.qa
Responsible disclosure welcome
Developer Community
docs.mukhtabir.hbku.edu.qa
Guides, tutorials, and FAQs