Swarmtix Help Center
Tool Reference

swarmtix_discounts_create

Creates a private discount code on an event, taking either an amount or a percentage off

swarmtix_discounts_create

Creates a discount code on an event and returns it. The code is private: it reduces the price only for a buyer who types it at checkout, and it is not advertised on the event page.

When you would reach for it

  • A partner or sponsor code for a specific audience.
  • An early-bird code with an end date and a redemption limit.
  • A speaker or staff code taking a fixed amount off one ticket tier.

Scope

discounts:write

This has a scope of its own rather than sharing events:write, because a discount is the one thing in this catalog that changes what a buyer pays. An organizer who wants an assistant to set an event up should not have to hand it the ability to price that event down as well.

Creating a code takes no money and gives none away on its own — it is redeemed at checkout, by a buyer, against tickets that are on sale. But it is the closest this catalog gets to the money, so it is the place the arguments are checked hardest.

Calling this twice with the same code creates two offers that both answer to it. It is not idempotent, and there is no delete tool — a duplicate is deactivated in the dashboard. Check swarmtix_discounts_list before retrying a call that timed out.

Parameters

NameTypeRequiredDefaultDescription
eventstringYesThe event's id (a GUID) or its URL slug.
codestringYesThe code a buyer types at checkout. Letters, digits, dots, dashes and underscores, up to 100 characters.
endsAtstringYesWhen the offer stops being accepted, in ISO 8601 form, read as UTC when no offset is given.
amountOffnumberNoHow much to take off each ticket, in the event's currency. Give this or percentOff, not both.
percentOffnumberNoWhat percentage to take off each ticket, from 1 to 100. Give this or amountOff, not both.
startsAtstringNonowWhen the offer starts being accepted, in ISO 8601 form.
ticketTypestringNoevery typeThe id of the one ticket type this applies to, from swarmtix_ticket_types_list.
usesLimitintegerNono limitHow many times in total the code may be redeemed. 1 to 1,000,000.

Exactly one of amountOff and percentOff is required. They are stored in one place with a flag saying which kind the offer is, so a request carrying both would silently keep one and throw the other away — it is refused instead.

endsAt is required and must be after the start. There is no "runs until sales end" option here: the setting that means that reads the furthest-future date across the whole system rather than this event's, so this tool always writes an explicit end date.

The offer is named after the code.

What the code may contain

Letters, digits, dots, dashes and underscores. That is narrower than what the product itself accepts, on purpose: a code that passes this check cannot then be rejected further down with a message this layer is not allowed to repeat, leaving you a generic failure for something you could have fixed.

Example call

{
  "name": "swarmtix_discounts_create",
  "arguments": {
    "event": "spring-summit-2027",
    "code": "PARTNER20",
    "percentOff": 20,
    "endsAt": "2027-09-30T23:59:00Z",
    "usesLimit": 50
  }
}

What comes back

The offer as stored:

{
  "id": "a15c9e02-3b7d-4c61-8f95-6d24e0a7b3c8",
  "eventId": "3b6f81ce-04a2-4d97-b5e8-7c10924af3d6",
  "name": "PARTNER20",
  "code": "PARTNER20",
  "amountOff": 0,
  "percentageOff": 20,
  "appliesToAllTicketTypes": true,
  "unlimited": false,
  "usesLimit": 50,
  "startDate": "2027-01-14T11:06:22",
  "endDate": "2027-09-30T23:59:00",
  "active": true
}
FieldWhat it is
idThe new offer's id
eventIdThe event it was created on
nameThe offer's name — the code
codeThe code a buyer types
amountOffThe fixed reduction. 0 when the offer is a percentage.
percentageOffThe percentage reduction. 0 when the offer is a fixed amount.
appliesToAllTicketTypesWhether it covers every ticket type on the event
ticketTypeIdThe single ticket type it covers, when it is scoped to one
unlimitedWhether it has no redemption limit
usesLimitThe limit, when there is one
startDate, endDateThe window it is accepted between
activeWhether the offer is live

What happens when you call it

  1. The event is resolved through the edit gate.
  2. code is validated against the character rule above, and endsAt and startsAt are parsed as UTC when they carry no offset.
  3. Exactly one of amountOff and percentOff is required, and the value is rounded to two decimals.
  4. ticketType, if given, is checked against this event. Nothing downstream does that: the offer is written with whatever id it is handed, so an id from another organisation's event would be stored against yours and two events would share a discount row neither organiser could account for.
  5. The offer is created as a coded discount — redeemed by typing the code, not advertised on the event page. The public kind is a marketing decision rather than a configuration one, and is not this connection's to take.
  6. The stored row is read back, checked for belonging to this event, and returned.

Troubleshooting

"amountOff is not valid: neither amountOff nor percentOff was given. Expected one of them, saying how much the code takes off."

One of the two is required.

"amountOff is not valid: both amountOff and percentOff were given. Expected only one of them, because an offer takes off an amount or a percentage but not both."

Send one. Sending both would have quietly kept one and dropped the other.

"amountOff is not valid: it was 0. Expected an amount greater than 0, or percentOff instead."

Zero is not "no discount" here — it is the flag that says the offer is a percentage, and the percentage would be zero too. Use a real amount, or percentOff.

"percentOff is not valid: it was 150. Expected an amount from 0 to 100."

Percentages run from 1 to 100.

"percentOff is not valid: it was 0.5. Expected a percentage from 1 to 100."

Fractions below 1% are not accepted.

"endsAt is not valid: "soon" is not a date and time. Expected a date and time in ISO 8601 form."

Use an ISO 8601 instant — 2027-09-30T23:59:00Z.

"endsAt is not valid: it is not after startsAt. Expected a date and time after the offer starts."

The window has no duration. When startsAt is omitted the offer starts immediately, so endsAt must be in the future.

"code is not valid: it contains " ". Expected a code of letters, digits, dots, dashes or underscores."

The code has a space or another disallowed character. Letters, digits, ., - and _ only.

"ticketType is not valid: there is no ticket type with that id on this event. Expected the id of a ticket type on this event, or nothing to cover all of them."

The ticket type id does not name an active type on that event. List them with swarmtix_ticket_types_list, or omit the argument to cover every type.

"usesLimit is not valid: it was 0. Expected a whole number from 1 to 1000000."

Omit usesLimit for an unlimited code rather than sending zero.

"Event not found, or this connection does not have access to it."

The event does not exist, it belongs to another organisation, or this organizer may read it but not edit it.

"This connection is not authorized for discounts:write. Reconnect and grant it to use this tool."

Reconnect and approve discounts:write. It is a separate permission from events:write on purpose.

The code does not work at checkout

Check it with swarmtix_discounts_check_code — it reports which of the four reasons applies in a sentence.

Two offers now share the same code

Expected after a retry. Deactivate one in the dashboard; the MCP catalog has no delete tool.

Use cases

  • Partner codes with a limit and an expiry
  • Speaker comps — a fixed amount off one ticket tier
  • Early-bird pricing without creating a second ticket type
  • Campaign codes created and then verified in two calls

On this page