Authentication
Authorization: Bearer <secret> on every request. Workspace and project keys unlock different route groups — using the wrong type returns 403 forbidden.API key types
| Type | Prefix | Created via | Use for |
|---|---|---|---|
| Workspace key | sk_wsp_… | Dashboard → Workspace keys | Projects, project API keys |
| Project key | sk_prj_… | Dashboard or workspace key API | Jobs, transcripts, storage connections, glossary, and catalog semantic search (ai:search) |
curl -X POST "https://perchat-media-api-csa4e2e0gedvgyfc.westus-01.azurewebsites.net/v1/catalog/search" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "performance metrics",
"limit": 5
}'curl "https://perchat-media-api-csa4e2e0gedvgyfc.westus-01.azurewebsites.net/v1/jobs/job_YOUR_JOB_ID" \
-H "Authorization: Bearer $API_KEY"Provision with a workspace key
Use a workspace key to create a project, mint a project key, then run jobs with sk_prj_…. See Projects and Project API keys for endpoint details.
curl -X POST "https://perchat-media-api-csa4e2e0gedvgyfc.westus-01.azurewebsites.net/v1/projects" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "staging"
}'curl -X POST "https://perchat-media-api-csa4e2e0gedvgyfc.westus-01.azurewebsites.net/v1/project-api-keys" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"projectId": "prj_01HX2K9V3JEK4WYZN6F0XQ2W8M",
"name": "ci",
"permissions": [
"job:create",
"job:read",
"ai:search",
"storage_connection:create",
"storage_connection:read"
]
}'curl -X POST "https://perchat-media-api-csa4e2e0gedvgyfc.westus-01.azurewebsites.net/v1/jobs" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"serviceType": "transcription",
"input": {
"sourceType": "s3_direct",
"connectionId": "e7b2c4d8-0000-4000-a000-000000000001",
"bucket": "my-bucket",
"sourceKey": "media/clips/demo.mp4",
"options": {
"language": "en"
}
},
"userMetadata": {
"customerJobRef": "abc-123"
}
}'Permission scopes
Permissions are fixed at key creation. Omit permissions to grant all scopes for that key type.
Storage connections live under a project URL, so programmatic access uses a project API key with storage_connection:* — not a workspace key. Dashboard users manage storage via workspace role permissions (same storage_connection:* strings) with X-Project-Id set in the UI.
Job status webhooks follow the same pattern: use a project API key with webhook:read (settings and delivery log) and/or webhook:update (URL, signing secret, test delivery). Dashboard users need the same permission strings on their workspace role. Per-job delivery history on GET /v1/jobs/{jobId}/webhook-deliveries requires job:read only.
Workspace key permissions
| Permission | Allows |
|---|---|
workspace:read | GET /v1/workspace |
project:create | POST /v1/projects |
project:list | GET /v1/projects |
project:read | GET /v1/projects/{projectId} |
project:update | PATCH /v1/projects/{projectId} |
project:delete | DELETE /v1/projects/{projectId} |
project_api_key:create | POST /v1/project-api-keys (with projectId in body) |
project_api_key:list | GET /v1/project-api-keys (with projectId query param) |
project_api_key:read | Included in list responses |
project_api_key:update | PATCH /v1/project-api-keys/{apiKeyId} — rename (name) or revoke (status: revoked) |
project_api_key:delete | DELETE /v1/project-api-keys/{apiKeyId} — permanent removal |
Project key permissions
| Permission | Allows |
|---|---|
job:create | POST /v1/jobs — S3 direct (storage connection) |
job:read | GET /v1/jobs/{jobId} and GET /v1/jobs/{jobId}/webhook-deliveries |
job:list | GET /v1/jobs |
job:cancel | POST /v1/jobs/{jobId}/cancel |
transcript:list | GET /v1/transcriptions |
transcript:read | GET /v1/transcriptions/{transcriptionId}, export routes, and GET .../storage sync status |
transcript:edit | PATCH /v1/transcriptions/{id} (display name), PATCH …/segments (batch segment edits), PATCH …/segments/{segmentId}, glossary preview/apply, revert, and POST …/storage/sync |
transcript:delete | DELETE /v1/transcriptions/{transcriptionId} |
live-transcription:create | GET /v1/live-transcription/sessions |
storage_connection:list | GET /v1/storage-connections |
storage_connection:read | Read a connection, browse buckets, discover buckets, job usage |
storage_connection:create | POST /v1/storage-connections |
storage_connection:update | PATCH /v1/storage-connections/{connectionId}, test, probe, activate |
storage_connection:delete | DELETE /v1/storage-connections/{connectionId} |
glossary:list | GET /v1/glossary |
glossary:read | Included in list responses |
glossary:create | POST /v1/glossary |
glossary:update | PATCH /v1/glossary/{entryId} |
glossary:delete | DELETE /v1/glossary/{entryId} |
vector_store:read | GET /v1/project-vector-store/settings, GET /v1/project-vector-store/inventory, POST /v1/project-vector-store/specs, and POST /v1/project-vector-store/health (console session only) |
vector_store:update | PATCH /v1/project-vector-store/settings and POST /v1/project-vector-store/test (console session only) |
ai:search | POST /v1/catalog/search, GET /v1/catalog/indexed-transcriptions, and DELETE /v1/catalog/indexed-transcriptions/{transcriptionId} |
webhook:read | GET /v1/project-webhooks/settings and GET /v1/project-webhooks/deliveries |
webhook:update | PATCH /v1/project-webhooks/settings, POST /v1/project-webhooks/rotate-secret, and POST /v1/project-webhooks/test |
voices:list | GET /v1/voices |
voices:read | GET /v1/voices/{voiceId} |
voices:edit | PATCH /v1/voices/{voiceId} |
voices:delete | DELETE /v1/voices/{voiceId} |