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

# Create transaction bundles

> How to create a transaction bundle with transactions, memberships, and donations.

## What you need before creating

Retrieve these group-specific values before making your first `POST /v1/transaction_bundles` call:

| What you need                        | How to get it                                           |
| :----------------------------------- | :------------------------------------------------------ |
| Allowed `payment_method_kind` values | `GET /v1/transaction_settings` → `payment_method_kinds` |
| Default valid `status_id`            | `GET /v1/transaction_settings` → `default_status_id`    |
| Membership price IDs                 | `GET /v1/membership_prices`                             |
| Donation price IDs                   | `GET /v1/donation_prices`                               |
| Campaign codes                       | `GET /v1/code_campaigns`                                |

See [Reference data](/pages/v1/reference/fundraising/reference-data) for details on each lookup endpoint.

## Minimal request: payment only

The only required array is `transactions`. A bundle with just a transaction records the payment without attaching a membership or donation.

```json theme={"system"}
{
  "data": {
    "transactions": [
      {
        "contact_id": 123456,
        "amount": 2000,
        "currency": "eur",
        "payment_method_kind": "CB",
        "date": "2026-03-29T12:59:52+02:00",
        "status_id": 1
      }
    ]
  }
}
```

> Use the `default_status_id` from `GET /v1/transaction_settings` — not a hardcoded `1`.

## With a membership

```json theme={"system"}
{
  "data": {
    "transactions": [
      {
        "contact_id": 123456,
        "amount": 2000,
        "currency": "eur",
        "payment_method_kind": "CB",
        "date": "2026-03-29T12:59:52+02:00",
        "external_transaction_id": 1001,
        "status_id": 1,
        "comment": "Imported via API"
      }
    ],
    "memberships": [
      {
        "contact_id": 123456,
        "membership_price_id": 10,
        "start_date": "2026-01-01T00:00:00Z",
        "end_date": "2026-12-31T00:00:00Z",
        "amount": 2000,
        "amount_initial": 2000,
        "currency": "eur"
      }
    ]
  }
}
```

## With a donation

```json theme={"system"}
{
  "data": {
    "transactions": [
      {
        "contact_id": 123456,
        "amount": 5000,
        "currency": "eur",
        "payment_method_kind": "CB",
        "date": "2026-03-27T18:00:28+02:00",
        "external_transaction_id": 1002,
        "status_id": 1
      }
    ],
    "donations": [
      {
        "contact_id": 123456,
        "amount": 5000,
        "amount_initial": 5000,
        "currency": "eur",
        "donation_price_id": 20
      }
    ]
  }
}
```

## Different payer and beneficiary (third party payer)

`contact_id` in `transactions` is the **payer**. `contact_id` in `memberships` or `donations` is the **beneficiary**. They can be different people.

```json theme={"system"}
{
  "data": {
    "transactions": [
      {
        "contact_id": 123456,
        "amount": 2000,
        "currency": "eur",
        "payment_method_kind": "CB",
        "date": "2026-03-29T10:00:00Z",
        "external_transaction_id": 1003,
        "status_id": 1
      }
    ],
    "memberships": [
      {
        "contact_id": 789012,
        "membership_price_id": 10,
        "start_date": "2026-01-01T00:00:00Z",
        "end_date": "2026-12-31T00:00:00Z",
        "amount": 2000,
        "amount_initial": 2000,
        "currency": "eur"
      }
    ]
  }
}
```

Here contact `123456` paid, but the membership is attributed to contact `789012`.

## Field notes

**`external_transaction_id`** — use this to link the bundle to your own system's record. Must be a plain integer; strings are not supported.

**Dates** — all date fields must be valid ISO 8601 timestamps. Invalid calendar dates (e.g. `2025-02-31`) are rejected.

**`amount_initial`** — always set this to the original price-list amount. When `amount` differs (discount or partial payment), `amount_initial` preserves the original value for reporting.
