> ## Documentation Index
> Fetch the complete documentation index at: https://next-developers.opencard.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Payload Formats

> Payload formats for receipt provider callbacks to OpenCard — required headers, HMAC signatures, and XML receipt body for resolved and deleted callback events.

When you send a collected receipt to OpenCard, the body format depends on the callback type configured for your integration.

***

## Headers (always required)

| Header                 | Value                                                 |
| ---------------------- | ----------------------------------------------------- |
| `X-Event`              | `CallbackRequestResolved` or `CallbackRequestDeleted` |
| `X-CallbackRequest-Id` | Callback request ID from OpenCard                     |
| `X-Data-Signature`     | `HMAC-SHA256(raw_body, client_secret)`                |

***

## CallbackRequestResolved — XML receipt

Content-Type: `application/xml`

OpenCard parses receipt XML to extract:

* True VAT rates and amounts
* Line items (if present in receipt)
* Receipt file for storage

Delivery note XML (partner code transactions) uses a different VAT extraction path.

***

## CallbackRequestResolved — JSON

Content-Type: `application/json`

Structured receipt data when callback type is JSON.

***

## CallbackRequestDeleted

Empty or minimal body. Indicates the match was cancelled or expired. OpenCard marks the callback request as deleted.

***

## Signature calculation

```python theme={null}
import hmac, hashlib

signature = hmac.new(
    client_secret.encode(),
    request_body_bytes,  # raw bytes, not re-serialized
    hashlib.sha256
).hexdigest()
# Set as X-Data-Signature header
```

```javascript theme={null}
const crypto = require('crypto');
const sig = crypto.createHmac('sha256', clientSecret)
  .update(rawBodyBuffer)
  .digest('hex');
```

<Warning>
  Hash the **raw request body bytes** exactly as received. Re-serializing JSON will break the signature.
</Warning>

***

## After successful delivery

OpenCard fires these webhooks to the EMS (if subscribed):

**`receipt.fetched`**

```json theme={null}
{
  "url": "https://api.opencard.io/files/receipts/abc123",
  "content_type": "application/pdf",
  "expiration_time": "2022-10-02 11:12:14",
  "purchase_merchant": "Coop",
  "original_amount": 109.38,
  "original_currency": "SEK",
  "transaction": { "id": "10", "card_issuer": "nordea" }
}
```

**`transaction.true.vat`** — corrected VAT from merchant receipt

**`transaction.line.items`** — purchase line items

OpenCard handles EMS delivery — you only send receipts to OpenCard.
