šŸ“˜

Looking for access?

The ultimate goal of the protocol is to fully open-source all tooling and open access to all interested parties permissionlessly. For now we currently follow an onboarding procedure for new users. Please get in touch with us to find out more.

API keys will be provided via the GET Protocol support team.

The Ticket Engine API allows you to programmatically create events & tickets, as well as update their state as needed. This allows you to reflect or mirror your ticket information on-chain.

Let's walk through the API calls needed to create an event and register tickets.

Authenticating with the API

Credentials are expected to be provided in the X-Api-Key header on every request. The API key for your organization will be provided during the onboarding process. You will also receive a ticketeerId which is required for subsequent requests.

curl -X POST 'https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/<PATH>' \
-H 'X-Api-Key: <string, required>' \
-H 'Content-Type: application/json'
fetch("https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/<PATH>", {
  headers: {
    "Content-Type": "application/json",
    "X-Api-Key": "<string, required>"
  },
  method: "POST"
})
import requests

headers = {
  'X-Api-Key': '<string, required>',
  'Content-Type': 'application/json',
}

response = requests.post('https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/<PATH>', headers=headers)

Authentication failures will be returned with a 403 Forbidden status code and body:

{
    "message": "Forbidden"
}

Creating your First Event

šŸ‘

Defining your webhooks

When creating an event you must provide a callbackUrl parameter as the blockchain transactions are written to the network depending on multiple load factors external to the Ticket Engine, so this happens via an asynchronous process. Take a look over the guide before jumping in.

Before we can register sold tickets we need an event to associate them to and this must be done before tickets can be created.

First we create an event using a POST request to the /api/v1/events endpoint which expects a client-generated eventId. We recommend that you generate this ID as a UUID and add this to your own Event model record prior to creating an event record with Ticket Engine.

curl -X POST 'https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/events' \
-H 'X-Api-Key: <string, required>' \
-H 'Content-Type: application/json' \
--data-raw '{
    "eventId": "d240f841-11c3-4140-b7d4-d18c87954ffe",
    "eventName": "My Awesome First Event",
    "ticketeerId": "<string, required>",
    "ticketeerName": "Hooli Tickets",
    "currency": "USD",
    "shopUrl": "https://hooli.tickets/shop/12345",
    "imageUrl": "https://images.hooli.tickets/events/12345/banner.jpg",
    "latitude": 37.8272,
    "longitude": 122.2913,
    "startTime": 1609430400,
    "endTime": 1609516800,
    "callbackUrl": "https://hooli.tickets/events/12345/webhook"
}'
fetch("https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/events", {
  headers: {
    "Content-Type": "application/json",
    "X-Api-Key": "<string, required>"
  },
  method: "POST",
  body: JSON.stringify({
    "eventId": "d240f841-11c3-4140-b7d4-d18c87954ffe",
    "eventName": "My Awesome First Event",
    "ticketeerId": "<string, required>",
    "ticketeerName": "Hooli Tickets",
    "currency": "USD",
    "shopUrl": "https://hooli.tickets/shop/12345",
    "imageUrl": "https://images.hooli.tickets/events/12345/banner.jpg",
    "latitude": 37.8272,
    "longitude": 122.2913,
    "startTime": 1609430400,
    "endTime": 1609516800,
    "callbackUrl": "https://hooli.tickets/events/12345/webhook"
  })
})
import requests

headers = {
  'X-Api-Key': '<string, required>',
  'Content-Type': 'application/json',
}

json = {
  'eventId': 'd240f841-11c3-4140-b7d4-d18c87954ffe',
  'eventName': 'My Awesome First Event',
  'ticketeerId': '<string, required>',
  'ticketeerName': 'Hooli Tickets',
  'currency': 'USD',
  'shopUrl': 'https://hooli.tickets/shop/12345',
  'imageUrl': 'https://images.hooli.tickets/events/12345/banner.jpg',
  'latitude': 37.8272,
  'longitude': 122.2913,
  'startTime': 1609430400,
  'endTime': 1609516800,
  'callbackUrl': 'https://hooli.tickets/events/12345/webhook'
}

response = requests.post('https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/events', headers=headers, json=json)
{
  "txPromise": "<txPromise>",
  "eventId": "d240f841-11c3-4140-b7d4-d18c87954ff",
  "status": "success"
}
{
    "txHash": "0xf21a20c8232f45a558de2b1e01abbeb65c839101c972d4d349cce71c9446ed61",
    "transactionType": "event",
    "action": "newEvent",
    "eventId": "d240f841-11c3-4140-b7d4-d18c87954ff"
}

Upon success the transaction will be sent to the blockchain and Ticket Engine will await confirmation that the transaction has been accepted. It is at this point that the callback is issued and a HTTP request will be sent to your callbackUrl. This must be secured by HTTPS.

The callback will POST the response body as per the 'Callback' snippet above.

Selling your First Tickets

