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

# Create Case

> POST /cases

## Endpoint

```http theme={null}
POST /cases
```

## Purpose

Creates a case, stores it with `status: "CREATED"`, and queues async processing for the initial outreach.

## Authentication

```http theme={null}
x-api-key: your-api-key
```

## Request Body

### Top-Level Fields

| Field                | Type           | Required | Notes                                                                                           |
| -------------------- | -------------- | -------- | ----------------------------------------------------------------------------------------------- |
| `channel`            | `EMAIL \| SMS` | Yes      | The schema accepts both values, but the implemented workflow is email-based. Use `EMAIL`.       |
| `goal`               | object         | Yes      | Must include `objective`.                                                                       |
| `counterparty`       | object         | Yes      | Must include `address` and `name`.                                                              |
| `senderPersona`      | object         | Yes      | Must include `name`.                                                                            |
| `clientReferenceId`  | string         | No       | Your own identifier for joining Offload cases back to your records.                             |
| `constraints`        | string\[]      | No       | Free-form instructions passed into the worker prompts.                                          |
| `maxAttempts`        | integer        | No       | Defaults to `3`. This is the number of automated follow-up attempts after the initial outreach. |
| `followUpDelayHours` | integer        | No       | Defaults to `72`. Must be a positive integer.                                                   |
| `resultSchema`       | object         | No       | Expected to be JSON Schema-shaped, but only validated as a generic object.                      |
| `clientWebhookUrl`   | string         | No       | Must be a valid URL. Offload sends async events here if present.                                |
| `metadata`           | object         | No       | Opaque JSON echoed in webhook payloads.                                                         |

### `goal`

| Field       | Type               | Required | Notes                                                                   |
| ----------- | ------------------ | -------- | ----------------------------------------------------------------------- |
| `objective` | string             | Yes      | Plain-language outcome you want Offload to reach.                       |
| `knowledge` | `string \| object` | No       | Extra context the worker can use while writing and evaluating messages. |

### `counterparty`

| Field        | Type   | Required | Notes                                                    |
| ------------ | ------ | -------- | -------------------------------------------------------- |
| `address`    | string | Yes      | Current implementation uses this as the email recipient. |
| `name`       | string | Yes      | Human-readable name used in the workflow.                |
| `company`    | string | No       | Optional extra context.                                  |
| `timezone`   | string | No       | Optional extra context.                                  |
| `customData` | object | No       | String-to-string map only.                               |

### `senderPersona`

| Field     | Type   | Required | Notes                        |
| --------- | ------ | -------- | ---------------------------- |
| `name`    | string | Yes      | Sender name used in prompts. |
| `role`    | string | No       | Optional role or title.      |
| `company` | string | No       | Optional company name.       |
| `tone`    | string | No       | Optional tone guidance.      |

## Example Request

```bash theme={null}
curl -X POST "$OFFLOAD_BASE_URL/cases" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $OFFLOAD_API_KEY" \
  -d '{
    "clientReferenceId": "vendor_2048",
    "channel": "EMAIL",
    "maxAttempts": 3,
    "followUpDelayHours": 72,
    "goal": {
      "objective": "Collect a signed W-9 from the vendor",
      "knowledge": {
        "vendorName": "Northstar Supplies",
        "reason": "AP onboarding"
      }
    },
    "counterparty": {
      "address": "ap@northstar.example",
      "name": "Maya Chen",
      "company": "Northstar Supplies",
      "timezone": "America/Los_Angeles",
      "customData": {
        "vendorId": "vendor_2048"
      }
    },
    "senderPersona": {
      "name": "Avery",
      "role": "Accounts Payable",
      "company": "Example Corp",
      "tone": "friendly, concise"
    },
    "constraints": [
      "Email only"
    ],
    "resultSchema": {
      "type": "object",
      "properties": {
        "signedW9Received": { "type": "boolean" },
        "receivedAt": { "type": "string" }
      },
      "required": ["signedW9Received"]
    },
    "clientWebhookUrl": "https://your-app.example/webhooks/offload",
    "metadata": {
      "vendorId": "vendor_2048"
    }
  }'
```

## Successful Response

```json theme={null}
{
  "ok": true,
  "data": {
    "caseId": "4fc5904d-0e44-4ed3-aa57-c4a47ad0ae4f"
  }
}
```

## What Happens Next

After the API returns `201`:

1. the case exists in storage
2. an internal `CASE_CREATED` event is queued
3. the worker later drafts and sends the initial outreach
4. if that send succeeds, the case moves to `RUNNING`

## Errors

| Status | Code                  | Meaning                                            |
| ------ | --------------------- | -------------------------------------------------- |
| `400`  | `INVALID_REQUEST`     | Malformed JSON or validation failure               |
| `401`  | `UNAUTHORIZED`        | Missing or invalid API key                         |
| `403`  | `FORBIDDEN`           | API key exists but is not active                   |
| `429`  | `USAGE_LIMIT_REACHED` | Monthly case cap reached for the current UTC month |
| `500`  | `INTERNAL_ERROR`      | Persistence or queueing failed                     |

<Info>
  API Gateway also applies route throttling. A platform-generated throttling response may also be `429`, but it may not use the standard JSON envelope.
</Info>
