Skip to content

REST API v1

Celestino Bellone edited this page Oct 4, 2024 · 45 revisions

While we're working on exposing all Alf.io functionalities through APIs (this will happen in v2) we decided to develop a very simple API for creating / updating / deleting and retrieving event statistics.

Configuration

Event

Reservation

Subscription Descriptor

Authentication

You must specify an API Client ApiKey in order to call the APIs.

curl -X POST  http://localhost:8080/api/v1/admin/event/create \
-H "Authorization: ApiKey e210468a-1831-4cf2-93d8-8cc093c7bd7d" \
-H "Cache-Control: no-cache" -H "Content-Type: application/json" \
-d "REQUEST_BODY_JSON (see below)"

ApiKey can be:

  • A system API Key for system-level requests (i.e. create a new organization)
  • An organization-level API Key for creating events and creating reservations

Organization-level requests

You can create an organization-level API Key from your Alf.io instance. Select "API Key" from the top menu and then fill in the details.

Create API Key

System-level requests

Only the "admin" user can view and rotate the System API Key. Select "API Key" from the top menu. You'll see

Create System API Key

Organization-level APIs

in order to consume this APIs you must generate a Organization-level API Key

Set configuration for Organization

Request

PUT /api/v1/admin/configuration/organization/{organizationId}

Sample Body

{
  "USE_INVOICE_NUMBER_AS_ID": "true",
  "VAT_NUMBER_IS_REQUIRED": "true",
  "ENABLE_ITALY_E_INVOICING": "true",
  "GENERATE_ONLY_INVOICE": "true",
  "ITALY_E_INVOICING_SEND_PROFORMA": "true"
}

Set configuration for Event

Request

PUT /api/v1/admin/configuration/organization/{organizationId}/event/{slug}

Sample Body

{
  "USE_INVOICE_NUMBER_AS_ID": "true",
  "VAT_NUMBER_IS_REQUIRED": "true",
  "ENABLE_ITALY_E_INVOICING": "true",
  "GENERATE_ONLY_INVOICE": "true",
  "ITALY_E_INVOICING_SEND_PROFORMA": "true"
}

Set configuration for Subscription

Request

PUT /api/v1/admin/configuration/organization/{organizationId}/subscription/{id}

Sample Body

{
  "USE_INVOICE_NUMBER_AS_ID": "true",
  "VAT_NUMBER_IS_REQUIRED": "true",
  "ENABLE_ITALY_E_INVOICING": "true",
  "GENERATE_ONLY_INVOICE": "true",
  "ITALY_E_INVOICING_SEND_PROFORMA": "true"
}

Create Event

Request

POST /api/v1/admin/event/create

Sample Body (Reference)

{
    "title": "Titolo",
    "slug": "titolo",
    "description": [{
        "lang": "de",
        "body": "text description"
    }],
    "location": {
        "fullAddress": "Pollegio 6742 Switzerland",
        "coordinate": {
            "latitude": "45.55",
            "longitude": "9.00"
        }
    },
    "timezone": "Europe/Zurich",
    "startDate": "2018-08-12T08:00:00",
    "endDate": "2018-08-12T09:00:00",
    "websiteUrl": "http://www.amicidelticino.ch/aktivitaten/exklusivbesuch-des-kommandoturms-der-sbb",
    "termsAndConditionsUrl": "http://www.amicidelticino.ch/agb",
    "imageUrl": "https://www.amicidelticino.ch/assets/adt/images/amicidelticino-logo.png",
    "tickets": {
        "freeOfCharge": false,
        "max": 10,
        "currency": "CHF",
        "taxPercentage": 7.7,
        "taxIncludedInPrice": true,
        "paymentMethods": ["ON_SITE"],
        "categories": [
            {
                "name":"Standard",
                "description": [{
                    "lang": "de",
                    "body": "text description"
                }],
                "maxTickets": null,
                "accessRestricted": false,
                "price": 10.0,
                "startSellingDate": "2018-08-02T15:24:22",
                "endSellingDate": "2018-08-12T07:00:00",
                "groupLink": {
                   "groupId": 123,
                   "type": "LIMITED_QUANTITY",
                   "matchType": "EMAIL_DOMAIN",
                   "maxAllocation": 2
                }
            }
        ]
    },
    "extensionSettings": [{
        "extensionId": "mailchimp",
        "key":"listId",
        "value":"your-list-id"
    }]
}

