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

# Voucher sets

> Create voucher sets, fill their content and follow their status.

## What a voucher set is

A voucher set is a collection of vouchers that share **content** (what consumers see), a **voucher kind** (`code` or `link`), a link format and a **schedule**. Examples: "€5 ride credit, Q4" with single-use codes, or "Free unlock" with personal deep links.

A set has three parts that change in different ways:

| Part | Fields | How it changes |
| - | - | - |
| Content | `live` (approved), `draftContent` (your working copy) | Only through [change requests](https://docs-provider.voucher.allride.io/provider/change-requests.md) that AllRide approves |
| Inventory | Vouchers, uploads | Directly, any time the set is not suspended or archived ([Vouchers and uploads](https://docs-provider.voucher.allride.io/provider/vouchers-and-uploads.md)) |
| Schedule and status | `status`, `activeFrom`, `deactivateAt` | Directly, with lifecycle commands ([Activation and scheduling](https://docs-provider.voucher.allride.io/provider/activation-and-scheduling.md)) |

Create a set in `draft`; `content` becomes its draft (partial content is fine):

```bash theme={null}
curl -sS -X POST "$VOUCHER_API_BASE_URL/provider/v1/voucher-sets" \
  -H "Authorization: Bearer $VOUCHER_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "internalName": "Ride credit EUR 5 - Q4",
    "voucherKind": "code",
    "content": {
      "name": {"de": "5 € Fahrguthaben", "en": "€5 ride credit"},
      "faceValue": {"value": 500},
      "categoryId": 7017
    }
  }'
```

`internalName` (1-120 characters) is your own label and never shown to consumers; change it any time with `PATCH`. Creating a set also creates its [stock alert rule](https://docs-provider.voucher.allride.io/provider/stock-and-alerts.md). Edit the draft with `PATCH /provider/v1/voucher-sets/{voucherSetId}` and `{"draftContent": {…}}` (fields merge) as long as no change request is open.

`voucherKind` can change only while the set is a `draft` without vouchers; afterwards → 409 `voucher-kind-locked`.

## Content fields

Every content field is consumer-visible and changes only through an approved change request. Texts are localised maps that must include your partner's default locale.

| Field | Type and limits | Notes |
| - | - | - |
| `name` | Text, 80 characters per locale | **Required.** Card title |
| `summary` | Text, 160 | One-liner |
| `bullets` | Up to 5 texts of 120 | Short lines on the card |
| `description` | Markdown, 5,000 | Restricted Markdown ([content rules](https://docs-provider.voucher.allride.io/provider/content-rules.md)) |
| `howToRedeem` | Up to 8 texts of 300 | Redemption steps |
| `termsText` | Markdown, 20,000 | **Required.** The voucher terms of this set (`terms-required` at `termsText`) |
| `valueLabel` | Text, 30 | Display value, for example "€5 off" |
| `faceValue` | Money | Nominal value, used in statistics |
| `categoryId` | Id | **Required.** An active [category](https://docs-provider.voucher.allride.io/api-reference/provider-categories-list.md) |
| `linkTemplate` | Link Template | `code` sets only: a link rendered next to each code ([Dynamic links](https://docs-provider.voucher.allride.io/provider/link-templates.md)) |
| `allowedLinkHosts` | Up to 10 hosts | Required when an https link can occur |
| `allowedLinkSchemes` | Up to 3 app schemes | For custom app deep links |
| `brandingOverride` | Colours, `logoAssetId`, `heroImageAssetId` | Per-set look |
| `countries` | Country codes | Empty means all |
| `extensions` | JSON | Display hints for consumers (keys `x-*` or `<consumerSlug>.*`) |
| `metadata` | JSON | Provider metadata visible to consumers (16 KiB) |

Required fields are checked when you submit; drafts may be incomplete.

A voucher set has **no terms URL and no app links**. Your general terms and privacy pages (`termsUrl`, `privacyUrl`) and your App Store and Google Play links (`appLinks`) belong to your [provider profile](https://docs-provider.voucher.allride.io/provider/profile-and-branding.md): landing pages show them in the voucher details and next to every issued voucher. A voucher set has **no button label** either: landing pages always show the standard "Redeem". Sending `termsUrl`, `appLinks` or `ctaLabel` in voucher set content fails with 400 `data-failed-validation` and the item `unknown-field`.

## Statuses

`status` is the **effective** status: a scheduled set whose `activeFrom` has passed reads `active` at once, even before the schedule has been applied (which happens within about a minute).

| Status | Meaning | Consumers |
| - | - | - |
| `draft` | Not yet approved | Invisible |
| `pending-approval` | The first change request is under review | Invisible |
| `inactive` | Approved content, not live | Invisible |
| `scheduled` | Activation planned at `activeFrom` | `availability: upcoming` |
| `active` | Live | `availability: active` |
| `deactivation-scheduled` | Live until `deactivateAt` | `availability: deactivation-scheduled` |
| `suspended` | Stopped by AllRide | Invisible |
| `archived` | Terminal | Invisible |

```mermaid theme={null}
stateDiagram-v2
  [*] --> draft
  draft --> pending_approval: submit create change request
  pending_approval --> draft: rejected or withdrawn
  pending_approval --> inactive: approved
  inactive --> active: activate
  inactive --> scheduled: schedule activation
  scheduled --> active: activeFrom reached
  scheduled --> inactive: cancel schedule
  active --> deactivation_scheduled: schedule deactivation
  deactivation_scheduled --> active: cancel schedule
  active --> inactive: deactivate
  deactivation_scheduled --> inactive: deactivate or deactivateAt reached
  inactive --> suspended: AllRide
  scheduled --> suspended: AllRide
  active --> suspended: AllRide
  deactivation_scheduled --> suspended: AllRide
  suspended --> inactive: AllRide unsuspends
  draft --> archived: archive
  inactive --> archived: archive
  archived --> [*]
```

**Suspension** is AllRide-only (for example while terms are reviewed). You receive the `voucher-set-suspended` webhook with `suspensionReason`. While suspended you cannot activate, schedule, archive, submit content or add vouchers (409 `voucher-set-suspended`). When AllRide lifts it, the set is `inactive` with no schedule; schedule it again.

## Archiving

`POST /provider/v1/voucher-sets/{voucherSetId}:archive` archives a `draft` or `inactive` set; deactivate an active set first.

* Archiving is **terminal**: the set cannot be activated, changed or receive vouchers again (409 `voucher-set-archived`).
* Vouchers and redemptions stay readable for reporting; the stock alert rule is disabled.
* Uploads in `pending-upload` or `validated` are cancelled; an upload still validating or importing → 409 `voucher-upload-in-progress`. An open change request → 409 `change-request-open` (withdraw it first).

## Related

* [Change requests and approval](https://docs-provider.voucher.allride.io/provider/change-requests.md)
* [Activation and scheduling](https://docs-provider.voucher.allride.io/provider/activation-and-scheduling.md)
* [Vouchers and uploads](https://docs-provider.voucher.allride.io/provider/vouchers-and-uploads.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.