Folders

Folders are how Monad organises everything: genres, venues, spaces, shows and performances are all folders with extra data. No session is needed: without one, results are what a member of the public sees. With a logged-in customer's session, members-only folders and member prices are included.

APIDescription
GET api/Folders

Gets the top-level folders.

GET api/Folders/{id}

Gets one folder.

GET api/Folders?page={page}&pageSize={pageSize}

Gets one page of the top-level folders.

GET api/Folders?parentId={parentId}

Gets the folders directly inside a folder.

GET api/Folders?parentId={parentId}&page={page}&pageSize={pageSize}

Gets one page of the folders directly inside a folder.

Shows

Shows are folders tagged as Show. A one-off event is usually both a show and a performance; a show with several dates has performance folders inside it. No session is needed: without one, results are what a member of the public sees. With a logged-in customer's session, members-only folders and member prices are included.

APIDescription
GET api/Shows/{id}

Gets one show.

GET api/Shows?folderId={folderId}&genreId={genreId}&spaceId={spaceId}&venueId={venueId}&fromDate={fromDate}&toDate={toDate}&page={page}&pageSize={pageSize}&searchText={searchText}

Gets shows, optionally filtered, searched and paged. The filters are all optional and apply together. The X-Total-Count response header has the number of matching shows, for paging.

Performances

Performances are folders tagged as Performance: one dated occurrence of an event, with a start and end time. They're usually inside a show, but don't have to be. No session is needed: without one, results are what a member of the public sees. With a logged-in customer's session, members-only folders and member prices are included.

APIDescription
GET api/Performances/{id}

Gets one performance.

GET api/Performances?folderId={folderId}&showId={showId}&genreId={genreId}&spaceId={spaceId}&venueId={venueId}&fromDate={fromDate}&toDate={toDate}&page={page}&pageSize={pageSize}

Gets performances, optionally filtered and paged. The filters are all optional and apply together.

Venues

Venues are folders tagged as Venue. Performances and other folders can take their venue from a venue folder, which is how you find where a performance is. No session is needed: without one, results are what a member of the public sees. With a logged-in customer's session, members-only folders and member prices are included.

APIDescription
GET api/Venues/{id}

Gets one venue.

GET api/Venues?folderId={folderId}

Gets venues: all of them, or only those below a folder.

Spaces

Spaces are folders tagged as Space: a room or area within a venue, such as a studio. Performances and other folders can take their space from a space folder, which is how you find where a performance is. No session is needed: without one, results are what a member of the public sees. With a logged-in customer's session, members-only folders and member prices are included.

APIDescription
GET api/Spaces/{id}

Gets one space.

GET api/Spaces?folderId={folderId}&venueId={venueId}

Gets spaces, optionally only those below a folder or at a venue.

Genres

Genres are folders tagged as Genre. Shows and other folders can take their genre from a genre folder, which is how you find a show's genre. No session is needed: without one, results are what a member of the public sees. With a logged-in customer's session, members-only folders and member prices are included.

APIDescription
GET api/Genres/{id}

Gets one genre.

GET api/Genres?folderId={folderId}

Gets genres: all of them, or only those below a folder.

AccessControlScan

Records scans of access control tokens (the barcodes or QR codes on tickets, or RFID cards and NFC tags) at entrances and checkpoints. Needs a logged-in session for a scanner account linked to an Access Control Location. Send the session as a bearer token: "Authorization: Bearer {sessionId}", using the Id returned by PUT api/Session.

APIDescription
POST api/AccessControlScan

Uploads a batch of scans, e.g. made offline by a handheld scanner, and records them. Each scan is validated against the time it was made, not the time it's uploaded. A scan with an empty SessionId is recorded against this session, and so its Access Control Location. An error (500) if the request has no session.

PUT api/AccessControlScan?accessControlToken={accessControlToken}

Validates one token scanned now at the session's Access Control Location, and records the scan. An error (500) if the request has no session.

AccessControlTokens