Response

  • HTTP 200 {slug} - the given slug or a new, auto-generated one
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Update Event

Request

POST /api/v1/admin/event/update/{slug}

Sample Body (Reference)

{
    "title": "NewTitle",
    "startDate": "2018-08-12T08:01:00"
}

Response

  • HTTP 200 {slug}
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

List Subscriptions linked to Event

Request

GET /api/v1/admin/event/{slug}/subscriptions

Response

Link Subscriptions to Event

Request

PUT /api/v1/admin/event/{slug}/subscriptions

Sample Body

[
  {
    "descriptorId": "33bd5a7b-5bbf-4040-818b-c7e4c7490312",
    "categories": [ 1, 2 ]
  }
]

Response

Generate tickets for subscribers

Triggers ticket generation for subscription holders linked to a given event

Request

POST /api/v1/admin/event/{slug}/generate-subscribers-tickets

Sample Body

{}

Response

  • HTTP 200 true if generation job has been scheduled
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Check-in log

Returns the check-in log for a given Event

Request

GET /api/v1/admin/event/{slug}/check-in-log

Response

  • HTTP 200 List of CheckInLogEntry
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Delete Event

Request

DELETE /api/v1/admin/event/{slug}

Response

  • HTTP 200 OK
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Create Ticket Reservation

POST /api/v1/admin/event/{slug}/reservation

Sample Body (Reference)

{
  "tickets": [
    {
      "ticketCategoryId": 53,
      "quantity": "1",
      "attendees": [{
        "firstName": "Test",
        "lastName": "McTest",
        "email": "[email protected]",
        "metadata": {
          "attributeForTicket1": "value"
        }
      }]
    },
    {
      "ticketCategoryId": 56,
      "quantity": "2",
      "attendees": [{
        "firstName": "John",
        "lastName": "Doe",
        "email": "[email protected]",
        "metadata": {
          "attributeForTicket1": "value1"
        }
      },{
        "firstName": "Jane",
        "lastName": "Doe",
        "email": "[email protected]",
        "metadata": {
          "attributeForTicket2": "value2"
        }
      }]
    }
  ],
  "additionalServices": [
    {
      "additionalServiceId": 1,
      "quantity": 1
    }
  ],
  "promoCode": null,
  "user": {
    "username": "[email protected]",
    "firstName": "Test",
    "lastName": "McTest",
    "email": "[email protected]",
    "id": "external-id"
  },
  "configuration": {
     "hideContactData": false
  }
}

Response

  • HTTP 201
    {
      "success": true,
      "id": "reservation-id",
      "href": "public-url-for-reservation",
      "errors": null
    }
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Create Subscription Reservation

POST /api/v1/admin/subscription/{descriptorId}/reservation

Sample Body (Reference)

{
  "metadata": {
    "key1": "value1"
  },
  "user": {
    "username": "[email protected]",
    "firstName": "Test",
    "lastName": "McTest",
    "email": "[email protected]"
  },
  "configuration": {
    "hideContactData": true
  },
  "language": "it"
}

Response

  • HTTP 201
    {
      "success": true,
      "id": "reservation-id",
      "href": "public-url-for-reservation",
      "errors": null
    }
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Get Reservation Detail

Ticket Reservation

GET /api/v1/admin/event/{slug}/reservation/{reservationId}

