Document API Endpoints
PDF Generation Endpoints
GET /v1/reports/{id}/pdf
Generate or serve cached PDF for a report.
Query Parameters:
?audience=patient|specialist|admin(default: based on caller role)?template_id=5(optional, uses org default if omitted)
Response: 200
Content-Type: application/pdf
Headers:
Content-Type: application/pdf
Content-Disposition: inline; filename="report-{id}.pdf"Access:
- Patient (own report, audience=patient forced)
- Specialist
- Admin
Caching: If form.status=signed, returns cached S3 version if available
Errors:
404 document_not_found- Document doesn't exist or not accessible400 form_not_attached- Document has no associated form500 pdf_generation_failed- Chrome rendering error
GET /v1/prescriptions/{id}/pdf
Generate or serve cached PDF for a prescription.
Query Parameters:
?audience=patient|specialist|admin(default: based on caller role)?template_id=5(optional, uses org default if omitted)
Response: 200
Content-Type: application/pdf
Access:
- Patient (own prescription)
- Specialist
- Admin
Additional rule: Prescription PDF always includes specialist signature (generation fails if missing)
Errors:
404 document_not_found400 form_not_attached400 specialist_signature_required- Prescription requires specialist signature500 pdf_generation_failed
Audience Filtering
The ?audience query parameter controls field visibility:
| Audience | Private fields | Specialist signature | Use case |
|---|---|---|---|
patient (default) | Excluded | Included | Patient downloads their report |
specialist | Included | Included | Specialist reviews full report |
admin | Included | Included | Admin/compliance review |
Filtering happens at the data building step, not in the template. The template always renders what it receives.
PDF Template Management
Note: PDF template management (visual designer, block-based editor, component library) has been moved to a separate feature.
See PDF Templates API for:
- Template CRUD (
/v1/pdf-templates/*) - Component management (
/v1/pdf-template-components/*) - Template versioning and publishing
- Live preview and rendering
Form templates link to PDF templates via form_templates.pdf_template_id, and documents record which pdf_template_version was used for generation.
Report CRUD Endpoints
Reports are stored in appointment_documents with type=report.
GET /v1/reports
List reports. Org-scoped by RLS.
Query Parameters:
?appointment_id=102?published=true?page=1&page_size=25
Response: 200
{
"data": [
{
"id": 1,
"organization_id": 1,
"appointment_id": 102,
"user_id": 42,
"form_id": 204,
"type": "report",
"title": "Consultation Report",
"document_url": null,
"published": false,
"created_at": "2025-01-15T10:00:00Z"
}
],
"meta": {
"page": 1,
"page_size": 25,
"total": 1,
"total_pages": 1
}
}POST /v1/reports
Create report for an appointment.
Request:
{
"appointment_id": 102,
"title": "Consultation Report",
"form_id": 204
}Response: 201
{
"data": {
"id": 1,
"organization_id": 1,
"appointment_id": 102,
"user_id": 42,
"form_id": 204,
"type": "report",
"title": "Consultation Report",
"published": false,
"created_at": "2025-01-15T10:00:00Z"
}
}Access: Specialist | Admin
GET /v1/reports/{id}
Get report with files.
Response: 200
{
"data": {
"id": 1,
"organization_id": 1,
"appointment_id": 102,
"user_id": 42,
"form_id": 204,
"type": "report",
"title": "Consultation Report",
"document_url": null,
"published": false,
"files": [
{
"id": 1,
"file_url": "https://s3.../file.pdf",
"file_name": "report.pdf",
"file_type": "application/pdf",
"file_size": 102400,
"created_at": "2025-01-15T10:00:00Z"
}
],
"created_at": "2025-01-15T10:00:00Z"
}
}Access: Patient (own) | Specialist | Admin
PUT /v1/reports/{id}
Update report metadata.
Request:
{
"title": "Updated Report Title",
"published": true
}Response: 200
Access: Specialist | Admin
DELETE /v1/reports/{id}
Delete report.
Response: 204 No Content
Access: Admin only
Prescription CRUD Endpoints
Prescriptions are stored in appointment_documents with type=prescription.
GET /v1/prescriptions
List prescriptions. Org-scoped by RLS.
POST /v1/prescriptions
Create prescription for an appointment.
Request:
{
"appointment_id": 102,
"title": "Treatment Prescription",
"form_id": 205
}GET /v1/prescriptions/{id}
Get prescription.
PUT /v1/prescriptions/{id}
Update prescription.
DELETE /v1/prescriptions/{id}
Delete prescription.
Error Codes
| Error | HTTP | When |
|---|---|---|
document_not_found | 404 | Document ID doesn't exist or not accessible via RLS |
form_not_attached | 400 | Document has no associated form |
form_not_signed | 400 | Trying to publish/cache a PDF for an unsigned form |
specialist_signature_required | 400 | Prescription PDF requested but specialist has no signature |
template_not_found | 404 | Specified template_id doesn't exist; or no default template for org+type |
template_render_error | 500 | Go template execution failed (syntax error in template HTML) |
pdf_generation_failed | 500 | chromedp failed to render PDF |
document_already_published | 409 | Trying to modify a published document |