{"openapi":"3.0.3","info":{"title":"Caligenix Connect — Partner API","description":"The Caligenix Connect Partner API provides secure, programmatic access to report data within the Caligenix Connect platform. Use this API to query report status, retrieve metadata, and download report PDFs directly into your systems.\n\n## Authentication\n\nAll authenticated endpoints require a valid API key in the `Authorization` header:\n\n```\nAuthorization: Bearer cgx_pk_<your_key>\n```\n\nAPI keys are provisioned by your Caligenix Connect account manager and scoped to specific permissions. Each key is tied to your partner account and provides access only to your organization's data.\n\n> **Important:** Your API key grants access to sensitive data. Store it securely, never commit it to source control, and rotate it immediately if compromised.\n\n## Rate Limiting\n\nRequests are rate-limited to **100 requests per minute** per API key, per endpoint. If you exceed this limit, the API responds with HTTP `429`. Implement exponential backoff to handle rate limiting gracefully.\n\n## Pagination\n\nList endpoints support offset-based pagination:\n\n- `limit` — Records per page (default: 50, max: 100)\n- `offset` — Records to skip (default: 0)\n\nEvery list response includes a `total` field with the count of all matching records, so you can calculate total pages.\n\n## Polling for New Reports\n\nUse the `since` parameter on `GET /v1/reports` to efficiently poll for updates. Pass the `updatedAt` value of the most recent report you've seen, and the API will return only reports updated after that time.\n\n## Report Download Workflow\n\nDownloading a report PDF is a two-step process:\n\n1. **Generate a download URL** — Call `GET /v1/reports/{id}/download-url` with your API key. The report must have a status of `AVAILABLE` or `DOWNLOADED`.\n\n2. **Download the file** — Follow the `downloadUrl` returned in the response. This is a pre-signed URL that requires **no authentication header**. The link is valid for 15 minutes, indicated by the `expiresAt` timestamp (Unix epoch seconds).\n\n## Correlation IDs\n\nEvery response includes an `X-Correlation-Id` header for request tracing. You may also send your own `X-Correlation-Id` request header — the API will echo it back instead of generating a new one. Include this ID when contacting support.\n\n## Error Handling\n\nAll errors return a consistent JSON structure with a machine-readable `code`, a human-readable `message`, and a `correlationId` for support reference.\n\n| Code | Status | Description |\n|------|--------|-------------|\n| `AUTH_REQUIRED` | 401 | Missing or invalid API key |\n| `FORBIDDEN` | 403 | Insufficient scopes or inactive partner account |\n| `NOT_FOUND` | 404 | Resource does not exist |\n| `BAD_REQUEST` | 400 | Invalid request parameters |\n| `RATE_LIMITED` | 429 | Too many requests — retry after backoff |\n| `INTERNAL_ERROR` | 500 | Unexpected server error |\n\n## Scopes\n\n| Scope | Grants |\n|-------|--------|\n| `reports:read` | List and view report metadata |\n| `reports:download` | Generate download URLs for report files |\n","contact":{"name":"Caligenix Connect Support","url":"https://caligenixconnect.com"}},"servers":[{"url":"https://api.caligenixconnect.com","description":"Production"}],"security":[{"BearerAuth":[]}],"tags":[{"name":"Reports","description":"Query report metadata and generate download URLs"},{"name":"System","description":"Health check and connectivity verification"}],"paths":{"/v1/health":{"get":{"tags":["System"],"summary":"Health check","description":"Returns the current health status of the API. No authentication required. Useful for monitoring and connectivity checks.","operationId":"getHealth","security":[],"responses":{"200":{"description":"API is healthy","headers":{"X-Correlation-Id":{"schema":{"type":"string","format":"uuid"},"description":"Request correlation identifier"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"},"example":{"ok":true,"correlationId":"550e8400-e29b-41d4-a716-446655440000"}}}}}}},"/v1/reports":{"get":{"tags":["Reports"],"summary":"List reports","description":"Returns a paginated list of reports in your organization. Supports filtering by status, location, client, and last-updated time.","operationId":"listReports","parameters":[{"name":"status","in":"query","description":"Filter by report status.","required":false,"schema":{"type":"string","enum":["PENDING","AVAILABLE","DOWNLOADED"]}},{"name":"location_id","in":"query","description":"Filter by location UUID.","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"client_id","in":"query","description":"Filter by client UUID.","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"since","in":"query","description":"Return only reports updated after this ISO 8601 timestamp. Ideal for incremental polling.","required":false,"schema":{"type":"string","format":"date-time"},"example":"2026-03-01T00:00:00Z"},{"name":"limit","in":"query","description":"Maximum number of reports to return.","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"offset","in":"query","description":"Number of reports to skip for pagination.","required":false,"schema":{"type":"integer","minimum":0,"default":0}}],"responses":{"200":{"description":"Paginated list of reports","headers":{"X-Correlation-Id":{"schema":{"type":"string","format":"uuid"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportListResponse"},"example":{"reports":[{"id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","clientId":"c1d2e3f4-a5b6-7890-cdef-123456789012","clientName":"Jane Smith","kitId":"d4e5f6a7-b8c9-0123-4567-890abcdef012","kitBarcode":"CGX-2026-001234","reportTypeId":"b2c3d4e5-f6a7-8901-2345-67890abcdef0","reportTypeName":"Full Panel Analysis","locationId":"e5f6a7b8-c9d0-1234-5678-90abcdef0123","locationName":"Downtown Clinic","status":"AVAILABLE","uploadedAt":"2026-03-20T14:30:00.000Z","createdAt":"2026-03-15T09:00:00.000Z","updatedAt":"2026-03-20T14:30:00.000Z"}],"limit":50,"offset":0,"total":1}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"BAD_REQUEST","message":"Invalid status. Valid values: PENDING, AVAILABLE, DOWNLOADED","correlationId":"660f9500-f39c-51e5-b827-557766551111"}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"AUTH_REQUIRED","message":"API key required. Use Authorization: Bearer cgx_pk_<key>","correlationId":"770a0600-a40d-62f6-c938-668877662222"}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests. Please try again later.","correlationId":"880b1700-b51e-73a7-d049-779988773333"}}}}}}}},"/v1/reports/{id}":{"get":{"tags":["Reports"],"summary":"Get a report","description":"Returns detailed metadata for a single report. Returns 404 if the report does not exist within your organization.","operationId":"getReport","parameters":[{"name":"id","in":"path","required":true,"description":"Report UUID","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Report details","headers":{"X-Correlation-Id":{"schema":{"type":"string","format":"uuid"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportDetailResponse"},"example":{"report":{"id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","clientId":"c1d2e3f4-a5b6-7890-cdef-123456789012","clientName":"Jane Smith","kitId":"d4e5f6a7-b8c9-0123-4567-890abcdef012","kitBarcode":"CGX-2026-001234","reportTypeId":"b2c3d4e5-f6a7-8901-2345-67890abcdef0","reportTypeName":"Full Panel Analysis","locationId":"e5f6a7b8-c9d0-1234-5678-90abcdef0123","locationName":"Downtown Clinic","status":"AVAILABLE","uploadedAt":"2026-03-20T14:30:00.000Z","createdAt":"2026-03-15T09:00:00.000Z","updatedAt":"2026-03-20T14:30:00.000Z"}}}}},"400":{"description":"Invalid report ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Report not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"NOT_FOUND","message":"Report not found","correlationId":"990c2800-c62f-84b8-e150-880099884444"}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/reports/{id}/download-url":{"get":{"tags":["Reports"],"summary":"Generate a download URL","description":"Generates a temporary, pre-signed URL for downloading the report file. The URL is valid for **15 minutes** and requires no authentication to follow.\n\nThe report must have a status of `AVAILABLE` or `DOWNLOADED`. Reports with status `PENDING` do not yet have an uploaded file.\n\n**Usage:**\n1. Call this endpoint to get the `downloadUrl`\n2. Issue a standard HTTP GET to `downloadUrl` (no `Authorization` header needed)\n3. The response will stream the PDF file with appropriate `Content-Type` and `Content-Disposition` headers","operationId":"getReportDownloadUrl","parameters":[{"name":"id","in":"path","required":true,"description":"Report UUID","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Download URL generated","headers":{"X-Correlation-Id":{"schema":{"type":"string","format":"uuid"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadUrlResponse"},"example":{"downloadUrl":"https://api.caligenixconnect.com/v1/files/a1b2c3d4-e5f6-7890-abcd-ef1234567890?key=reports%2F...&expires=1742968800&sig=abc123...","expiresAt":1742968800,"report":{"id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","fileName":"c1d2e3f4-CGX-2026-001234-full-panel-analysis.pdf","status":"AVAILABLE"}}}}},"400":{"description":"Report is not available for download or has no uploaded file","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":{"code":"BAD_REQUEST","message":"Report is not available for download. Status must be AVAILABLE or DOWNLOADED.","correlationId":"aa0d3900-d73a-95c9-f261-991100995555"}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Report or report file not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"Partner API key prefixed with `cgx_pk_`.\n\nExample value: `cgx_pk_abc123def456ghi789...`"}},"schemas":{"Report":{"type":"object","description":"A report record within your organization.","properties":{"id":{"type":"string","format":"uuid","description":"Unique report identifier"},"clientId":{"type":"string","format":"uuid","description":"Client associated with the report"},"clientName":{"type":"string","nullable":true,"description":"Full name of the client"},"kitId":{"type":"string","format":"uuid","description":"Kit used for this report"},"kitBarcode":{"type":"string","nullable":true,"description":"Barcode label of the kit"},"reportTypeId":{"type":"string","format":"uuid","description":"Report type identifier"},"reportTypeName":{"type":"string","nullable":true,"description":"Human-readable name of the report type"},"locationId":{"type":"string","format":"uuid","description":"Location where the kit was processed"},"locationName":{"type":"string","nullable":true,"description":"Name of the location"},"status":{"$ref":"#/components/schemas/ReportStatus"},"uploadedAt":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp when the report file was uploaded"},"createdAt":{"type":"string","format":"date-time","description":"Timestamp when the report record was created"},"updatedAt":{"type":"string","format":"date-time","description":"Timestamp of the most recent update"}},"required":["id","clientId","kitId","reportTypeId","locationId","status","createdAt","updatedAt"]},"ReportStatus":{"type":"string","enum":["PENDING","AVAILABLE","DOWNLOADED"],"description":"Current lifecycle status of a report.\n\n- **PENDING** — Report record created; file has not been uploaded yet\n- **AVAILABLE** — Report file has been uploaded and is ready for download\n- **DOWNLOADED** — Report file has been downloaded at least once via the portal"},"ReportListResponse":{"type":"object","description":"Paginated list of reports.","properties":{"reports":{"type":"array","items":{"$ref":"#/components/schemas/Report"}},"limit":{"type":"integer","description":"Page size used for this request"},"offset":{"type":"integer","description":"Offset used for this request"},"total":{"type":"integer","description":"Total number of reports matching the filter criteria"}},"required":["reports","limit","offset","total"]},"ReportDetailResponse":{"type":"object","description":"Single report detail.","properties":{"report":{"$ref":"#/components/schemas/Report"}},"required":["report"]},"DownloadUrlResponse":{"type":"object","description":"Pre-signed download URL with expiry and report summary.","properties":{"downloadUrl":{"type":"string","format":"uri","description":"Temporary URL to download the report file. Valid for 15 minutes. No authentication header required."},"expiresAt":{"type":"integer","description":"Unix epoch timestamp (seconds) when the download URL expires"},"report":{"type":"object","description":"Summary of the report being downloaded","properties":{"id":{"type":"string","format":"uuid"},"fileName":{"type":"string","nullable":true,"description":"File name of the report"},"status":{"type":"string","enum":["AVAILABLE","DOWNLOADED"]}},"required":["id","status"]}},"required":["downloadUrl","expiresAt","report"]},"HealthResponse":{"type":"object","description":"Health check response.","properties":{"ok":{"type":"boolean","description":"Whether the API is healthy"},"correlationId":{"type":"string","format":"uuid","description":"Request correlation identifier"}},"required":["ok","correlationId"]},"ErrorResponse":{"type":"object","description":"Standard error envelope returned by all error responses.","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Machine-readable error code (e.g. AUTH_REQUIRED, BAD_REQUEST)"},"message":{"type":"string","description":"Human-readable error description"},"correlationId":{"type":"string","format":"uuid","description":"Unique identifier for this request — include when contacting support"}},"required":["code","message","correlationId"]}},"required":["error"]}}}}