# Add deliveries to a batch

`POST https://api.parasend.com/v1/batches/{id}/deliveries`

Source: https://parasend.com/docs/api/batches/add-deliveries

Authentication: `Authorization: Bearer <API key>` (a `ps_test_` key in test mode, `ps_live_` in live mode).
Send an `Idempotency-Key` header: a retry with the same key returns the first answer.

**Partial-failure pattern (normative):** returns 200 with per-item results
`{index, status: created | failed, delivery_id?, error?}` — the inline `error`
object is byte-identical in shape to top-level errors. A call where every item
fails still returns 200; only request-level faults (auth, malformed JSON,
> 1,000 items) use top-level errors. Unresolved paper addresses are per-item
`needs_address` results, not errors.

## Path parameters

- `id` (string, required): The batch's ID, starting `bat_`.

## Body (application/json)

- `deliveries` (array of object, required)
  - `deliveries[].recipient` (object, required): Who receives a delivery. At least one of `email` and `phone`; `phone` is required at `verification_level: medium`, where the SMS code goes. With `conditional_authentication` true, only the named person can open it: `personal_code` is required at `high` (only an eID with that kennitala passes) and `id_document_number` at `substantial` (only that identity document passes). Without it, the recipient still verifies at the level you set, and their verified identity is recorded and returned to you. A mismatch is the event `delivery.auth_failed`, with the reason `personal_code_mismatch` or `id_document_mismatch`.
    - `deliveries[].recipient.verification_level` (string, required): How the recipient must identify themselves before they see the documents: `high`, eID; `substantial`, a passport or ID-card check with a selfie; `medium`, a one-time code sent by SMS when they open the link; `low`, the link alone. A stronger way is always accepted. One of: `high`, `substantial`, `medium`, `low`.
    - `deliveries[].recipient.name` (string · nullable, optional): The recipient's name as you gave it, trimmed: up to 255 characters, no control characters. It is sealed into the evidence as given and never checked; null when none was given. `verified_name` holds the name from their eID or passport.
    - `deliveries[].recipient.email` (string · email · nullable, optional): The recipient's e-mail address, where e-mail notices and reminders go; null when not given. At least one of `email` and `phone` is required.
    - `deliveries[].recipient.phone` (string · nullable, optional): E.164
    - `deliveries[].recipient.address` (object · nullable, optional)
      - `deliveries[].recipient.address.line1` (string, optional): The first address line, such as the street and number. Required.
      - `deliveries[].recipient.address.line2` (string · nullable, optional): A second address line, or null.
      - `deliveries[].recipient.address.postal_code` (string, optional): The postal code. Required.
      - `deliveries[].recipient.address.city` (string, optional): The town or city. Required.
      - `deliveries[].recipient.address.country` (string, optional): ISO 3166-1 alpha-2
      - `deliveries[].recipient.address.source` (string · nullable, optional): Where the address came from, as you state it: `thjodskra`, Iceland's national registry (Þjóðskrá); `customer_csv`, your own records, imported from a file; `manual`, entered by hand. Default `manual`. One of: `thjodskra`, `customer_csv`, `manual`.
    - `deliveries[].recipient.conditional_authentication` (boolean, optional): When true, only the person you name can open the delivery: at `high` their eID must carry `personal_code`, and at `substantial` their passport or ID card must carry `id_document_number`. Default false: the recipient still identifies themselves at the level, and you get back the identity they used. Default: `false`.
    - `deliveries[].recipient.personal_code` (string · nullable, optional): The recipient's Icelandic personal code (kennitala). Required when `conditional_authentication` is true at `high`.
    - `deliveries[].recipient.id_document_number` (string · nullable, optional): The number of the recipient's passport or ID card. Required when `conditional_authentication` is true at `substantial`.
  - `deliveries[].files` (array of string, required): The files to send: the `fil_` IDs that Upload a file returned.
  - `deliveries[].options` (object, optional)
    - `deliveries[].options.notify_channels` (array of string, optional): How the recipient is told — the invitation and every reminder go to each channel listed; each needs its contact (recipient.email, recipient.phone). Default — e-mail when there is an address, else SMS. Told on both, a failure on one channel bounces the delivery only once the other cannot arrive either. One of: `email`, `sms`.
    - `deliveries[].options.auth_methods` (array of string, optional): Which ways of identifying the recipient to offer within `recipient.verification_level`, in your order of preference. The recipient may always use a way at least as strong as the weakest one you list. Left out: every way the level allows (an SMS code only when the recipient has a phone). One of: `audkenni`, `smart_id`, `sms_otp`, `passkey`, `videoid`, `password`, `link_only`.
    - `deliveries[].options.reminder_policy` (string · nullable, optional): The follow-up policy's ID (`rpol_…`): the reminders this delivery sends while it waits.
    - `deliveries[].options.brand_profile_id` (string · nullable, optional): The brand profile's ID (`bp_…`). One set on the delivery wins over the batch's, and the batch's over the account's default.
    - `deliveries[].options.expires_in_days` (integer, optional): How many days the recipient has to confirm receipt before the delivery expires: a whole number from 1 to 365. Default 30. For a delivery in a batch, the days count from when the batch is sent out.
    - `deliveries[].options.sender_display` (string, optional): What the recipient and the evidence show as the sender. `legal_person` (your organisation's default) shows the organisation, with an opaque reference to the person who sent it; that person's name, personal code and e-mail are not shown. `individual` names the person who sent it as well. Your choice per delivery or template; a personal account is always `individual`. One of: `legal_person`, `individual`.
    - `deliveries[].options.allow_parasend_links` (boolean, optional): Send even though your brand profile's link domain is not working, with Parasend's own links (warning `link_domain_unavailable`). Without it such a delivery is refused with 409 `link_domain_unavailable`. Default: `false`.
    - `deliveries[].options.notice_wording` (object, optional): Which saved wording the first notice uses, per channel: a wording ID, null for Parasend's own, or left out for your organisation's default.
      - `deliveries[].options.notice_wording.email` (string · nullable, optional)
      - `deliveries[].options.notice_wording.sms` (string · nullable, optional)
  - `deliveries[].metadata` (object, optional): Your own key–value pairs, kept with the object and returned as you sent them. Never put personal data here.
  - `deliveries[].title` (string, optional): The subject the recipient sees in the notice and on their page.
  - `deliveries[].message` (string, optional): A plain-text note shown before sign-in. Line breaks are kept. It is not sealed into the evidence.
  - `deliveries[].language` (string, optional): The language of the notice and of the recipient page. One of: `is`, `en`. Default: `"is"`.

## Example: Add two deliveries

```bash
curl -X POST "https://api.parasend.com/v1/batches/bat_01M6R27T8SXWNM911FS53W4S9F/deliveries" \
  -H "Authorization: Bearer $PARASEND_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "deliveries": [
      {
        "recipient": {
          "name": "Anna Björk Jónsdóttir",
          "email": "anna.bjork@example.com",
          "verification_level": "high"
        },
        "files": [
          "fil_01M6R27SZK99V6N6WG4GK15T6R"
        ],
        "title": "Final notice: invoice 2026-114"
      },
      {
        "recipient": {
          "name": "Jón Jónsson",
          "email": "jon.jonsson@example.com",
          "verification_level": "high"
        },
        "files": [
          "fil_01M6R27SZK99V6N6WG4GK15T6R"
        ],
        "title": "Final notice: invoice 2026-115"
      }
    ]
  }'
```

```js
const res = await fetch('https://api.parasend.com/v1/batches/bat_01M6R27T8SXWNM911FS53W4S9F/deliveries', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PARASEND_KEY}`,
    'Idempotency-Key': crypto.randomUUID(),
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    deliveries: [
      {
        recipient: {
          name: 'Anna Björk Jónsdóttir',
          email: 'anna.bjork@example.com',
          verification_level: 'high',
        },
        files: ['fil_01M6R27SZK99V6N6WG4GK15T6R'],
        title: 'Final notice: invoice 2026-114',
      },
      {
        recipient: {
          name: 'Jón Jónsson',
          email: 'jon.jonsson@example.com',
          verification_level: 'high',
        },
        files: ['fil_01M6R27SZK99V6N6WG4GK15T6R'],
        title: 'Final notice: invoice 2026-115',
      },
    ],
  }),
});
const data = await res.json();
```

## Response 200

Per-item results.

```json
{
  "object": "list",
  "data": [
    {
      "index": 0,
      "status": "created",
      "delivery_id": "dlv_01M6R27T9GD2VVC1DVVE1DD6RB"
    },
    {
      "index": 1,
      "status": "created",
      "delivery_id": "dlv_01M6R27T9M7Z1HH1FADRGGMEZK"
    }
  ],
  "created": 2,
  "failed": 0
}
```

Errors: one shape, `{"error": {type, code, message, param, request_id}}`; every code is listed at https://parasend.com/docs/errors.
