---
description: "Create and manage event promo codes, read used-code labels, and queue invitations with per-recipient results."
group: "Resources"
order: 23
---

# Promo codes and invitations

Configure event promotions and issue invitations with explicit recipient results.

## Read used-code labels {#read-used-code-labels}

`GET /{event_id}/promocodes/all_data.json` and `GET /promocodes/all_data.json` return cached maps from code UUID to visible code, scoped to event or accessible companies. The query includes codes referenced by orders; unused configured codes do not appear. An empty map can serialize as `[]`. Use validators to handle 304 responses.

The legacy `promocodes/index.json` list produced malformed JSON during local discovery: PHP notices and HTML appeared despite a JSON content type and HTTP 200. It is excluded from the supported JSON reference. There is currently no advertised full promo-detail catalog endpoint; use the organizer promotion view for that workflow.

## Create and edit {#create-and-edit}

POST `/{event_id}/promocodes/add/{type}.json` creates a single code. Types are `products` (product-specific price) and `prd_prct` (percentage, using `Promocode.discount`). Submit `Promocode` plus event-owned `ProductsPromocode` rows.

```
{
  "Promocode":{"code":"WELCOME","active":1,"stock":100},
  "ProductsPromocode":[{"product_id":"22222222-2222-4222-8222-222222222222","active":1,"max":1,"price":"0.00"}]
}
```

Code length is at most 25 characters. Other allowed settings include discount, expiry, budget, guaranteed stock, invoice allowance and hiding other products. Product links use `product_id`, `active`, `max` and `price`. A promo link's zero maximum has different semantics from the waiting-list invitation's required 1–50 amount.

PUT `/{event_id}/promocodes/edit/{promocode_id}.json` edits an authorized code with the same envelopes. Single-code create/edit success returns `{"ok":true,"id":"..."}`. Validation and save failures have JSON error handling. Batch `code_amount` creation uses a legacy success redirect and is not part of this single-code result contract.

## Activate or remove {#activate-or-remove}

PUT `/{event_id}/promocodes/activate/{promocode_id}.json`, `deactivate/{promocode_id}.json` or `delete/{promocode_id}.json`. Referenced codes can be protected from deletion. Inspect `ok`/`error` even on HTTP 200. Bulk deletion and company-wide promotion forms retain separate legacy rendering and need their own response verification.

## Invite recipients {#invite-recipients}

Read `GET /{event_id}/promocode_invites/view/{promocode_id}.json` for `MailQues` history (up to 500 rows), `limit` and `remaining`. POST `/{event_id}/promocode_invites/add/{promocode_id}.json` with recipient rows.

```
{"invites":[{"firstname":"Alex","lastname":"Example","email":"alex@example.com"}]}
```

Firstname and a valid email are required. At most 100 recipients are accepted per request; duplicate email addresses are rejected. An organization awaiting clearance can have a three-invitation organization-wide allowance.

The result contains `status` (`ok`, `partial`, `error`), `queued`, `queued_indices`, `rejected`, `message`, `limit` and `remaining`. Rejected rows have an index/reason. Correct and resend only rejected rows; don't resend recipients already queued. A wholly rejected validation request can return 422 and a storage failure 500. Queue acceptance does not prove delivery.

For invitations linked to waiting-list entries, use [waiting-list invitations](/en-us/docs/waiting-lists.md) so prior invitation codes and entry links are updated together.

## Company and batch workflows {#company-and-batch-workflows}

The [coverage table](/en-us/docs/api-coverage.md#organizer-workflows) records company-wide promo management, batch creation and full-catalog limits. Create individual event codes when you need a structured returned ID; keep that ID because used-label maps exclude unused codes.
