Authentication

Send Authorization: Bearer <secret> on every request. Workspace and project keys unlock different route groups — using the wrong type returns 403 forbidden.

API key types

TypePrefixCreated viaUse for
Workspace keysk_wsp_…Dashboard → Workspace keysProjects, project API keys
Project keysk_prj_…Dashboard or workspace key APIJobs, transcripts, storage connections, glossary, and catalog semantic search (ai:search)
Search catalog
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
}'
Get job
curl "https://perchat-media-api-csa4e2e0gedvgyfc.westus-01.azurewebsites.net/v1/jobs/job_YOUR_JOB_ID" \
  -H "Authorization: Bearer $API_KEY"
Treat secrets like passwords. Shown once at creation. Revoke compromised keys in the dashboard.

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.

Create project
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"
}'
Create project API key
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"
  ]
}'
Submit transcription job
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

PermissionAllows
workspace:readGET /v1/workspace
project:createPOST /v1/projects
project:listGET /v1/projects
project:readGET /v1/projects/{projectId}
project:updatePATCH /v1/projects/{projectId}
project:deleteDELETE /v1/projects/{projectId}
project_api_key:createPOST /v1/project-api-keys (with projectId in body)
project_api_key:listGET /v1/project-api-keys (with projectId query param)
project_api_key:readIncluded in list responses
project_api_key:updatePATCH /v1/project-api-keys/{apiKeyId} — rename (name) or revoke (status: revoked)
project_api_key:deleteDELETE /v1/project-api-keys/{apiKeyId} — permanent removal

Project key permissions

PermissionAllows
job:createPOST /v1/jobs — S3 direct (storage connection)
job:readGET /v1/jobs/{jobId} and GET /v1/jobs/{jobId}/webhook-deliveries
job:listGET /v1/jobs
job:cancelPOST /v1/jobs/{jobId}/cancel
transcript:listGET /v1/transcriptions
transcript:readGET /v1/transcriptions/{transcriptionId}, export routes, and GET .../storage sync status
transcript:editPATCH /v1/transcriptions/{id} (display name), PATCH …/segments (batch segment edits), PATCH …/segments/{segmentId}, glossary preview/apply, revert, and POST …/storage/sync
transcript:deleteDELETE /v1/transcriptions/{transcriptionId}
live-transcription:createGET /v1/live-transcription/sessions
storage_connection:listGET /v1/storage-connections
storage_connection:readRead a connection, browse buckets, discover buckets, job usage
storage_connection:createPOST /v1/storage-connections
storage_connection:updatePATCH /v1/storage-connections/{connectionId}, test, probe, activate
storage_connection:deleteDELETE /v1/storage-connections/{connectionId}
glossary:listGET /v1/glossary
glossary:readIncluded in list responses
glossary:createPOST /v1/glossary
glossary:updatePATCH /v1/glossary/{entryId}
glossary:deleteDELETE /v1/glossary/{entryId}
vector_store:readGET /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:updatePATCH /v1/project-vector-store/settings and POST /v1/project-vector-store/test (console session only)
ai:searchPOST /v1/catalog/search, GET /v1/catalog/indexed-transcriptions, and DELETE /v1/catalog/indexed-transcriptions/{transcriptionId}
webhook:readGET /v1/project-webhooks/settings and GET /v1/project-webhooks/deliveries
webhook:updatePATCH /v1/project-webhooks/settings, POST /v1/project-webhooks/rotate-secret, and POST /v1/project-webhooks/test
voices:listGET /v1/voices
voices:readGET /v1/voices/{voiceId}
voices:editPATCH /v1/voices/{voiceId}
voices:deleteDELETE /v1/voices/{voiceId}