---
title: Записване на измервания
description: Изпращане на измервания за батерия към публикуван паспорт. Само за паспорти на батерии; 1–500 измервания на извикване. Поддържа Idempotency-Key.
canonical: "https://www.tracepass.eu/bg/docs/capture-measurements"
locale: bg
source: "https://www.tracepass.eu/bg/docs/capture-measurements"
---

# Записване на измервания

> Изпращане на измервания за батерия към публикуван паспорт. Само за паспорти на батерии; 1–500 измервания на извикване. Поддържа Idempotency-Key.

```http
POST /api/v1/passports/{id}/measurements
```

**Само за паспорти на батерии** (Регламент (ЕС) 2023/1542, чл. 77, Приложение XIII, точка 4 — данни от употреба). Паспортът трябва да е публикуван; чернова или спрян паспорт връща 422 `passport_not_active`. Паспорт, който не е за батерия, връща 422 `not_a_battery`. Изпращайте 1–500 измервания на извикване, всяко като `{ fieldKey, value, measuredAt, externalId?, unit? }` — `measuredAt` е времеви печат по ISO 8601 и не трябва да е в бъдещето; `value` трябва да е най-много **16 KB след сериализация** (по-голяма стойност връща 400 `invalid_value`). Приемливите `fieldKey` са полетата за данни от употреба по Приложение XIII, точка 4: `stateOfHealth`, `stateOfCertifiedEnergy`, `remainingCapacity`, `remainingPowerCapability`, `remainingRoundTripEfficiency`, `evolutionOfSelfDischargeRate`, `currentInternalResistancePack`, `capacityFade`, `powerFade`, `internalResistanceIncrease`, `dynamicRatedCapacity`, `dynamicPowerCapability`, `dynamicInternalResistance`, `dynamicEnergyRoundTripEfficiency`, `dynamicExpectedLifetimeCycles`, `numberOfFullEquivalentChargingCycles`, `numberOfChargingEvents`, `currentStateOfCharge`, `negativeEvents`, `temperatureConditionsHistorical`.

Всяко измерване се съхранява. Най-новото по поле (по `measuredAt`) става текущата стойност на полето в паспорта и задава `dynamicDataAsOf`. По-старо измерване, пристигнало по-късно, се пази в историята, но не презаписва по-нова текуща стойност. Предоставянето на `externalId` прави измерването **идемпотентно**: повторно изпращане се отчита в `duplicates`, без да се съхранява или таксува отново. Поддържа се и заглавният параметър `Idempotency-Key` — същият ключ + същото тяло преизпълнява кеширания отговор за 24 ч.; същият ключ + различно тяло връща 422. OAuth scope: `passports:write`.

`batteryStatus` **не** е поле за измерване — промените в жизнения цикъл се извършват чрез таблото за управление. Батерия, подготвена за повторна употреба, промяна на предназначението или вторично производство, получава нов паспорт, свързан с оригиналния чрез `lineage` при създаване на паспорт. Поле, което Регламентът ограничава за дадена категория батерии, връща 422 `field_not_applicable` (напр. `stateOfCertifiedEnergy` е недостъпно за LMT батерии; петте метрики за остатъчен капацитет от Приложение VII, Част A са недостъпни за EV батерии). Алтернативна форма на адресиране е налична на `POST /api/v1/passports/by-serial/{serial}/measurements` — същото тяло, същият отговор. При несигурен сериен номер добавете `?gtin=<gtin>` за разграничаване.

