REST API
Endpoints

Endpoints

All endpoints require Authorization: Bearer hd_ext_<your-key>. See Authentication.


Create a Project

POST /api/projects — Submit audio for transcription and optional AI processing.

The server downloads the audio (and optional job sheet) from the provided presigned URLs, re-uploads to internal storage, creates the project, and queues the transcription job.

Template Resolution

Templates determine the DOCX formatting applied after transcription. Resolution order:

  1. Use templateId if provided.
  2. Auto-select based on projectType + jurisdiction (and extracted job sheet metadata).
  3. Fall back to the configured system default template.
  4. If no template is available → 422.

Call GET /api/templates to see available templates and their IDs.

Request Body

FieldTypeRequiredDescription
titlestringDisplay title. Overridden by AI-extracted case title if a job sheet is provided.
audioUrlstring (URL)Presigned S3 URL to the audio file (MP3, WAV, M4A, WebM, MP4). Valid for ≥ 5 minutes.
jobSheetUrlstring (URL)Presigned S3 URL to a job sheet (DOCX, TXT, CSV) for AI metadata extraction.
descriptionstringFree-text description shown in the project list.
projectType"legal" | "general"Affects template auto-select. Default: "general".
templateIdstringSpecific template ID. Skips auto-select if provided.
jurisdictionstringState code for template auto-select (e.g. "CA", "NY"). Also extracted from job sheet.
additionalDetailsstringContext for the AI pipeline (max 1000 chars).
autoProcessEnabledbooleanRun AI formatting + proofreading after transcription. Default: true.
externalRefstringYour reference ID (order number, job ID) stored with the project.
jobIdstringJob ID for filtering a multi-case CSV job sheet. If the ID is not found or matches multiple rows, returns 422. Ignored for non-CSV job sheets.
metadataobjectCase metadata. Merged with job sheet extraction; caller values take precedence.

metadata fields (all optional):

{
  "caseNumber": "2024-CV-00123",
  "courtName": "Superior Court of California",
  "date": "2024-06-15",
  "plaintiffs": ["Alice Smith"],
  "defendants": ["Bob Jones"],
  "attorneys": ["John Counsel"],
  "witnesses": ["Mary Witness"]
}

Response 201

{
  "projectId": "j57abc123def456",
  "transcriptId": "k89xyz789ghi012"
}
FieldDescription
projectIdUse in subsequent status calls.
transcriptIdConvex transcript record ID.
warningPresent if transcription could not be started (project is still created).

Status Codes

CodeMeaning
201Project created, transcription queued.
400Missing title or audioUrl, invalid JSON.
401Invalid or revoked API key.
403templateId not found or not accessible.
422No template available for the requested project type, or jobId filtering failed (not found, multiple matches, malformed CSV, or blank jobId).
429Rate limit exceeded. See Retry-After header.
500Unexpected server error.
502Failed to download audio from audioUrl (upstream error).

Example

curl -X POST https://app.heydonna.chat/api/projects \
  -H "Authorization: Bearer hd_ext_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Smith v. Jones — Order 98765",
    "audioUrl": "https://s3.amazonaws.com/bucket/audio.mp3?X-Amz-Signature=...",
    "jobSheetUrl": "https://s3.amazonaws.com/bucket/jobsheet.docx?X-Amz-Signature=...",
    "projectType": "legal",
    "jurisdiction": "CA",
    "externalRef": "ORG-JOB-98765",
    "metadata": {
      "caseNumber": "2024-CV-00123",
      "courtName": "Superior Court of California"
    }
  }'

Get Project Status

GET /api/projects/:id/status — Poll transcription and AI pipeline status.

This endpoint is not rate-limited. Poll at most once every 5–10 seconds. Transcription typically takes 3–15 minutes depending on audio length.

Path Parameter

ParameterDescription
idProject ID from POST /api/projects.

Response 200

{
  "projectId": "j57abc123def456",
  "status": "processing",
  "externalRef": "ORG-JOB-98765",
  "transcripts": [
    {
      "transcriptId": "k89xyz789ghi012",
      "title": "Smith v. Jones Deposition",
      "status": "processing",
      "audioDuration": null,
      "progress": 45,
      "pipelineStage": null,
      "pipelineProgressMessage": null,
      "pipelineStageStartedAt": null
    }
  ]
}

Project status values:

ValueDescription
createdProject created; transcription not yet started.
processingTranscription or AI pipeline active.
transcribedTranscription complete; AI pipeline not yet run (or disabled).
readyAI pipeline complete; transcript ready for editing.
sharedTranscript shared with another user.
finalizedTerminal state — work complete.
failedProcessing failed. Contact support to retry.

Transcript status values:

ValueDescription
processingActive (transcription or pipeline running).
transcribingTranscription stage in progress.
formattingAI formatting stage in progress.
proofreadingAI proofreading stage in progress.
ready_for_reviewProofreading done; formatting not yet applied.
readyFinal state — transcript complete.
errorAn error occurred (check pipelineProgressMessage).

Transcript pipelineStage values (internal pipeline stages, autoProcessEnabled: true):

ValueDescription
queuedPipeline queued; not yet started.
v0First pipeline stage (formatting).
v1Second pipeline stage.
v2Third/final pipeline stage.
cancelledPipeline was cancelled by the user.

Status Codes

CodeMeaning
200Status returned.
400Invalid project ID format.
401Invalid or revoked API key.
404Project not found or not accessible with this key.
500Unexpected server error.

Polling Pattern

import time, requests, os
 
project_id = "j57abc123def456"
headers = {"Authorization": f"Bearer {os.environ['HEYDONNA_API_KEY']}"}
 
while True:
    resp = requests.get(
        f"https://app.heydonna.chat/api/projects/{project_id}/status",
        headers=headers,
    )
    resp.raise_for_status()
    data = resp.json()
 
    print(f"Status: {data['status']}")
 
    if data["status"] in ("ready", "transcribed", "finalized", "failed"):
        break
 
    time.sleep(15)  # Poll every 15 seconds

List Templates

GET /api/templates — List formatting templates available to your API key.

Returns system templates and templates owned by your account. Use the returned id as templateId in POST /api/projects to bypass auto-select.

Response 200

{
  "templates": [
    {
      "id": "j57abc123def456",
      "name": "Standard Deposition — California",
      "jurisdiction": "CA",
      "category": "deposition",
      "proceedingType": "deposition",
      "isDefault": true,
      "hasTranscriptSection": true
    },
    {
      "id": "m12pqr345stu678",
      "name": "EUO Template",
      "jurisdiction": null,
      "category": null,
      "proceedingType": "euo",
      "isDefault": false,
      "hasTranscriptSection": true
    }
  ]
}

Template fields:

FieldDescription
idUse as templateId in POST /api/projects.
nameHuman-readable display name.
jurisdictionState/jurisdiction the template is optimized for (null = all).
categoryTemplate category ("deposition", "hearing", etc.).
proceedingTypeProceeding type used for auto-select matching.
isDefaultWhether this is the default for its proceeding type.
hasTranscriptSectionWhether the template includes a formatted transcript section.

Status Codes

CodeMeaning
200Template list returned (may be empty).
401Invalid or revoked API key.
429Rate limit exceeded.
500Unexpected server error.

Example

curl https://app.heydonna.chat/api/templates \
  -H "Authorization: Bearer hd_ext_YOUR_KEY"