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

# Create a Letter

> Create a letter as a draft or send it immediately.

# Create a Letter

Create a physical letter by providing recipient details, a validated address, and the letter content. By default, the letter is sent immediately. Set `send` to `false` to create a draft you can review and send later.

## Request

<ParamField body="recipient" type="string" optional>
  Name of the recipient. Maximum 30 characters.
</ParamField>

<ParamField body="address" type="object" required>
  The recipient's postal address.

  <Expandable title="address properties">
    <ParamField body="street" type="string" required>
      Street name (e.g. "Keizersgracht").
    </ParamField>

    <ParamField body="number" type="string" required>
      House/building number (e.g. "123").
    </ParamField>

    <ParamField body="suffix" type="string" optional>
      Address suffix or addition (e.g. "A", "2nd floor").
    </ParamField>

    <ParamField body="postalcode" type="string" required>
      Postal or ZIP code (e.g. "1015 CJ").
    </ParamField>

    <ParamField body="city" type="string" required>
      City name (e.g. "Amsterdam").
    </ParamField>

    <ParamField body="country" type="string" required>
      ISO 3166-1 alpha-2 country code (e.g. "NL", "BE", "DE").
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="content" type="string" required>
  The letter body text. Line breaks (`\n`) are preserved for formatting.
</ParamField>

<ParamField body="send" type="boolean" optional default="true">
  Whether to send the letter immediately. Set to `false` to create a draft. Drafts can be updated with `PATCH /api/v1/letters/:id` and sent with `POST /api/v1/letters/:id/send`.
</ParamField>

## Response

<ResponseField name="id" type="string">
  The unique letter ID.
</ResponseField>

<ResponseField name="status" type="string">
  The letter status — `"processing"` when sent immediately, `"draft"` when created as a draft.
</ResponseField>

<ResponseField name="balance_cents" type="integer">
  Your remaining balance in cents after this letter. Only present when `send` is `true`.
</ResponseField>

## Examples

<RequestExample>
  ```bash cURL — Send immediately theme={null}
  curl -X POST https://thepostalcompany.com/api/v1/letters \
    -H "Authorization: Bearer tpc_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "recipient": "Jane Doe",
      "address": {
        "street": "Keizersgracht",
        "number": "123",
        "postalcode": "1015 CJ",
        "city": "Amsterdam",
        "country": "NL"
      },
      "content": "Dear Jane,\n\nThis is a letter sent via the API.\n\nBest regards"
    }'
  ```

  ```bash cURL — Create draft theme={null}
  curl -X POST https://thepostalcompany.com/api/v1/letters \
    -H "Authorization: Bearer tpc_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "recipient": "Jane Doe",
      "address": {
        "street": "Keizersgracht",
        "number": "123",
        "postalcode": "1015 CJ",
        "city": "Amsterdam",
        "country": "NL"
      },
      "content": "Dear Jane,\n\nThis is a draft letter.\n\nBest regards",
      "send": false
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://thepostalcompany.com/api/v1/letters", {
    method: "POST",
    headers: {
      "Authorization": "Bearer tpc_your_api_key",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      recipient: "Jane Doe",
      address: {
        street: "Keizersgracht",
        number: "123",
        postalcode: "1015 CJ",
        city: "Amsterdam",
        country: "NL",
      },
      content: "Dear Jane,\n\nThis is a letter sent via the API.\n\nBest regards",
    }),
  });

  const data = await response.json();
  console.log(data.id); // letter ID
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://thepostalcompany.com/api/v1/letters",
      headers={"Authorization": "Bearer tpc_your_api_key"},
      json={
          "recipient": "Jane Doe",
          "address": {
              "street": "Keizersgracht",
              "number": "123",
              "postalcode": "1015 CJ",
              "city": "Amsterdam",
              "country": "NL",
          },
          "content": "Dear Jane,\n\nThis is a letter sent via the API.\n\nBest regards",
      },
  )

  data = response.json()
  print(data["id"])  # letter ID
  ```
</RequestExample>

<ResponseExample>
  ```json 201 — Sent immediately theme={null}
  {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "processing",
    "balance_cents": 1000
  }
  ```

  ```json 201 — Draft created theme={null}
  {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "draft"
  }
  ```

  ```json 400 — Validation error theme={null}
  {
    "error": "address.country must be a valid ISO 3166-1 alpha-2 code (e.g. NL, BE, DE)"
  }
  ```

  ```json 401 — Unauthorized theme={null}
  {
    "error": "Invalid or revoked API key"
  }
  ```

  ```json 402 — Insufficient balance theme={null}
  {
    "error": "Insufficient balance",
    "balance_cents": 100,
    "letter_price_cents": 250
  }
  ```
</ResponseExample>

## Error codes

| Status | Description                                                          |
| ------ | -------------------------------------------------------------------- |
| `400`  | Invalid request body — missing or invalid fields                     |
| `401`  | Missing, invalid, or revoked API key                                 |
| `402`  | Insufficient balance to send the letter (only when `send` is `true`) |
| `500`  | Internal server error                                                |