A ticket is not created until it is sold, so to create our first tickets for the newly created event we issue a call to the /api/v1/sold endpoint.

The body of the request is expected to be an array and it is possible to register up to 100 sold tickets per request. Much like the eventId used above, ticketId is a client generated ID so UUIDs are recommended here also.

All further calls will accept up to 100 ticket modifications per-request.

curl -X POST 'https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/sold' \
-H 'X-Api-Key: <string, required>' \
-H 'Content-Type: application/json' \
--data-raw '[
    {
        "eventId": "d240f841-11c3-4140-b7d4-d18c87954ffe",
        "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1",
        "orderTime": 1604160000,
        "price": "15"
    },
    {
        "eventId": "d240f841-11c3-4140-b7d4-d18c87954ffe",
        "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4",
        "orderTime": 1604163600,
        "price": "20"
    }
]'
fetch("https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/sold", {
  headers: {
    "Content-Type": "application/json",
    "X-Api-Key": "<string, required>"
  },
  method: "POST",
  body: JSON.stringify([
    {
        "eventId": "d240f841-11c3-4140-b7d4-d18c87954ffe",
        "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1",
        "orderTime": 1604160000,
        "price": "15"
    },
    {
        "eventId": "d240f841-11c3-4140-b7d4-d18c87954ffe",
        "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4",
        "orderTime": 1604163600,
        "price": "20"
    }
  ])
})
import requests

headers = {
  'X-Api-Key': '<string, required>',
  'Content-Type': 'application/json',
}

json = [
  {
    'eventId': 'd240f841-11c3-4140-b7d4-d18c87954ffe',
    'ticketId': '031bdc1d-c864-4d74-855c-4f10022a2cc1',
    'orderTime': 1604160000,
    'price': '15'
  },
  {
    'eventId': 'd240f841-11c3-4140-b7d4-d18c87954ffe',
    'ticketId': '76981d0d-5e11-4a4a-8840-a0a5d4f89bb4',
    'orderTime': 1604163600,
    'price': '20'
  }
]

response = requests.post('https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/sold', headers=headers, json=json)
[
  {
    "txPromise": "<txPromise>",
    "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1",
    "status": "success"
  },
  {
    "txPromise": "<txPromise>",
    "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4",
    "status": "success"
  }
]
{
    "txHash": "0xcb291466b0475e254dc3604011d1f0fe3d0da9e48d8cabfca113579363b711f2",
    "transactionType": "ticket",
    "action": "sold",
    "eventId": "d240f841-11c3-4140-b7d4-d18c87954ffe",
    "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1"
}
{
    "txHash": "0xcb291466b0475e254dc3604011d1f0fe3d0da9e48d8cabfca113579363b711f2",
    "transactionType": "ticket",
    "action": "sold",
    "eventId": "d240f841-11c3-4140-b7d4-d18c87954ffe",
    "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4"
}

The response will be returned as an array with an individual success status for each submitted ticket.

When successfully registered on-chain a callback will be issued to the callbackUrl of the event for each submitted ticket (see the 'Callback' snippets above). This means that an NFT mirror of your ticket state had been created on-chain and any further updates to this ticket will modify the state, metadata, or ownership of this NFT.

Registering a Secondary Market Resale

A resale event will move the ticket between blockchain accounts (addresses). Ownership of a ticket is represented by the address that holds the NFT, so this is important to ensure correct ownership post-sale for future claim functionality.

curl -X POST 'https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/resold' \
-H 'X-Api-Key: <string, required>' \
-H 'Content-Type: application/json' \
--data-raw '[
    {
        "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1",
        "orderTime": 1604180000,
        "price": "10.99"
    },
    {
        "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4",
        "orderTime": 1604183600,
        "price": "21.25"
    }
]'
fetch("https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/resold", {
  headers: {
    "Content-Type": "application/json",
    "X-Api-Key": "<string, required>"
  },
  method: "POST",
  body: JSON.stringify([
    {
        "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1",
        "orderTime": 1604180000,
        "price": "10.99"
    },
    {
        "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4",
        "orderTime": 1604183600,
        "price": "21.25"
    }
  ])
})
import requests

headers = {
  'X-Api-Key': '<string, required>',
  'Content-Type': 'application/json',
}

json = [
  {
    'ticketId': '031bdc1d-c864-4d74-855c-4f10022a2cc1',
    'orderTime': 1604180000,
    'price': '10.99'
  },
  {
    'ticketId': '76981d0d-5e11-4a4a-8840-a0a5d4f89bb4',
    'orderTime': 1604183600,
    'price': '20.25'
  }
]

