> ## Documentation Index
> Fetch the complete documentation index at: https://aftercaredocs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Start Processing a Discharge Document — POST /upload

> POST /upload accepts a multipart PDF or image, queues it for processing, and returns a documentId and SSE stream URL. Requires authentication.

Send your patient's discharge paperwork to `POST /upload` and AfterCare immediately queues it for processing. The endpoint accepts a single PDF, JPEG, or PNG file up to 15 MB and returns a `documentId` you use to track progress and retrieve the finished recovery plan.

## Request

<ParamField body="document" type="file" required>
  The discharge document to process. Must be a **PDF**, **JPEG**, or **PNG** file no larger than **15 MB**. Send this field as `multipart/form-data`.
</ParamField>

<Note>
  If you upload a document that AfterCare has already seen, it will not reprocess it. Instead, the server returns `200 OK` with the **existing** `documentId` and its current status. Use the returned `processUrl` to check status — if processing already finished, the SSE stream will replay the full event history and close immediately.
</Note>

## Response — 202 Accepted

A fresh upload returns `202 Accepted` with the following fields.

<ResponseField name="documentId" type="string (UUID)">
  The unique identifier for this document. Store it — you need it to stream progress, retrieve medications, and list appointments.
</ResponseField>

<ResponseField name="status" type="string">
  Always `"processing"` on a 202 response. Connect to `processUrl` to receive stage-by-stage progress.
</ResponseField>

<ResponseField name="processUrl" type="string">
  The relative path of the SSE stream for this document, e.g. `/process/550e8400-e29b-41d4-a716-446655440000`. Connect to this URL immediately after uploading to receive real-time pipeline progress.
</ResponseField>

<ResponseField name="originalDocumentUrl" type="string">
  The relative path where you can retrieve the original uploaded file, e.g. `/documents/550e8400-e29b-41d4-a716-446655440000/original`. Useful for displaying or cross-referencing source text alongside extracted data.
</ResponseField>

<ResponseField name="isPlaceholder" type="boolean">
  When `true`, AfterCare is operating in safe-development mode and no real AI calls were made. The returned plan is a static fixture. In production this is always `false`.
</ResponseField>

<ResponseField name="deduplicated" type="boolean">
  `false` on a 202 response — this is a newly accepted document. When the same document has been uploaded before, the server returns `200 OK` with `deduplicated: true` and the existing `documentId` instead of queuing a new pipeline run.
</ResponseField>

<Tip>
  Connect to the SSE stream at `processUrl` **immediately after** receiving the 202 response. The server buffers all past events, so reconnecting later still replays the full history — but listening from the start lets you show your user live progress as each pipeline stage completes.
</Tip>

## Code examples

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.aftercare.app/upload \
    -H "Authorization: Bearer <YOUR_TOKEN>" \
    -F "document=@/path/to/discharge-summary.pdf"
  ```

  ```typescript fetch (TypeScript) theme={null}
  const form = new FormData();
  form.append("document", fileBlob, "discharge-summary.pdf");

  const response = await fetch("https://api.aftercare.app/upload", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${token}`,
    },
    body: form,
  });

  if (!response.ok) {
    throw new Error(`Upload failed: ${response.status}`);
  }

  const { documentId, processUrl } = await response.json();
  console.log("Upload accepted. Document ID:", documentId);
  console.log("Connect to SSE stream at:", processUrl);
  ```
</CodeGroup>

## Sample 202 response

```json theme={null}
{
  "documentId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "processing",
  "processUrl": "/process/550e8400-e29b-41d4-a716-446655440000",
  "originalDocumentUrl": "/documents/550e8400-e29b-41d4-a716-446655440000/original",
  "isPlaceholder": false,
  "deduplicated": false
}
```

## Error responses

| Status | Meaning |
| - | - |
| `400` | No file attached, or the `document` field is missing from the request body. |
| `415` | Unsupported file type. Only `application/pdf`, `image/jpeg`, and `image/png` are accepted. |
| `401` | Missing or invalid Bearer token. |
| `429` | Upload rate limit exceeded. Wait before retrying. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.