Response

  • HTTP 200 see ReservationDetail
    {
      "id": "abcd",
      "status": "COMPLETE",
      "user": {
        "firstName": "Test",
        "lastName": "McTest",
        "email": "[email protected]"
      },
      "tickets": [
        {
          "ticketCategoryId": 53,
          "quantity": "1",
          "attendees": [{
            "firstName": "Test",
            "lastName": "McTest",
            "email": "[email protected]",
            "metadata": {
              "attributeForTicket1": "value"
            },
            "additional": {
              "key": ["value"]
            },
            "resources": {
              "ticketPdf": "https://instance-address/ticket-url", // only if reservation status is COMPLETE
              "ticketQrCode": "https://instance-address/ticket-qrcode-image-url", // only if reservation status is COMPLETE
              "googleWallet": "https://instance-address/google-wallet-url", // only if google wallet support is enabled
              "applePass": "https://instance-address/apple-pass-url" // only if apple pass support is enabled
            }
          }]
        }
      ]
    }
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Subscription Reservation

GET /api/v1/admin/subscription/{descriptorId}/reservation/{reservationId}

Response

  • HTTP 200 see ReservationDetail
    {
      "id": "abcd",
      "status": "COMPLETE",
      "user": {
        "firstName": "Test",
        "lastName": "McTest",
        "email": "[email protected]"
      },
      "subscriptionOwners": {
          "firstName": "Test",
          "lastName": "McTest",
          "email": "[email protected]",
          "metadata": {
            "attributeKey": "value"
          },
          "additional": {
            "key": ["value"]
          }
      }
    }
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Confirm Reservation

PUT /api/v1/admin/reservation/{id}/confirm

Sample Body (Reference)

{
  "transaction": {
    "id": "123456789",
    "paymentProvider": "ON_SITE",
    "timestamp": "2023-10-22T17:00:00",
    "paidAmount": "120.00",
    "notes": "test notes"
  },
  "notification": {
    "attendees": true,
    "customer": true
  }
}

Response

  • HTTP 200
    {
      "holders": [
        {
          "id": "6ccd858f-d391-4558-9ad0-e39fc9683f49",
          "firstName": "Test",
          "lastName": "McTest",
          "email": "[email protected]"
        }
      ]
    }
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Remove Ticket

Removes a ticket from a reservation. After being removed, the ticket will not be valid anymore.

DELETE /api/v1/admin/event/{slug}/reservation/delete-ticket/{UUID}

Response

  • HTTP 200 OK
  • HTTP 404 Event not found or Ticket not found
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Cancel Subscription

Cancels a subscription and removes it from a reservation. After being removed, the subscription will not be valid anymore.

DELETE /api/v1/admin/subscription/{descriptorId}/reservation/delete-subscription/{subscriptionId}

Response

  • HTTP 200 OK
  • HTTP 404 Subscription Descriptor not found or Subscription not found
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Create Subscription Descriptor

Request

POST /api/v1/admin/subscription/create

{
  "usageType": "ONCE_PER_EVENT",
  "termType": "standard",
  "term": {
    "timeUnit": "MONTHS",
    "units": 1
  },
  "title": [
    {
      "lang": "en",
      "body": "this is the title"
    }
  ],
  "description": [
    {
      "lang": "en",
      "body": "this is the description"
    }
  ],
  "onSaleFrom": "2022-07-23T12:00:18.22831",
  "onSaleTo": "2022-12-23T12:00:18.22831",
  "price": "10.00",
  "taxPercentage": "7.7",
  "taxPolicy": "INCLUDED",
  "currencyCode": "CHF",
  "imageUrl": "https://alf.io/img/tutorials/check-in-app/003.png",
  "termsAndConditionsUrl": "https://alf.io",
  "privacyPolicyUrl": "https://alf.io",
  "timezone": "Europe/Zurich",
  "supportsTicketsGeneration": false,
  "paymentMethods": [
    "STRIPE"
  ],
  "isPublic": true
}

Response

  • HTTP 200 {ID} - the subscription descriptor auto-generated ID (UUID)
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Update Subscription Descriptor

Request

POST /api/v1/admin/subscription/{id}/update