Измерванията се броят спрямо **месечния** лимит на плана (`maxMeasurementsPerMonth`), а не спрямо дневния лимит за v1 записвания. Платените планове продължават да приемат и броят измервания след лимита без допълнително заплащане; Free планът спира при достигане на лимита. Преглеждането на паспорт никога не се таксува.

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Authorization` | header | string | yes | `Bearer <token>` — или `tp_` API ключ (Developer → API Keys; най-просто, за server-to-server), или OAuth 2.0 access token (Developer → OAuth Apps; за приложения, авторизирани от потребител, scoped и отзоваеми). Страницата Authentication съдържа пълния OAuth поток и списъка със scopes. |
| `id` | path | ObjectId | yes | ID на паспорта. |
| `Idempotency-Key` | header | string | no | Незадължителен ключ за идемпотентност (UUID v4 или произволен непрозрачен низ ≤ 64 символа). Същият ключ + същото тяло преизпълнява кеширания отговор за 24 ч.; същият ключ + различно тяло връща 422. |

## Examples

```bash
curl -sS -X POST \
  https://app.tracepass.eu/api/v1/passports/6650b2c3d4e5f6a7b8c9d0e1/measurements \
  -H "Authorization: Bearer tp_REDACTED_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "measurements": [
      {
        "fieldKey": "stateOfHealth",
        "value": 96.4,
        "measuredAt": "2027-03-01T06:00:00Z",
        "externalId": "bms-7781-2027-03-01"
      },
      {
        "fieldKey": "numberOfFullEquivalentChargingCycles",
        "value": 112,
        "measuredAt": "2027-03-01T06:00:00Z"
      }
    ]
  }'
```

```typescript
const res = await fetch(
  `https://app.tracepass.eu/api/v1/passports/${id}/measurements`,
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.TRACEPASS_API_KEY}`,
      "Content-Type": "application/json",
      "Idempotency-Key": crypto.randomUUID(),
    },
    body: JSON.stringify({
      measurements: [
        {
          fieldKey: "stateOfHealth",
          value: 96.4,
          measuredAt: new Date().toISOString(),
          externalId: "bms-7781-2027-03-01",
        },
        {
          fieldKey: "numberOfFullEquivalentChargingCycles",
          value: 112,
          measuredAt: new Date().toISOString(),
        },
      ],
    }),
  },
);
const result = await res.json();
console.log("accepted:", result.accepted, "stored:", result.storedCount);
```

```python
import os, uuid, requests
res = requests.post(
    f"https://app.tracepass.eu/api/v1/passports/{passport_id}/measurements",
    headers={
        "Authorization": f"Bearer {os.environ['TRACEPASS_API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "measurements": [
            {
                "fieldKey": "stateOfHealth",
                "value": 96.4,
                "measuredAt": "2027-03-01T06:00:00Z",
                "externalId": "bms-7781-2027-03-01",
            },
            {
                "fieldKey": "numberOfFullEquivalentChargingCycles",
                "value": 112,
                "measuredAt": "2027-03-01T06:00:00Z",
            },
        ]
    },
)
res.raise_for_status()
data = res.json()
print("accepted:", data["accepted"], "stored:", data["storedCount"])
```

## Responses

### 200 — Измерванията са приети

```json
{
  "accepted": 2,
  "storedCount": 2,
  "materializedCount": 2,
  "duplicates": 0,
  "measurementIds": [
    "6750a1b2c3d4e5f6a7b8c9d0",
    "6750a1b2c3d4e5f6a7b8c9d1"
  ]
}
```

### 200 — Дублиращо се измерване пропуснато (повторен externalId)

```json
{
  "accepted": 1,
  "storedCount": 0,
  "materializedCount": 0,
  "duplicates": 1,
  "measurementIds": []
}
```

### 400 — Невалиден ключ на поле (batteryStatus)

```json
{ "error": "invalid_field_key", "details": "batteryStatus is not a measurement field" }
```

### 400 — Стойността е твърде голяма (> 16 KB)

```json
{ "error": "invalid_value", "details": "value exceeds 16 KB serialised limit" }
```

### 402 — Месечен лимит за измервания на Free плана е достигнат

```json
{ "error": "measurement_allowance_exceeded" }
```

### 422 — Не е паспорт на батерия

```json
{ "error": "not_a_battery" }
```

### 422 — Паспортът не е публикуван

```json
{ "error": "passport_not_active" }
```

## Related

- [История на измерванията](https://www.tracepass.eu/bg/docs/list-measurements.md)
- [Последни измервания](https://www.tracepass.eu/bg/docs/latest-measurements.md)
- [Създаване на паспорт (lineage)](https://www.tracepass.eu/bg/docs/create-passport.md)
