Loby API

The base URL to send all API requests ishttps://api.loby.io. HTTPS is required for all API requests.

The Loby API follows RESTful conventions when possible, with most operations performed via GET, POST, PATCH, and DELETE requests. Request and response bodies are encoded as JSON and therefore requests need to include the headercontent-type: application/jsonwhen appropriate.

Use Loby API to retrieve, create or modify data stored in your Loby account programmatically and to create custom integrations.

Versions

There is currently one version, which is reachable via:https://api.loby.io/v1

Error Codes

Authentication

Loby API uses API access tokens to authenticate requests. You can view and manage your API keys in Loby.

Your API keys carry many privileges, so be sure to keep them secure! Do not share your secret API key in publicly accessible areas such as GitHub, client-side code, and so forth.

All API requests must be made over HTTPS. Calls made over plain HTTP will fail. API requests without authentication will also fail.

The API key should be passed as a Bearer authorization header, e.g.:

Authorization: Bearer {{accessToken}}

Replace{{accessToken}}with your key from Loby.

Resources

Customer

PropertyTypeDefaultDescriptionExample
id*string(UUIDv4)Unique identifier"bd4a0997-39db-41d9-883a-cdfa83e2101f"
encryptedIdstringEncrypted identifier. Used to create direct checkout links. It has been encrypted with a key for the organization."Wn6VsJflvjBO3YyC0lgXdBt9QKcLVZQ2qkEcvJGqa+Txg+mHI/TWbEuUpS45VZgg"
firstNamestringnullFirst name of customer"Johanna"
lastNamestringnullLast name of customer"Ha"
emailstringnullEmail of customer. Email is unique and trying to create a new customer with an email that already exists will fail"hello@hello.com"
phonestringnullPhone number of customer"12345678"
phoneCountryCodestringnullCountry code of phone number"dk"
memberNumbernumbernullMember number of customer. This will only be issued if the customer at some point has had a membership12345678
addressstringnullAddress of customer"Hovedgaden 1"
address2stringnullAddress 2 of customer"1. sal"
postalCodestringnullPostal code of customer"1234"
citystringnullCity of customer"København"
countrystringnullCountry of customer"dk"
birthdatestringnullBirth date for the customer formattedYYYY-MM-DD"2024-01-04"
birthyearnumbernullBirth year for the customer if you only have this information2000
avatarstring(UUIDv4)nullId of the image used for the avatar"bd4a0997-39db-41d9-883a-cdfa83e2101f"
notestringnullOptional internal note"This customer is awesome"
qrCodestringnullQR code of the customer"https://www.acme-museum.com/?qr=KLkjndfjf..."

List Customers

GET /customers

You can use this endpoint to retrieve a list of customers. You can use thefilterparameter to filter the list of customers.

Use thePaginationandQueryingsections to learn more about how to complete this request.

List of available fields to query:

Field NameType
NAMEstring
FIRST_NAMEstring
LAST_NAMEstring
EMAILstring
MEMBER_NUMBERnumber
INITIALSstring
ADDRESSstring
POSTAL_CODEstring
CITYstring
COUNTRYstring
PHONEstring
ENABLE_MEMBERSHIP_EXPIRATION_FLOWboolean
SUBSCRIBED_TO_NEWSLETTERboolean
MEMBERSHIPMembership
CHECKINCheckin
TRANSACTIONTransaction

Getting a customer

GET /customers/:id

If you have an id for a customer, you can use this endpoint to retrieve the customer.

Example response

{
  "id": "bd4a0997-39db-41d9-883a-cdfa83e2101f",
  "firstName": "Henny",
  ...
}

Create a customer

POST /customers

You can create a new customer by providing any of the following fields:

PropertyTypeDescription
firstNamestringFirst name of customer
lastNamestringLast name of customer
emailstringEmail of customer
phonenumberPhone number of customer
phoneCountryCodestringISO Country code of phone number
addressstringAddress of customer
address2stringAddress 2 of customer
postalCodestringPostal code of customer
citystringCity of customer
countrystringISO Country code of customer
birthdatestringBirth date for the customer
avatarstring(UUIDv4)Id of the image used for the avatar
notestringNote for the customer