{
  "usageType": "ONCE_PER_EVENT",
  "termType": "standard",
  "term": {
    "timeUnit": "MONTHS",
    "units": 1
  },
  "title": [
    {
      "lang": "en",
      "body": "this is the title"
    }
  ],
  "description": [
    {
      "lang": "en",
      "body": "this is the description"
    }
  ],
  "onSaleFrom": "2022-07-23T12:00:18.22831",
  "onSaleTo": "2022-12-23T12:00:18.22831",
  "price": "10.00",
  "taxPercentage": "7.7",
  "taxPolicy": "INCLUDED",
  "currencyCode": "CHF",
  "imageUrl": "https://alf.io/img/tutorials/check-in-app/003.png",
  "termsAndConditionsUrl": "https://alf.io",
  "privacyPolicyUrl": "https://alf.io",
  "timezone": "Europe/Zurich",
  "supportsTicketsGeneration": false,
  "paymentMethods": [
    "STRIPE"
  ],
  "isPublic": true
}

Response

  • HTTP 200 {ID}
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Get Subscription Descriptor

GET /api/v1/admin/subscription/{id}

Response

Get Linked Events

Returns events linked with a given Subscription Descriptor

GET /api/v1/admin/subscription/{id}/events

Response

  • HTTP 200 Array of LinkedEvent
  • HTTP 404 Not found
  • HTTP 500 Error descriptor

Update Linked Events

Updates linked Events for a given Subscription Descriptor

Request

POST /api/v1/admin/subscription/{id}/events

Sample Body

[
  {
    "slug": "event_1"
  },
  {
    "slug": "event_2",
    "categories": [ 1, 2]
  }
]

Response

  • HTTP 200 Array of LinkedEvent
  • HTTP 404 Not found
  • HTTP 500 Error descriptor

Deactivate Subscription Descriptor

Deactivates a given Subscription Descriptor. This will prevent people from using purchased subscriptions and from purchasing new ones of the same kind.

Request

DELETE /api/v1/admin/subscription/{id}/deactivate

Response

  • HTTP 200 Subscription Descriptor has been deactivated
  • HTTP 404 Not found
  • HTTP 500 Error descriptor

JSON Reference

Event Request

Name Description Mandatory
title The event name *
slug Short name, used in URLs
description Array of i18n, Markdown-formatted descriptions *
description.lang Language code *
description.body Localized, Markdown formatted, text *
location Event Location *
location.fullAddress Location address *
location.coordinate geolocation data: latitude and longitude *
timezone time zone identifier (e.g. Europe/Zurich, see List of tz database time zones) *
startDate start date/time, format: YYYY-MM-DDTHH:mm:SS *
endDate start date/time, format: YYYY-MM-DDTHH:mm:SS *
websiteUrl The URL of the event website (can be a dedicated page, or a generic website) *
termsAndConditionsUrl T&C URL *
privacyPolicyUrl Privacy Policy URL
imageUrl URL for retrieving the Event Logo. Must be accessible from alf.io's server *
tickets ticket categories definition *
tickets.freeOfCharge whether or not the event is free of charge *
tickets.max the maximum allowed seats *
tickets.currency ISO 4217 currency code (e.g. CHF, EUR, USD) if freeOfCharge is false
tickets.taxPercentage VAT/GST percentage if freeOfCharge is false
tickets.taxIncludedInPrice Whether the prices are already VAT/GST inclusive if freeOfCharge is false
tickets.paymentMethods Allowed Payment methods if freeOfCharge is false
tickets.categories Available ticket categories *
tickets.categories[n].id Category ID, as returned by the /stats endpoint. Make sure to specify it on update
tickets.categories[n].name Name *
tickets.categories[n].description i18n Localized descriptions
tickets.categories[n].maxTickets Maximum tickets to allocate for this category
tickets.categories[n].accessRestricted Make the category private and generate unique access codes for it. Requires maxTickets > 0
tickets.categories[n].price Ticket price for this category if tickets.freeOfCharge is false
tickets.categories[n].startSellingDate Start Selling Date/Time *
tickets.categories[n].endSellingDate End Selling Date/Time *
tickets.categories[n].groupLink Tickets for this category can only be assigned to people in the given Group
tickets.categories[n].groupLink.groupId Group ID *
tickets.categories[n].groupLink.type Link type *
tickets.categories[n].groupLink.matchType Matching type *
tickets.categories[n].groupLink.maxAllocation max tickets allowed per match if matchType is "LIMITED_QUANTITY"
extensionSettings settings for extensions
extensionSettings.extensionId the id as defined in the Repository *
extensionSettings.key extension setting key *
extensionSettings.value extension setting value *