Access control tokens: the codes that let a ticket holder in, usually printed as barcodes or QR codes, or stored on RFID cards or NFC tags. Scanners download them so they can validate scans offline. Send the session as a bearer token: "Authorization: Bearer {sessionId}", using the Id returned by PUT api/Session.

APIDescription
GET api/AccessControlTokens?changesSince={changesSince}

Downloads the tokens a scanner needs. The session must be logged in as a user with the Scanner role who is linked to an Access Control Location. The result is the tokens for products that use the Access Control Schemes linked to that location, where the product's performance is within the scheme's active times. An error (500) if the request has no session.

Basket

The basket: what the session is about to buy. Each session has one basket, and an anonymous session is enough. Send the session as a bearer token: "Authorization: Bearer {sessionId}", using the Id returned by PUT api/Session.

APIDescription
GET api/Basket

Gets the session's basket, with packages (multi-buy offers) worked out again. Null if the request has no session.

PUT api/Basket

Adds products, or a package, to the session's basket. Each item group adds a quantity of a product at a concession. ItemId picks a specific item, such as a seat from the seating plan, and applies to every group with a quantity above 0. PackageId applies a package and checks the basket now qualifies for it. Responses: 200 with the request echoed back. 401 if the request has no session. An error (500) if the items are sold out or not on sale, or the basket doesn't qualify for the package.

Cache

The API caches what it returns (folders, shows, performances, prices and so on). Clearing the cache makes the next requests read from the database.

APIDescription
GET api/Cache

Clears the whole cache, for every session. Needs a valid session token: 401 otherwise. Send the session as a bearer token: "Authorization: Bearer {sessionId}", using the Id returned by PUT api/Session.

CustomForms

Custom form values: the extra fields set up in Monad for shows, performances, venues, spaces and genres. No session is needed.

APIDescription
GET api/CustomForms?formDataId={formDataId}

Gets custom form values by form data ID, the ID the other CustomForm endpoints look up.

GET api/Genres/{genreId}/CustomForm

Gets the custom form values for a genre: the extra fields set up for genres in Monad. Responses: 200 with the values. 404 if the genre doesn't exist or has no custom form. An error (500) if genreId isn't a GUID.

GET api/Performances/{performanceId}/CustomForm

Gets the custom form values for a performance: the extra fields set up for performances in Monad. Responses: 200 with the values. 404 if the performance doesn't exist or has no custom form. An error (500) if performanceId isn't a GUID.

GET api/Shows/{showId}/CustomForm

Gets the custom form values for a show: the extra fields set up for shows in Monad. Responses: 200 with the values. 404 if the show doesn't exist or has no custom form. An error (500) if showId isn't a GUID.

GET api/Spaces/{spaceId}/CustomForm

Gets the custom form values for a space: the extra fields set up for spaces in Monad. Responses: 200 with the values. 404 if the space doesn't exist or has no custom form. An error (500) if spaceId isn't a GUID.

GET api/Venues/{venueId}/CustomForm

Gets the custom form values for a venue: the extra fields set up for venues in Monad. Responses: 200 with the values. 404 if the venue doesn't exist or has no custom form. An error (500) if venueId isn't a GUID.

Delivery

Delivery documents (tickets, receipts, PDFs) for the Hardware Interface to print. The server sends the workstation a Deliver XMPP message with the document ID; the workstation gets the document here, prints it, and confirms it. HTTPS only, with "Authorization: MonadHardware {hardwareId}:{password}" using the Hardware ID and password from Admin > System Settings > Hardware. 403 over HTTP; 401 if the header is missing or the credentials are wrong.

APIDescription
GET api/delivery-documents/{deliveryDocumentId}

Gets a delivery document with its content and file name, ready to print. Responses: 200 with the document, or 200 with null if no document has this ID. A 404 means the URL is wrong, not that the document is missing.

POST api/delivery-documents/{deliveryDocumentId}/confirm

Marks a delivery document as delivered. Call it once the document has printed. Responses: 204.