Update a customer

PATCH /customers/:id

You can update a customer by providing any of the following fields:

PropertyTypeDescription
firstNamestringFirst name of customer
lastNamestringLast name of customer
memberNumbernumberMember number of the customer
emailstringEmail of customer
phonenumberPhone number of customer
phoneCountryCodestringISO Country code of phone number
addressstringAddress of customer
address2stringAddress 2 of customer
postalCodestringPostal code of customer
citystringCity of customer
countrystringISO Country code of customer
birthdatestringBirth date for the customer
avatarstring(UUIDv4)Id of the image used for the avatar
notestringNote for the customer

Set to null to remove the field.

Deleting a customer

DELETE /customers/:customerId

MembershipType

A membership type is a type specification, that is referred to when issuing new memberships.

PropertyTypeDefaultDescriptionExample
id*string(UUIDv4)Unique identifier"bd4a0997-39db-41d9-883a-cdfa83e2101f"
title*stringTitle of membership type"All access pass"or"Season Pass"or"Yearly Membership"
pricenumbernullPrice of ticket in lowest unit. Cents forEUR,USDetc. 0 = FREE54000
cyclestringYEARLYFor how long the membership will be active until it needs to be renewed. Can be eitherYEARLYorMONTHLYorINFINITE."MONTHLY"
translationsarray[]A list of translation objectsMembershipTypeTranslationfor the object[{ language: "da", title: "Et adgang til alt..." }]
renewalPricenumbernullA potential renewal price49000
enableRenewalPricebooleanfalseWhether the renewal price should be enabledtrue
enableRenewalPriceEligibilitybooleanfalseIf this is set to true, you are only allowed to renew if the conditions inrenewalPriceEligibilityPeriodType,renewalPriceEligibilityPeriodsandrenewalPriceEligibilityBeforeExpirationare met.true
renewalPriceEligibilityPeriodTypestringnullCan beDAY,MONTHorYEAR. Determines how many of the chosen types have to be passed before you are uneligible for renewal price"MONTH"
renewalPriceEligibilityPeriodsnumbernullIfrenewalPriceEligibilityPeriodTypeis set toMONTHandrenewalPriceEligibilityPeriodsis set to 2 andrenewalPriceEligibilityBeforeExpirationis set totrue, then the member needs to renew its membership 2 months before expiration to be eligible for the renewal price.2
enableRenewalPricebooleanfalseWhether the renewal price should be enabledtrue
renewalPriceEligibilityBeforeExpirationbooleanfalseAs default it will append the period before the expiration. Otherwise it will be after.true

List Membership Types

GET /membership-types

You can use this endpoint to retrieve a list of membership types.

Use thePaginationandQueryingsections to learn more about how to complete this request.

MembershipTypeTranslation

AMembershipTypeTranslationcontains translated fields for the object.

PropertyTypeDefaultDescriptionExample
language*string(ISO 639-1)Language code for the translation"da"
titlestringnullSee description of field inMembershipType

Membership

AMembershiprepresents an entered membership, that has a MembershipType. A Membership can e.g. be used to get benefits or to get access to the museum.