Create Ticket Reservation Request

Name Description Mandatory
tickets Tickets to reserve *
tickets.*.ticketCategoryId Category ID *
tickets.*.quantity number of tickets for the given category ID *
tickets.*.attendees Attendees for this category
additionalServices additional items to reserve
additionalServices.*.additionalServiceId additional service ID *
additionalServices.*.quantity number of additional services items *
promoCode promoCode to apply
user authenticated user who is performing the reservation
user.username username. Depending on the Authentication system in use, can be the user email *
user.firstName First name *
user.lastName Last name *
user.email Email *
user.id External ID, this attribute is currently ignored
subscriptionId Subscription code to apply
configuration reservation process configuration
configuration.hideContactData whether to hide the "contact data" section. Useful if user was specified
configuration.hideConfirmationButtons hide buttons on confirmation page (buy other tickets, back to organizer).
configuration.lockEmailEdit Do not edit email address for attendee. Only if you provided attendees.*.email

Create Subscription Reservation Request

Name Description Mandatory
metadata key/value map of custom properties that will be linked to the generated subscription
language IETF BCP 47 language tag
user authenticated end user who is performing the reservation
user.username username. Depending on the Authentication system in use, can be the user email *
user.firstName First name *
user.lastName Last name *
user.email Email *
user.id External ID, this attribute is currently ignored
configuration reservation process configuration
configuration.hideContactData whether to hide the "contact data" section. Useful if user was specified
subscriptionConfiguration subscription-specific configurations
subscriptionConfiguration.displayPin display PIN on confirmation page and PDF (default true)

Confirm Reservation Request

Name Description Mandatory
transaction Transaction details *
transaction.id Transaction identifier *
transaction.paymentProvider PaymentProvider used. If in doubt, use 'ADMIN' *
transaction.timestamp timestamp of the transaction *
transaction.paidAmount amount paid from attendee
transaction.notes notes
notification notification settings *
notification.attendees notify attendees (ticket/subscription holders)
notification.customer notify customer

System-level APIs

List Organizations

GET /api/v1/admin/system/organization/list

Response

Get Organization

GET /api/v1/admin/system/organization/{id}

Response

  • HTTP 200 Organization
  • HTTP 404 Organization ID not found
  • HTTP 500 Error descriptor

Create Organization

Request

POST /api/v1/admin/system/organization/create

{
    "name": "New Organization",
    "email": "[email protected]",
    "description": "mandatory description"
}

Response

  • HTTP 200 Organization
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Update Organization

Request

POST /api/v1/admin/system/organization/{id}

{
    "id": 1,
    "name": "New Name",
    "email": "[email protected]",
    "description": "mandatory description"
}

Response

  • HTTP 200 Organization
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Delete Organization

DELETE /api/v1/admin/system/organization/{id}

Warning This will delete all Events, Subscriptions, Reservations owned by the Organization you're deleting

Response

  • HTTP 200 OK
  • HTTP 400 Error descriptor
  • HTTP 500 Error descriptor

Create API Key for Organization

PUT /api/v1/admin/system/organization/{id}/api-key

Sample Body (optional)

{
  "type": "SUPERVISOR",
  "description": "API Key Description"
}

type must be one of

  • API_CLIENT
  • SUPERVISOR
  • SPONSOR
  • OPERATOR

Response

  • HTTP 200 OrganizationApiKey { "organizationId": 123, "apiKey": "abcd" }
  • HTTP 500 Error descriptor

Delete API Key

DELETE /api/v1/admin/system/organization/{id}/api-key/{apiKey}

Response

  • HTTP 200
  • HTTP 500 Error descriptor

Credits

We would like to thank

Starplane

for sponsoring the development of this feature. Thank you!

Clone this wiki locally