EcwidToken

Single sign-on from Monad to an Ecwid (Lightspeed) store, using the client ID and secret from the Lightspeed integration. Send the session as a bearer token: "Authorization: Bearer {sessionId}", using the Id returned by PUT api/Session.

APIDescription
GET api/EcwidToken

Creates or updates the session's logged-in customer in Ecwid, in the customer group for their current membership, then returns an Ecwid SSO profile for them: the base64 JSON profile, its HMAC-SHA256 signature and a timestamp, separated by spaces. Responses: 200 with the profile. 401 if there's no session token or the session isn't logged in. 404 if the session doesn't exist. 500 if the Lightspeed integration has no Ecwid client ID or secret.

Hardware

Workstation login and configuration for the Monad Hardware Interface. HTTPS only, with "Authorization: MonadHardware {hardwareId}:{password}" using the Hardware ID and password from Admin > System Settings > Hardware. 403 over HTTP; 401 if the header is missing or the credentials are wrong. Requests should also send "User-Agent: MonadHardwareInterface/{version}", which is recorded at login.

APIDescription
POST api/hardware/login

Logs the workstation in and returns its configuration for this session: printers, till drawer, payment terminal, log level, and the XMPP settings it uses to receive print and payment requests. Each call issues a new XMPP password (creating the XMPP account on first login) and records the client version and login time. POST rather than GET for that reason: don't cache it or retry it automatically. Responses: 200 with the configuration. 401 if the Hardware ID or password is wrong. 503 if the server can't reach the XMPP server or its Jabber configuration is missing: try again later.

PUT api/hardware/payment-terminal/pairing

Reports the outcome of a POSitive WebLink terminal pairing that the server asked for (the CNPPairing XMPP message): the terminal's auth token on success, or the error. The Hardware ID comes from the Authorization header, so a workstation can only complete its own pairing request. Responses: 204 when accepted. 400 if RequestId is missing. 409 if the request has expired, has already completed, or isn't this workstation's pending request.

Packages

Packages are multi-buy offers, such as a subscription or a three-show deal: rules that give a discount when the basket holds a qualifying set of items. No session is needed: without one, results are what a member of the public sees. With a logged-in customer's session, members-only folders and member prices are included.

APIDescription
GET api/Packages/{id}

Gets a package, checked against the session's basket: what it offers and, for each gap (a rule the basket doesn't meet yet), the folders on sale that would fill it.

Payments

Card payments and refunds on a customer-present card terminal driven by the Hardware Interface. When a customer pays by card at the till, the server creates a payment request and sends the workstation a CNP XMPP message with its PaymentId. The workstation gets the request, locks it, takes the payment on the terminal, then confirms or cancels the request. Refunds work the same way, with a CNPRefund message. HTTPS only, with "Authorization: MonadHardware {hardwareId}:{password}" using the Hardware ID and password from Admin > System Settings > Hardware. 403 over HTTP; 401 if the header is missing or the credentials are wrong.

APIDescription
GET api/payments/refunds/{refundPaymentId}

Gets a refund to make on the card terminal. Responses: 200 with the refund, or 200 with null if no refund has this ID.

POST api/payments/refunds/{refundPaymentId}/confirm

Confirms that the terminal made the refund: marks it processed, at the server's current time, and stores the terminal's reference on the refund payment. Responses: 200 with the refund. 404 if the refund or its payment doesn't exist.

GET api/payments/requests/{paymentId}

Gets a payment request: the amount to take, the payment type and the customer. Responses: 200 with the request, or 200 with null if it no longer exists (it has been confirmed, cancelled or removed). A 404 means the URL is wrong.

POST api/payments/requests/{paymentId}/cancel

Records that the payment failed or was cancelled on the terminal: the request becomes a payment failure, with the error and the terminal's response in its log. Safe to repeat: if the request has already been cancelled, the existing failure is returned. Responses: 200 with the failure. 404 if there's no such request. 409 if the payment has already been confirmed.