response = requests.post('https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/resold', headers=headers, json=json)
[
  {
    "txPromise": "<txPromise>",
    "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1",
    "status": "success"
  },
  {
    "txPromise": "<txPromise>",
    "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4",
    "status": "success"
  }
]
{
    "txHash": "0xcb291466b0475e254dc3604011d1f0fe3d0da9e48d8cabfca113579363b711f2",
    "transactionType": "ticket",
    "action": "resold",
    "eventId": "d240f841-11c3-4140-b7d4-d18c87954ffe",
    "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1"
}
{
    "txHash": "0xcb291466b0475e254dc3604011d1f0fe3d0da9e48d8cabfca113579363b711f2",
    "transactionType": "ticket",
    "action": "resold",
    "eventId": "d240f841-11c3-4140-b7d4-d18c87954ffe",
    "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4"
}

Checking-in a Ticket

Checking-in a ticket is a one-way operation and will prevent the ticket from continuing to be resold. This will also unlock future claim functionality, enabling withdrawal to their own blockchain wallet.

curl -X POST 'https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/checkedin' \
-H 'X-Api-Key: <string, required>' \
-H 'Content-Type: application/json' \
--data-raw '[
    {
        "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1",
        "orderTime": 1604190000
    },
    {
        "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4",
        "orderTime": 1604193600
    }
]'
fetch("https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/scanned", {
  headers: {
    "Content-Type": "application/json",
    "X-Api-Key": "<string, required>"
  },
  method: "POST",
  body: JSON.stringify([
    {
        "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1",
        "orderTime": 1604190000
    },
    {
        "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4",
        "orderTime": 1604193600
    }
  ])
})
import requests

headers = {
  'X-Api-Key': '<string, required>',
  'Content-Type': 'application/json',
}

json = [
  {
    'ticketId': '031bdc1d-c864-4d74-855c-4f10022a2cc1',
    'orderTime': 1604190000
  },
  {
    'ticketId': '76981d0d-5e11-4a4a-8840-a0a5d4f89bb4',
    'orderTime': 1604193600
  }
]

response = requests.post('https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/scanned', headers=headers, json=json)
[
  {
    "txPromise": "<txPromise>",
    "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1",
    "status": "success"
  },
  {
    "txPromise": "<txPromise>",
    "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4",
    "status": "success"
  }
]
{
    "txHash": "0xcb291466b0475e254dc3604011d1f0fe3d0da9e48d8cabfca113579363b711f2",
    "transactionType": "ticket",
    "action": "scanned",
    "eventId": "d240f841-11c3-4140-b7d4-d18c87954ffe",
    "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1"
}
{
    "txHash": "0xcb291466b0475e254dc3604011d1f0fe3d0da9e48d8cabfca113579363b711f2",
    "transactionType": "ticket",
    "action": "scanned",
    "eventId": "d240f841-11c3-4140-b7d4-d18c87954ffe",
    "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4"
}

Invalidating a Ticket

Any tickets that have been deemed as invalid (due to customer issue, refund, etc) must be marked as invalid to prevent scan and claim events from succeeding. A ticket that has already been checked-in cannot be invalidated.

curl -X POST 'https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/invalidated' \
-H 'X-Api-Key: <string, required>' \
-H 'Content-Type: application/json' \
--data-raw '[
    {
        "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1",
        "orderTime": 1604190000
    },
    {
        "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4",
        "orderTime": 1604193600
    }
]'
fetch("https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/invalidated", {
  headers: {
    "Content-Type": "application/json",
    "X-Api-Key": "<string, required>"
  },
  method: "POST",
  body: JSON.stringify([
    {
        "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1",
        "orderTime": 1604190000
    },
    {
        "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4",
        "orderTime": 1604193600
    }
  ])
})
import requests

headers = {
  'X-Api-Key': '<string, required>',
  'Content-Type': 'application/json',
}

json = [
  {
    'ticketId': '031bdc1d-c864-4d74-855c-4f10022a2cc1',
    'orderTime': 1604190000
  },
  {
    'ticketId': '76981d0d-5e11-4a4a-8840-a0a5d4f89bb4',
    'orderTime': 1604193600
  }
]

response = requests.post('https://playground.ticket-engine.blockchain.get-protocol.io/api/v1/invalidated', headers=headers, json=json)
[
  {
    "txPromise": "<txPromise>",
    "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1",
    "status": "success"
  },
  {
    "txPromise": "<txPromise>",
    "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4",
    "status": "success"
  }
]
{
    "txHash": "0xcb291466b0475e254dc3604011d1f0fe3d0da9e48d8cabfca113579363b711f2",
    "transactionType": "ticket",
    "action": "invalidated",
    "eventId": "d240f841-11c3-4140-b7d4-d18c87954ffe",
    "ticketId": "031bdc1d-c864-4d74-855c-4f10022a2cc1"
}
{
    "txHash": "0xcb291466b0475e254dc3604011d1f0fe3d0da9e48d8cabfca113579363b711f2",
    "transactionType": "ticket",
    "action": "invalidated",
    "eventId": "d240f841-11c3-4140-b7d4-d18c87954ffe",
    "ticketId": "76981d0d-5e11-4a4a-8840-a0a5d4f89bb4"
}