# Create batch serials via API

A **batch serial** groups several individual serial numbers under one batch (parent) serial number. Batch serials are created through the ERP API — send one batch serial together with all the serials that belong to it in a single request.

<p class="callout info">Only creating is exposed through the API. There are no API endpoints for listing, updating or deleting batch serials.</p>

## 1. Authentication

All requests must be authenticated with an OAuth2 access token. Get the token by logging in with your username and password, as described in the [API documentation, section **OAuth2 → Login (Password Grant)**](https://erpapi-central.dewesoft.com/private/documentation/#api-OAuth2-LoginPasswordGrant).

The login call returns an `access_token`, which you send with every request:

```bash
Authorization: Bearer <access_token>
```

<p class="callout warning">The account you log in with needs the **Create batch Serial** permission (`create-batch-serials`). The *admin* and *super-admin* roles have it by default.</p>

## 2. Endpoint

```bash
POST https://erpapi-<tenant>.dewesoft.com/v1/batch-serials
```

Use your own company's API host — for example `https://erpapi-erp.dewesoft.com/v1/batch-serials`. Required headers:

```bash
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json
```

## 3. Request body

The example below creates **one** batch serial with **two** serial items:

```json
{
  "serial_number": "BATCH-0001",
  "related_serials": [
    {
      "serial_1": {
        "sn": "SN-AAA-001",
        "production_date": "2026-08-17 14:12:00"
      },
      "serial_2": {
        "sn": "SN-BBB-001",
        "production_date": "2026-08-17 14:12:00"
      }
    },
    {
      "serial_1": {
        "sn": "SN-AAA-002",
        "production_date": "2026-08-18 08:30:00"
      },
      "serial_2": {
        "sn": "SN-BBB-002",
        "production_date": "2026-08-18 08:30:00"
      }
    }
  ]
}
```

If an item has only one serial number, set `serial_2` to `null` or leave it out:

```json
{
  "serial_1": { "sn": "SN-AAA-003", "production_date": "2026-08-18 09:00:00" },
  "serial_2": null
}
```

## 4. Fields

<table id="bkmrk-fieldrequireddescrip"><tbody><tr><td>**Field**</td><td>**Required**</td><td>**Description**</td></tr><tr><td>`serial_number`</td><td>yes</td><td>Serial number of the batch (parent). Must be unique — a batch serial with the same number cannot be created twice.</td></tr><tr><td>`related_serials`</td><td>no</td><td>List of serial items that belong to this batch. Each entry is one item.</td></tr><tr><td>`related_serials[].serial_1.sn`</td><td>yes</td><td>First serial number of the item.</td></tr><tr><td>`related_serials[].serial_2.sn`</td><td>no</td><td>Second serial number (alias) of the same item. Use `null` when the item has only one serial number.</td></tr><tr><td>`production_date`</td><td>no</td><td>Production date of that serial, format `YYYY-MM-DD HH:MM:SS`.</td></tr></tbody></table>

<p class="callout info">`production_date` is kept for reference on the batch serial record only — it is not written onto the individual serial.</p>

## 5. How serial numbers are matched

For every item in `related_serials` the system looks for an existing serial before creating a new one:

- All serial numbers are converted to **UPPERCASE**, so lower case input is fine.
- An existing serial is matched by its serial number *or* its alias, in either order — `serial_1` and `serial_2` can be swapped.
- If a serial with only one number exists, the second number from the request is saved as its **alias**.
- If no matching serial exists, a new one is created: `serial_1` becomes the serial number and `serial_2` the alias.
- All matched and newly created serials are then linked to the batch serial.

<p class="callout danger">If any of the serial numbers in the request already belongs to a **lot on stock**, the whole request is rejected with the message *"Same serials on stock already exists. Exiting."* and nothing is saved.</p>

## 6. Trying it out

To send a test request, use any API client (Postman, Insomnia, or your own integration): set the method and address from step **2. Endpoint**, add the three headers listed there, and paste the JSON from step **3. Request body**. A successful request returns the created batch serial together with its linked serials.

## 7. Common errors

<table id="bkmrk-messagecause-unauthe"><tbody><tr><td>**Message**</td><td>**Cause**</td></tr><tr><td>Unauthenticated / 401</td><td>Missing, wrong or expired `access_token`.</td></tr><tr><td>This action is unauthorized / 403</td><td>The user does not have the `create-batch-serials` permission.</td></tr><tr><td>The serial number field is required</td><td>`serial_number` is missing from the request body.</td></tr><tr><td>Create resource failed</td><td>A batch serial with this `serial_number` already exists.</td></tr><tr><td>Same serials on stock already exists. Exiting.</td><td>One of the listed serials is already assigned to a lot on stock.</td></tr></tbody></table>