POST api/payments/requests/{paymentId}/confirm

Confirms that the terminal took the payment: records the card details and turns the request into a payment. Fields left out default to: PaymentReference "Manual", PaymentMask and CardType empty, PaymentNetAmount the amount requested. Responses: 200 with the payment. 404 if the request no longer exists, which includes a second confirm of the same request.

POST api/payments/requests/{paymentId}/lock

Locks a payment request so it isn't removed while the payment is in progress. Call it before starting the payment on the terminal. The lock lasts until the request is confirmed or cancelled. Responses: 204.

POST api/payments/requests/{paymentId}/update

Replaces the payment request's RequestData: the payment plugin's own data about the payment in progress, such as the terminal's status. The whole value is replaced. Responses: 200 with the updated request. 404 if the request no longer exists.

Prices

Prices for products. No session is needed: without one these are the public prices, and a logged-in member gets member prices.

APIDescription
GET api/Prices?productId={productId}

Gets a product's prices: the price bands (such as seating areas) and concessions (such as Adult and Child) it's sold at, and the price, booking fee and mandatory donation for each combination. prices, fees and donations are keyed by price band ID, then by concession ID.

Products

Products are what's sold: tickets, memberships, donations, merchandise. A product may belong to a performance or show, but doesn't have to (a donation, say). Tickets are products for a performance, with optional seating plans and extra stock control. No session is needed: without one, results are what a member of the public sees. With a logged-in customer's session, members-only folders and member prices are included.

APIDescription
GET api/Products/{id}

Gets one product. The same for every session.

GET api/Products?folderId={folderId}&performanceId={performanceId}&showId={showId}&genreId={genreId}&spaceId={spaceId}&venueId={venueId}&fromDate={fromDate}&toDate={toDate}&page={page}&pageSize={pageSize}

Gets products, optionally filtered and paged. The filters are all optional and apply together.

Quantities

How many of a product are left, for showing Sold Out, Limited Availability and so on. No session is needed.

APIDescription
GET api/Quantities?productId={productId}

Gets how many of a product are available, and how many there are in all.

Seatplan

Seating plans for seated products. No session is needed.

APIDescription
GET api/Seatplan?productId={productId}

Gets a product's seating plan: the background drawing, and every seat with its position, price band and current status. To book a seat, put its Id in BasketRequest.ItemId.

Session

Sessions. Most endpoints work without one and return what a member of the public would see. The basket needs a session (an anonymous one is enough), and a session logged in as a customer also sees members-only folders and member prices. Send the session as a bearer token: "Authorization: Bearer {sessionId}", using the Id returned by PUT api/Session.

APIDescription
PUT api/Session

Starts or logs in a session. With no session token and no email: creates an anonymous session, whose basket can be filled before the customer logs in. With no token, and an email and password: logs in, returning the customer's session. With a token, and an email and password: logs that session in as the customer, keeping its basket. With a token and no email: returns that session unchanged. An error (500) if the email or password is wrong.

DELETE api/Session

Logs out and ends the session in the bearer token. Responses: 200, or 404 if the request has no session token.

User

Customer accounts. Send the session as a bearer token: "Authorization: Bearer {sessionId}", using the Id returned by PUT api/Session.

APIDescription
PUT api/User

Creates a customer account. The email address is also the login name. This doesn't log the session in: call PUT api/Session with the same email and password for that. Responses: 200 with the new user's ID. An error (500) if the email or password is missing, or an account already has that email address.

GET api/User?userId={userId}

Gets the session's logged-in customer. Needs a valid session token: 401 otherwise. An error (500) if userId isn't the session's own user, or the user doesn't exist.

UserStatuses

The statuses a customer holds, such as memberships. Send the session as a bearer token: "Authorization: Bearer {sessionId}", using the Id returned by PUT api/Session.

APIDescription
GET api/UserStatuses?userId={userId}

Gets the current statuses of the session's logged-in customer. An error (500) if there's no session, or userId isn't the session's own user.