PropertyTypeDefaultDescriptionExample
id*string(UUIDv4)Unique identifier"bd4a0997-39db-41d9-883a-cdfa83e2101f"
validFromstring (YYYY-MM-DD)nullDate for when the membership starts2024-04-05
validTostring (YYYY-MM-DD)nullDate for when the membership will expire. Including the date2025-04-05
activebooleanWhether the membership is valid or not. This is a convenience property that is calculated from validFrom and validTotrue
autoRenewbooleanfalseShows whether the membership will be auto renewedtrue
preferredRenewalMembershipTypeIdstring(UUIDv4)nullThis field can be used to determine which membership type should be used for the renewal"bd4a0997-39db-41d9-883a-cdfa83e2101f"
membershipTypeMembershipTypeA reference to aMembershipType{ id: "... }
payerIdstring(UUIDv4)nullA reference to aCustomerthat is the payer of the membership"bd4a0997-39db-41d9-883a-cdfa83e2101f"

List of available fields to query:

Field NameType
IDuuid
ACTIVEboolean
AUTO_RENEWboolean
DATEdate
VALID_FROMdate
VALID_TOdate

Issuing membership

POST /customers/:customerId/memberships

You can post a new membership by providing the following fields:

PropertyTypeDescription
membershipTypeId*string(UUIDv4)ID of membership type
validFromstring (YYYY-MM-DD)Date for when the membership should be valid from. If not provided, it will be set to the current date.
validTostring (YYYY-MM-DD)Date for when the membership should be valid to. If not provided, it will be set to the current date + the cycle of the membership type.
previousMembershipIdstring(UUIDv4)If the membership is a renewal, then this field should be set to the id of the previous membership.\
payerIdstring(UUIDv4)If the membership is paid by another customer, then this field should be set to the id of the payer.

Updating af membership

PATCH /memberships/:membershipId

You can update the following fields:validFrom,validTo,autoRenew,preferredRenewalMembershipTypeId,payerId

Deleting a membership

DELETE /memberships/:membershipId

Send membership email

POST /memberships/:membershipId/send-email

This will automatically send a membership email to the customer.

Verifying the validity of a membership via a QR code

GET /verify-membership-qr-code/:qrData

The variableqrDatais the entire data for the qr code e.g.https://test...?qr=test. It needs to be url encoded. So in that means something like this:https%3A%2F%2Ftest...%2F%3Fqr%3DHX9Smn5X%252

It will always return a response with the booleanvalid.

{
  "valid": true
}

Ticket Type

A ticket type is a type specification, that is referred to when issuing new tickets.

PropertyTypeDefaultDescriptionExample
id*string(UUIDv4)Unique identifier"bd4a0997-39db-41d9-883a-cdfa83e2101f"
locationIdstring(UUIDv4)Reference to a location. If that ticket type belongs to a specific location"bd4a0997-39db-41d9-883a-cdfa83e2101f"
name*stringName of ticket type"Adult Ticket Web"
descriptionstringDescription of the ticket"This ticket..."
onlineName*stringOnline Name of ticket type"Adult Ticket"
onlineDescriptionstringOnline Description of the ticket"This ticket..."
translationsarray[]A list of translation objectsTicketTypeTranslationfor the object[{ language: "da", name: "Voksen Bill..." }]
pricenumbernullPrice of ticket in lowest unit. Cents forEUR,USDetc. 0 = FREE54000

List Ticket Types

GET /ticket-types

You can use this endpoint to retrieve a list of ticket types.

TicketTypeTranslation

ATicketTypeTranslationcontains translated fields for the object.

PropertyTypeDefaultDescriptionExample
language*string(ISO 639-1)Language code for the translation"da"
namestringnullSee description of field inTicketType
descriptionstringnullSee description of field inTicketType
onlineNamestringnullSee description of field inTicketType
onlineDescriptionstringnullSee description of field inTicketType

Ticket

ATicketrepresents an issued ticket, that has a TicketType. A Ticket can e.g. be used to get access to the museum.

PropertyTypeDefaultDescriptionExample
id*string(UUIDv4)Unique identifier"bd4a0997-39db-41d9-883a-cdfa83e2101f"
createdAtstringDate for when the ticket was created"2021-03-01T12:00:00.000Z"
numbernumberNumber of the ticket166
ticketTypeTicketTypeTheTicketTypeobject for the ticket{ id: "... }
qrCodestringQR code of the ticket"https://www.acme-museum.com/tickets?qr=KLkjndfjf..."

Getting a ticket

GET /tickets/:id

If you have an id for a ticket, you can use this endpoint to retrieve the ticket.

Example response

{
  "id": "bd4a0997-39db-41d9-883a-cdfa83e2101f",
  "number": 3455,
  ...
}

Issuing a ticket

POST /tickets

You can post a new ticket by providing the following fields:

PropertyTypeDescription
ticketTypeId*string(UUIDv4)ID of ticket type
customerIdstring(UUIDv4)ID of customer
timeSlotIdstring(UUIDv4)A valid time slot reference for the ticket. Ticket Type and Time Slot should either not have location id or the same. Time Slot should have sufficient capacity.

Deleting a ticket

DELETE /tickets/:ticketId

Location

A location can be used for various things. Eg. Assigning timeslots and ticket types to it

PropertyTypeDefaultDescriptionExample
id*string(UUIDv4)Unique identifier"bd4a0997-39db-41d9-883a-cdfa83e2101f"
name*stringName of location"Train"

List Locations

GET /locations

You can use this endpoint to retrieve a list of locations.

Time Slot

A time slot holds information regarding a specific time slot for tickets.

PropertyTypeDefaultDescriptionExample
id*string(UUIDv4)Unique identifier"bd4a0997-39db-41d9-883a-cdfa83e2101f"
maxCapacitynumberThe max capacity for the slot120
startdateStart time stamp for the time slot"2024-01-11T10:00:00.000Z"
enddateStart time stamp for the time slot"2024-01-11T10:29:59.999Z"
numberOfIssuedTicketsnumberHow many tickets have been issued for this time slot99
numberOfReservedTicketsnumberHow many tickets have been reserved for this time slot2
availableTicketsnumberHow many tickets are available in total19

List Time Slots for Location

GET /locations/:locationId/time-slots/:dateQuery

You can use this endpoint to retrieve a list of time slots. You can query the date with the following formats:YYYY,YYYY-MM,YYYY-MM-DD

Event

An event represents a scheduled activity or occasion. You can create ticket types for the event with EventTicketType.

PropertyTypeDefaultDescriptionExample
id*string(UUIDv4)Unique identifier"bd4a0997-39db-41d9-883a-cdfa83e2101f"
createdAtdateCreation timestamp of the event"2024-01-15T09:30:00.000Z"
name*stringName of the event"Summer Festival 2024"
descriptionstringDescription of the event"Annual summer celebration with music and activities"
startDatedateStart date and time of the event"2024-07-01T14:00:00.000Z"
endDatedateEnd date and time of the event"2024-07-03T22:00:00.000Z"
publishedbooleanfalseWhether the event is publicly visibletrue
imageIdstring(UUIDv4)nullID of an image associated with the event"bd4a0997-39db-41d9-883a-cdfa83e2101f"
translationsarray[]A list of translation objectsEventTranslationfor the object[{ language: "da", title: "Sommerfestival 2024", description: "Årlig sommerfest..." }]
enableTicketsbooleanfalseWhether tickets can be issued for this eventtrue
ticketTypesarray[]A list of ticket types (EventTicketType) associated with this event[{ id: "bd4a0997-39db-41d9-883a-cdfa83e2101f", title: "General Admission" }]
soldOutbooleanfalseWhether all tickets for this event have been soldtrue

List Events

GET /events

You can use this endpoint to retrieve a list of events. The standard pagination and filtering options apply. It is default sorted by createdAt DESC.

EventTranslation

AnEventTranslationcontains translated fields for the event object.

PropertyTypeDefaultDescriptionExample
language*string(ISO 639-1)Language code for the translation"da"
namestringnullSee description of field inEvent"Sommerfestival 2024"
descriptionstringnullSee description of field inEvent"Årlig sommerfest..."

EventTicketType

AnEventTicketTyperepresents a type of ticket that can be issued for an event.

PropertyTypeDefaultDescriptionExample
id*string(UUIDv4)Unique identifier"bd4a0997-39db-41d9-883a-cdfa83e2101f"
name*stringName of the ticket type"General Admission"
descriptionstringDescription of the ticket type"Standard entry ticket"
pricenumbernullPrice of ticket in lowest unit. Cents forEUR,USDetc. 0 = FREE2500
maxQuantitynumbernullMaximum number of tickets of this type that can be issued. Null means unlimited.1000
translationsarray[]A list of translation objectsEventTicketTypeTranslationfor the object[{ language: "da", title: "Standard billet", description: "Standard adgangsbillet" }]
availableQuantitynumberNumber of tickets still available for purchase850
soldOutbooleanfalseWhether all tickets of this type have been soldtrue
addOnbooleanfalseWhether this ticket type is an add-on. This ticket type cannot be used as admittance to the eventtrue
publishedbooleanfalseWhether this ticket type is publicly visibletrue

EventTicketTypeTranslation

AnEventTicketTypeTranslationcontains translated fields for the event ticket type object.

PropertyTypeDefaultDescriptionExample
language*string(ISO 639-1)Language code for the translation"da"
titlestringnullSee description of field inEventTicketType"Standard billet"
descriptionstringnullSee description of field inEventTicketType"Standard adgangsbillet"

Pagination

When querying for a list of objects, you will receive a format like this:

{
  "total": 15646,
  "list": [
    {
      "id": "bd4a0997-39db-41d9-883a-cdfa83e2101f",
      ...
    },
    ...
  ]
}

Wheretotalis the total number of objects that are available andlistis the list of objects that are returned. The limit is 1000 objects per request. So in the above response there are 15646 objects available, but only 1000 are returned. If you want the next 1000 objects, you can use theoffsetparameter.

Querying

To query a list of objects, you can use thefilterparameter. Thefilterparameter is a uri encoded JSON object, where you can specify the fields you want to query.

The base filter is an object like this:

{
  "operator": "CONTAINS",
  "fieldName": "NAME",
  "value": "John"
}

So if you want to run this filter on aCustomer, then you need to stringify the object and uri encode it. The result will be:

%7B%22operator%22%3A%22CONTAINS%22%2C%22fieldName%22%3A%22NAME%22%2C%22value%22%3A%22John%22%7D

And this needs to be appended to the request, which will look like this:

GET
https://api.loby.io/v1/customers?filter=%7B%22operator%22%3A%22CONTAINS%22%2C%22fieldName%22%3A%22NAME%22%2C%22value%22%3A%22John%22%7D

Below are the types foroperator: | Operator | Description | | - | - | |CONTAINS| The field contains the value | |NOT_CONTAINS| The field does not contain the value | |EQUAL| The field is equal to the value | |NOT_EQUAL| The field is not equal to the value | |STARTS_WITH| The field starts with the value | |ENDS_WITH| The field ends with the value | |INCLUDES| The field includes the value | |NOT_INCLUDES| The field does not include the value | |LESSER| The field is lesser than the value | |LESSER_OR_EQUAL| The field is lesser than or equal to the value | |GREATER| The field is greater than the value | |GREATER_OR_EQUAL| The field is greater than or equal to the value | |AND| Use this operator if you want to nest conditions and check that all sub conditions are true | |OR| Use this operator if you want to nest conditions and check that at least one is true |

ThefieldNameis the field you want to query. The available fields are listed in the resource documentation for each resource.

Nested fields

Some fields refer to other resources. E.g.MEMBERSHIPonCustomerrefers to aMembership. In this case you can query the nested fields by using the.notation. E.g. if you want to query theVALID_TOfield on theMembershipfrom the customer you can do it like this:

{
  "operator": "GREATER",
  "fieldName": "MEMBERSHIP.VALID_TO",
  "value": 1646071663704
}

Multiple conditions

If you want to query multiple conditions, you can use theANDorORoperator. E.g. if you want to query all customers that have a membership that is valid for more than 1 month, you can do it like this:

{
  "operator": "AND",
  "conditions": [
    {
      "operator": "GREATER",
      "fieldName": "MEMBERSHIP.VALID_TO",
      "value": 1646071663704
    },
    ...
  ]
}

You can also nest each condition infinitely and also combineANDandORoperators.

Images

Loby provides a fully functional image generator, that dynamically generates images for requested sizes. The images are quickly generated and cached for fast reuse.

Url format

Use the following url for generating images:

https://img.loby.io/{{imageId}}_{{sizingType}}{{size}}.{{format}}

componentDescriptionExample
imageIdThe id of the image6ef7d631-b898-40a4-ba27-b8c772f6db03
sizingTypeThere are 3 options:w,hands. By choosingw, image is sized according to width.haccording to height andswill square crop the image and size according to both sidesw
sizeThe size according to the sizing type1280
formatYou can choose betweenjpgandpngjpg

Example

https://img.loby.io/6ef7d631-b898-40a4-ba27-b8c772f6db03_w1280.jpg

QR Code Specification