Back to top

GET protocol

Welcome to the GET protocol API-documentation.

Introduction

This api documentation is in ALPHA state

Miscelaneous

Logging in as a customer

First, Login by requesting an access code for +31612345678

curl 'https://api.sandbox.guts.tickets/api/v1/mobile-auth/' -X POST --data 'recipient=%2B31612345678&locale=en'

//Response
{"authid":"<auth_id>","tries_left":3,"used":false}

The user will now receive a SMS containing the access code. The code is a 4 digit number, e.g. 1234.

curl 'https://api.sandbox.guts.tickets/api/v1/mobile-auth/<auth_id>/' -X POST --data 'token=1234'

//Response
{"id":9500,"username":"+31612345678",..., "refresh_token":"<refresh_token>","jwt_token":"<jwt_token>"}

The system has two kind of users. Customer and Dashboard users. Both users use JWT for authentication but they have different ways of obtaining them.

Customers are identified by their mobile phone and they use that to obtain JWT token. Dashboard users use their username/password to authenticate.

Both types of users use the same endpoints. The system is aware of the type of user and might differentiate the retrieved results depending on the user type. In general, Dashboard users will see more information.

When logging in the api returns a refresh token and a jwt token. The jwt token is used for authentication. It needs to be added to the header of all endpoints that require authentication.

Authorization: JWT <token>

Check the authentication section for more details.

Pagination

All listing endpoints use pagination. It follows this format:

{
  "count": 1,
  "next": url,
  "previous": url,
  "results": ....
}

Error handling

The API will raise HTTP error codes when it receives malformed or incorrect input. There are cases where the API request was valid and well formed but some logic restriction prevents the call API call from completing successfully. Example: Trying to put a ticket in your cart when no tickets are available. In these cases the call will return a 200 but will provide a status in the payload.

{
  "status": "error|success",
  "error": "error_code_string"
}

Use Case: Buying a ticket flow

Find the event

First, we need to select the event_id of the event that we are going to buy tickets for. To do that, we need to list all events.

curl 'https://api.sandbox.guts.tickets/api/v1/events/?filter=upcoming'

//Response
{
    "results": [
        {"slug": <slug>, "id": <event_id>, ...}
    ],
    ...
}

Get event details

The event listing does not contain all the information of the events. For example, the field tickets_per_rank (see next steps) is missing from that response. In order to get all the info for the event that we are interested in purchasing tickets, we need to make a separate call to event detail

curl 'https://api.sandbox.guts.tickets/api/v1/events/<slug>/'

//Response
{
    ...
    "tickets_per_rank":[
        {
            "kind": <kind_1>,
            ...
        },
        {
            "kind": <kind_2>,
            ...
        }
    ]
}

We are going to need these kind IDs later when adding tickets to our cart.

Create a cart

Next we need to create a cart. You’ll need to create a guid for the cart yourself the format is

<uuid4>-<event_id>
example: 98bebab2-3969-4ec4-b16c-dcabfc4e9c5f-11

Next we retrieve the cart.

curl 'https://api.sandbox.guts.tickets/api/v1/carts/<guid>

//Response
{
    "id":<id>,
    "guid":"<guid>",
    "tickets": []
}

Fill the cart

As you can see the cart is now empty. We can fill the cart with tickets by sending a PUT request with this data payload structure. The kind key is the ID of the ticket kind that the user selects. These IDs are available in the event detail response under the key tickets_per_rank. Make sure you always send the whole ticket/rank state.

{
    "event": 1 ,
    "ranks": [
        { "kind": <kind_1>, "amount": 2 },
        { "kind": <kind_2>, "amount": 1 }
    ]
}
curl 'https://api.sandbox.guts.tickets/api/v1/carts/<guid>' -X PUT -H 'Content-Type: application/json; charset=utf-8' --data '{"event":"1", "ranks": [{"kind": 1, "amount":0},{"kind": 2, "amount":1}]}'

Payment

To start a payment we first have to checkout the cart. At this point the user has to be logged in. So make sure to authenticate the user using the correct Authorization header (see example).

curl 'https://api.sandbox.guts.tickets/api/v1/carts/<guid>/checkout/' -X PUT -H 'Authorization: JWT <jwt_token>'

//Response
{"order": <id>}

Using the returned order we can start a payment on the order.

curl 'https://api.sandbox.guts.tickets/api/v1/orders/<order_id>/start_payment/' -X POST -H 'Authorization: JWT <jwt_token> -H 'Content-Type: application/json; charset=utf-8' --data '{"psp_arguments", {"return_page": <your_url>}}'

//Response
{"status": "redirect": <url>}

The return_url should be the url of your landing page that handles the order completion.

After this list your new tickets.

curl 'https://api.sandbox.guts.tickets/api/v1/tickets/' -H 'Authorization: JWT <jwt_token>'

Use Case: External Ticketeer

Integrate an external system that handles the sales and seating with GUTS. A user can see his tickets in GUTS ticket wallet app and scan his ticket with GUTS scanner.

Authentication

A dashboard user account is required to continue the procedure. Contact GUTS to learn more and have your account generated. Check here how to login and here on how to use the tokens .

Get organization ID

You need to know your organization id if you want to create an event. Check here on how to retrieve it. Normally you are going to be part of one organization, so the list will contain only one item, which will be used to create the event. We are going to use the key id of that item for the next steps and refer to it as organization_id.

Create event

Check here how to create an event. You probably want to use hide: true and organization: <organization_id> from previous step. We refer to the returned id as event_id.

(Optional) Upload cover photo for event

In order to set the cover photo for an event you need to:

  1. Request upload url from GET protocol, check here how to do that, setting field cover.

  2. After that you need to upload the image to the amazon s3 bucket using the key returned by request upload url.

// We use javascript here for convenience, transforming the following code to another language is trivial.
// We assume that data is the response data from request_upload
// We use axios here, this can be replaced with any library

const s3Object = new FormData();

Object.keys(data.fields).forEach((k) => {
    s3Object.append(k, data.fields[k]);
});
s3Object.append('Content-Type', image.type);
s3Object.append('file', image);
axios.post(data.url, s3Object).then(() => {
    const url = data.url + data.fields.key
    // Your image is on the url, you can use it in cover key in event url
})
  1. Use the resulting key as cover in event edit api.

Create ticket kind

Check here how to create a ticket-kind. In the case of external ticketeer the recommended payload is:

{
   "event_id": "<event_id>", // From previous step
   "name": "My ticket kind",
   "description": "My descriptions", //OPTIONAL
   "amount": 0, // Amount is 0 in this case, since we don't want to sell through GET protocol but only through your system. This means that tickets are going to be created on the fly
   "price_buildup": [{"tag": "ticket", "vat": 0, "price": "34.00", "is_base": true}], // Adding the correct value will make reporting better
   "for_sale": false // don't sell through GUTS
}

We refer to the id of the object returned as ticketkind_id

Publish Event

Check here

Register Ticket

You need to have obtained already the user’s mobile phone in your system. Note: normalizing mobile phone is not required. +31611111111 and 0611111111 are both valid. After a successful ticket sale in your system, register ticket in GET protocol.

Check here how to make the request. You need to use ticketkind_id from previous step as ticket_kind. You need to use “pool”: “new” to create new tickets instead of using the ones that are for sale. If you followed the steps above, the ticketkind does not have any available tickets for sale. You need to use “paid_to”: “eo” meaning that the ticket was already paid to the Event organizer without going through GET protocol backend. You need to use “free”: false" meaning that it is not a gift.

The response contains an array of tickets, and each of them contains an array of privileges (in this case all of them are of length one). We are going to refer to the ids of this single item of the privileges array as privilege_id. We are going to refer to the ids of the tickets list as ticket_id

Register Seating for a ticket

Check here how to edit privileges. You need to use privilege_id from above and use info to add your seating details. This field will show up in the GUTS apps.

Invalidate tickets (Optional)

In case of editting/changing tickets in your system and you want to keep GET protocol in sync, you can invalidate tickets. You need to use ticket_id from previous step.

Endpoints

Authentication and Users

Customer request access token
POST/api/v1/mobile-auth/

Example URI

POST /api/v1/mobile-auth/
Request
HideShow
Headers
Content-Type: application/json
Body
{
  "recipient": "+31612345678",
  "locale": "en"
}
Schema
{
    "type": "object",
    "properties": {
        "recipient": {
            "type": "string"
            "description": "user's phone number"
        },
        "locale": {
            "type": "string"
            "description": "determines language used in SMS"
        }
    },
    "required": ["recipient"]
}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "authid": "7b5601a3-4a25-4955-8568-4f703a219aa1",
  "tries_left": 3,
  "used": false
}

Customer login
POST/api/v1/mobile-auth/{authid}

Example URI

POST /api/v1/mobile-auth/authid
URI Parameters
HideShow
authid
string (required) 

uuid to identify login request

Request
HideShow
Headers
Content-Type: application/json
Body
{
  "token": "2834",
  "locale": "en"
}
Schema
{
    "type": "object",
    "properties": {
        "recipient": {
            "type": "string"
            "description": "token sent to users phone"
        },
        "locale": {
            "type": "string"
            "description": "determines language used in SMS"
        }
    },
    "required": ["recipient"]
}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 62721,
  "username": "+3161345678",
  "first_name": "",
  "last_name": "",
  "email": "",
  "verified": false,
  "date_joined": "2019-02-06T12:26:15.357093+01:00",
  "profile_complete": false,
  "gender": null,
  "birthdate": null,
  "zipcode": "",
  "house_number": "",
  "locale": "nl",
  "opt_in": null,
  "avatar": null,
  "can_share_tickets": true,
  "refresh_token": "refresh_token",
  "jwt_token": "jwt_token"
}
Response  401
HideShow
Headers
Content-Type: application/json
Body
{
  "authid": "7b5601a3-4a25-4955-8568-4f703a219aa1",
  "tries_left": 2,
  "used": false
}

Event organizer Login
POST/api/v1/api-token-auth/

Event organizers login to GET protocol using their credentials instead of a mobile phone. Contact GET protocol to get your credentials.

Example URI

POST /api/v1/api-token-auth/
Request
HideShow
Headers
Content-Type: application/json
Body
{
  "username": "MY USERNAME",
  "password": "MY PASSWORD"
}
Schema
{
    "type": "object",
    "properties": {
        "username": {
            "type": "string"
            "description": "Username provided"
        },
        "password": {
            "type": "string"
            "description": "Your password"
        }
    },
    "required": ["username", "password"]
}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 62721,
  "username": "+3161345678",
  "first_name": "",
  "last_name": "",
  "email": "",
  "verified": false,
  "date_joined": "2019-02-06T12:26:15.357093+01:00",
  "profile_complete": false,
  "gender": null,
  "birthdate": null,
  "zipcode": "",
  "house_number": "",
  "locale": "nl",
  "opt_in": null,
  "avatar": null,
  "can_share_tickets": true,
  "refresh_token": "refresh_token",
  "jwt_token": "jwt_token"
}

JWT Token Refresh
POST/api/v1/api-token-refresh/

Eventually the jwt token will expire. A new one can be retrieved using the refresh token. If a new refresh token is generated the old one will become invalid.(logging in on a different device)

Example URI

POST /api/v1/api-token-refresh/
Request
HideShow
Headers
Content-Type: application/json
Body
{
  "client_id": "web",
  "refresh_token": "refresh_token"
}
Schema
{
    "type": "object",
    "properties": {
        "client_id": {
            "type": "string",
            "description": "can be anything, allows to be signed in 
                            multiple devices"
        },
        "refresh_token": {
            "type": "string",
            "description": "determines language used in SMS"
        }
    },
    "required": ["client_id", "refresh_token"]
}
Response  201
HideShow
Headers
Content-Type: application/json
Body
{
  "token": "jwt_token",
  "refresh_token": "refresh_token"
}

Self
GET/api/v1/users/self

Return the user that makes the request. The user is located from the information in the JWT token in the header.

Example URI

GET /api/v1/users/self
Request
HideShow
Headers
Content-Type: application/json
Authorization: JWT <token>
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
    "id":1,
    "username":"+3161234568",
    "first_name":"",
    "last_name":"",
    "email":"email@gmail.com",
    "verified":false,
    "is_active":true,
    "date_joined":"2018-04-03T11:15:55+02:00",
    "profile_complete":true,
    "gender":"o",
    "birthdate":"1989-01-02T01:00:00+01:00",
    "zipcode":"",
    "house_number":"",
    "locale":"en",
    "opt_in":"true",
}

Update details
PUT/api/v1/users/{id}

Example URI

PUT /api/v1/users/1
URI Parameters
HideShow
id
number (required) Example: 1

id of users

Request
HideShow
Headers
Content-Type: application/json
Authorization: JWT <token>
Body
{
    "id":1,
    "username":"+3161234568",
    "first_name":"",
    "last_name":"",
    "email":"email@gmail.com",
    "verified":false,
    "is_active":true,
    "date_joined":"2018-04-03T11:15:55+02:00",
    "profile_complete":true,
    "gender":"o",
    "birthdate":"1989-01-02T01:00:00+01:00",
    "zipcode":"",
    "house_number":"",
    "locale":"en",
    "opt_in":"true",
}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
    "id":1,
    "username":"+3161234568",
    "first_name":"",
    "last_name":"",
    "email":"email@gmail.com",
    "verified":false,
    "is_active":true,
    "date_joined":"2018-04-03T11:15:55+02:00",
    "profile_complete":true,
    "gender":"o",
    "birthdate":"1989-01-02T01:00:00+01:00",
    "zipcode":"",
    "house_number":"",
    "locale":"en",
    "opt_in":"true",
}

Organizations

List
GET/api/v1/organizations/

Example URI

GET /api/v1/organizations/
Request
HideShow
Headers
Content-Type: application/json
Authorization: JWT <token>
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": 1,
      "name": "My Org",
      "permissions": [],
      "floorplans": []
    }
  ]
}

Details
GET/api/v1/organizations/{id}

Example URI

GET /api/v1/organizations/123
URI Parameters
HideShow
id
string (required) Example: 123

id of an organization

Request
HideShow
Headers
Content-Type: application/json
Authorization: JWT <token>
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 123,
  "name": "My Org",
  "permissions": [],
  "floorplans": []
}

Events

A listing of all events.

List
GET/api/v1/events/{?filter,own}

Example URI

GET /api/v1/events/?filter=upcoming&own=True
URI Parameters
HideShow
filter
string (optional) Example: upcoming

only show upcoming events

own
boolean (optional) Example: True

only show events the user has tickets for. (this flag requires being logged in)

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
    "count":1,
    "next":null,
    "previous":null,
    "results":[
        {
            address: "address",
            city: "city",
            country: "NL",
            cover: "https://cover.jpg",
            ends: "2020-01-02T01:00:00+01:00",
            id: 1,
            location: "location",
            slug: "9a6936593705b0998868",
            sublocation: "",
            subtitle: "Subtitle",
            title: "Title",
            when: "2020-01-01T20:00:00+01:00"
        }
    ]
}

Detail
GET/api/v1/events/{slug}

Example URI

GET /api/v1/events/9a6936593705b0998868
URI Parameters
HideShow
slug
string (required) Example: 9a6936593705b0998868

slug of an event

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
    "id":11,
    "seating_image": "url",
    "cover":"url",
    "payment_methods":[
        "credit",
        "transfer"
    ],
    "tickets_per_rank":[
        {
            "kind":341,
            "rank":"Rank 2",
            "description":"",
            "price":0.0,
            "total":465,
            "max_per_user":null,
            "upsell":false
        },
        {
            "kind":734,
            "rank":"Rank 1",
            "description":"",
            "price":1.0,
            "total":98,
            "max_per_user":null,
            "upsell":false
        }
    ],
    "user_ticketlimit":8,
    "user_purchased_tickets":2,
    "state":"available",
    "created":"2018-04-30T13:49:02.139562+02:00",
    "modified":"2019-02-05T15:05:40.732443+01:00",
    "slug":"9a6936593705b0998868",
    "human_slug":"guts-app-test",
    "when":"2019-01-15T16:45:00+01:00",
    "ends":"2019-04-19T23:59:00+02:00",
    "doors_open":"2019-01-15T16:45:00+01:00",
    "sale_start":"2018-04-30T13:49:02+02:00",
    "title":"Guts App Test",
    "subtitle":"",
    "description":"description of event",
    "max_tickets":2,
    "location":"Pakhuis de Zwijger",
    "sublocation":"  ",
    "city":"Amsterdam",
    "address":"Piet Heinkade 179, 1019 HC",
    "country":"NL",
    "latitude":"52.3768450",
    "longitude":"4.9221170",
    "time_till_soldout":"2019-01-15T16:45:00+01:00",
    "publish_state":"published",
}

Create
POST/api/v1/events/

Example URI

POST /api/v1/events/
Request
HideShow
Headers
Content-Type: application/json
Body
{
    organization: 12,
    doors_open: ISO8601,
    when: ISO8601,
    ends: ISO8601,
    title: string,
    hide: true,

    subtitle: string,
    description: html_string,
    location: string,
    city: string,
    cover: 'url'

}
Schema
{
    "type": "object",
    "properties": {
        "organization": {
            "type": "integer"
            "description": "id of organization"
        },
        "doors_open": {
            "type": "ISO8601"
            "description": "start time of scanning"
        },
        "when": {
            "type": "ISO8601"
            "description": "start time of event"
        },
        "ends": {
            "type": "ISO8601"
            "description": "end time of event"
        },
        "title": {
            "type": "string",
            "description": "Title of event"
        },
        "hide": {
            "type": boolean,
            "description": "should the event be hidden from the GUTS website?"
        },
        "cover": {
            "type": "url",
            "description: "cover image of event"
        },[POST /api/v1/events/]
        "subtitle": {
            "type": "string",
            "description": "Subtitle of event"
        },
        "description": {
            "type": "html|string"
            "description": "Extra information for the event"
        },
        "location": {
            "type": "string",
            "description": "Description of the event location"
        },
        "city": {
            "type": "string",
            "description": "city of the event"
        }
    },
    "required": ["organization", "doors_open", "when", "ends", "title", "hide"]
}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
    "id":11,
    "seating_image": null,
    "cover": null,
    "payment_methods":[],
    "tickets_per_rank":[],
    "state": "available",
    "created": "2018-04-30T13:49:02.139562+02:00",
    "modified": "2019-02-05T15:05:40.732443+01:00",
    "slug": "9a6936593705b0998868",
    "human_slug":"guts-app-test",
    "when":"2019-01-15T16:45:00+01:00",
    "ends":"2019-04-19T23:59:00+02:00",
    "doors_open":"2019-01-15T16:45:00+01:00",
    "sale_start":"2018-04-30T13:49:02+02:00",
    "title":"Guts App Test",
    "subtitle":"",
    "description":"description of event",
    "max_tickets":2,
    "location":"Pakhuis de Zwijger",
    "sublocation":"  ",
    "city":"Amsterdam",
    "address":"Piet Heinkade 179, 1019 HC",
    "country":"NL",
    "latitude":"52.3768450",
    "longitude":"4.9221170",
    "time_till_soldout":"2019-01-15T16:45:00+01:00",
    "publish_state":"published",
}

Edit
PATCH/api/v1/events/

Example URI

PATCH /api/v1/events/
Request
HideShow
Headers
Content-Type: application/json
Body
{
    organization: 12,
    doors_open: ISO8601,
    when: ISO8601,
    ends: ISO8601,
    title: string,
    hide: true,

    subtitle: string,
    description: html_string,
    location: string,
    city: string,
    cover: 'url'

}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
    "id":11,
    "seating_image": null,
    "cover": null,
    "payment_methods":[],
    "tickets_per_rank":[],
    "state": "available",
    "created": "2018-04-30T13:49:02.139562+02:00",
    "modified": "2019-02-05T15:05:40.732443+01:00",
    "slug": "9a6936593705b0998868",
    "human_slug":"guts-app-test",
    "when":"2019-01-15T16:45:00+01:00",
    "ends":"2019-04-19T23:59:00+02:00",
    "doors_open":"2019-01-15T16:45:00+01:00",
    "sale_start":"2018-04-30T13:49:02+02:00",
    "title":"Guts App Test",
    "subtitle":"",
    "description":"description of event",
    "max_tickets":2,
    "location":"Pakhuis de Zwijger",
    "sublocation":"  ",
    "city":"Amsterdam",
    "address":"Piet Heinkade 179, 1019 HC",
    "country":"NL",
    "latitude":"52.3768450",
    "longitude":"4.9221170",
    "time_till_soldout":"2019-01-15T16:45:00+01:00",
    "publish_state":"published",
}

Request upload url
POST/api/v1/events/request_upload

Example URI

POST /api/v1/events/request_upload
Request
HideShow
Headers
Content-Type: application/json
Body
{
  "field": "cover",
  "filename": "filename.png"
}
Schema
{
    "type": "object",
    "properties": {
        "field": {
            "type": "oneOf: [cover, seating_image]"
            "description": "the field that you are about to edit"
        },
        "filename": {
            "type": "string"
            "description": "name of the file"
        }
    },
    "required": ["filename", "field"]
}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
    "url":"https://otas3staging.s3.amazonaws.com/",
    "fields":{
        "acl":"...",
        "cache-control":"...",
        "key":"...",
        "x-amz-algorithm":"...",
        "x-amz-credential":"...",
        "x-amz-date":"...",
        "policy":"...",
        "x-amz-signature":"..."}
    }
}

Publish
POST/api/v1/events/publish

Publishing an event:

  • Changes event state from draft to published.

  • Invalidates all the existing tickets

  • Shows event in ticket listings (if hide = true)

Example URI

POST /api/v1/events/publish
Request
HideShow
Headers
Content-Type: application/json
Body
No body is required
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
        'success': true
    }

TicketKinds

TicketKind list
GET/api/v1/ticket-kinds/{?event_id}

Example URI

GET /api/v1/ticket-kinds/?event_id=102,
URI Parameters
HideShow
event_id
number (optional) Example: 102,

filter tickets per event

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": 734,
      "type_id": 525,
      "available_from": "2018-04-30T13:49:02+02:00",
      "available_to": "2019-04-19T23:59:00+02:00",
      "root": true,
      "combi": false,
      "price_buildup": [
        {
          "tag": "Base Ticket",
          "vat": "0.21",
          "price": "1.00"
        }
      ],
      "price": "1.00",
      "created": "2018-09-04T16:03:38.727535+02:00",
      "modified": "2019-02-04T12:45:32.263222+01:00",
      "name": "Paid entrance",
      "description": "",
      "for_sale": true,
      "upsell": false,
      "max_amount": 100,
      "max_per_user": null,
      "local_available_from": null,
      "local_available_to": null,
      "guest": false
    }
  ]
}

Detail
GET/api/v1/ticket_kinds/{id}/

Example URI

GET /api/v1/ticket_kinds/734/
URI Parameters
HideShow
id
number (required) Example: 734

id of ticket

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 734,
  "type_id": 525,
  "available_from": "2018-04-30T13:49:02+02:00",
  "available_to": "2019-04-19T23:59:00+02:00",
  "root": true,
  "combi": false,
  "price_buildup": [
    {
      "tag": "Base Ticket",
      "vat": "0.21",
      "price": "1.00"
    }
  ],
  "price": "1.00",
  "created": "2018-09-04T16:03:38.727535+02:00",
  "modified": "2019-02-04T12:45:32.263222+01:00",
  "name": "Paid entrance",
  "description": "",
  "for_sale": true,
  "upsell": false,
  "max_amount": 100,
  "max_per_user": null,
  "local_available_from": null,
  "local_available_to": null,
  "guest": false
}

Create simple
POST/api/v1/tickets/create_simple/

Example URI

POST /api/v1/tickets/create_simple/
Request
HideShow
Headers
Content-Type: application/json
Body
{
    event_id: event_id,
    name: "name",
    description: "description",
    amount: 20,
    price_buildup: [{"tag": "ticket", "vat": 0, "price": "34.00", "is_base": true}]
    for_sale: true
}
Schema
{
    "type": "object",
    "properties": {
        "event_id": {
            "type": "integer"
            "description": "event id of the event that this ticket kind belongs to"
        },
        "name": {
            "type": "string",
            "description": "name of the ticket kind"
        },
        "description": {
            "type": "string",
            "description"; "extra information on the ticketkind"
        },
        "amount": {
            "type": "integer",
            "description": "number of tickets to sell"
        },
        "price_buildup": {
            "type": "array",
            "description": "extended information of price, the total price is the sum of these parts",
            "item": {
                "type": "object",
                "properties": {
                    "is_base": {
                        "type": "boolean",
                        "description": "is this part the base price? Exactly one item has to be true"
                    },
                    "tag": {
                        "type": "string",
                        "description": "tag the price part, usefull for reports"
                    },
                    "price": {
                        "type": "decimal string",
                        "description: "price of the part"
                    },
                    "vat": {
                        "type": "float [0-1]",
                        "description" "vat of the price part"
                    }
            },
        },
        "for_sale": {
            "type": "boolean",
            "description": "false disables selling this ticket kind"
        }
    },
    "required": ["for_sale", "price_buildup", "amount", "name", "event_id"]
}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 734,
  "type_id": 525,
  "available_from": "2018-04-30T13:49:02+02:00",
  "available_to": "2019-04-19T23:59:00+02:00",
  "root": true,
  "combi": false,
  "price_buildup": [
    {
      "tag": "ticket",
      "vat": "0",
      "price": "34.00",
      "is_base": true
    }
  ],
  "price": "34.00",
  "created": "2018-09-04T16:03:38.727535+02:00",
  "modified": "2019-02-04T12:45:32.263222+01:00",
  "name": "Name",
  "description": "",
  "for_sale": true,
  "upsell": false,
  "max_amount": 100,
  "max_per_user": null,
  "local_available_from": null,
  "local_available_to": null,
  "guest": false
}

Tickets

All tickets have a Ticket kind. The ticket kinds are determined by the organiser when setting up an event. A ticket kind can represent a simple entrance ticket but there is much more. There are combi tickets, early bird, upsell and guest tickets.

When a customer buys a ticket he specifies the ticket kind. The api then creates a ticket with the correct ticket kind for the user.

List
GET/api/v1/tickets/{?event_id}

Show all tickets belonging to a user

Example URI

GET /api/v1/tickets/?event_id=102,
URI Parameters
HideShow
event_id
number (optional) Example: 102,

filter tickets per event

Request
HideShow
Headers
Content-Type: application/json
Authorization: JWT <token>
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": 123620,
      "state": "resold",
      "guest": false,
      "kind_name": "Paid entrance",
      "kind_description": "",
      "owner_id": 9500,
      "kind_id": 734,
      "price": 1,
      "event": 102,
      "seatings": [],
      "resellable": false,
      "type": "normal"
    },
    {
      "id": 330230,
      "state": "sold",
      "guest": false,
      "kind_name": "Paid entrance",
      "kind_description": "",
      "owner_id": 9500,
      "kind_id": 734,
      "price": 1,
      "event": 102,
      "seatings": [],
      "resellable": true,
      "type": "normal"
    }
  ]
}

Detail
GET/api/v1/tickets/{id}/

Show all tickets belonging to a user

Example URI

GET /api/v1/tickets/123620/
URI Parameters
HideShow
id
number (required) Example: 123620

id of ticket

Request
HideShow
Headers
Content-Type: application/json
Authorization: JWT <token>
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 123620,
  "state": "resold",
  "guest": false,
  "kind_name": "Paid entrance",
  "kind_description": "",
  "owner_id": 9500,
  "kind_id": 734,
  "price": 1,
  "event": 102,
  "seatings": [],
  "resellable": false,
  "type": "normal"
}

Create gift ticket
POST/api/v1/tickets/create_gift_ticket

Example URI

POST /api/v1/tickets/create_gift_ticket
Request
HideShow
Headers
Content-Type: application/json
Body
[{
    'username': mobile,
    'ticket_kind': ticket_kind_id,
    'notify_customer': true will send an SMS to the customer,
    'amount': 2, // how many tickets?
    'pool': 'new', // Create new ticket, not use one of the precreated ones
    'paid_to': 'eo', // EO: Event organizer
    'free': false, // always false, true means that the ticket was a gift from the theater
    'payment_method': 'pin' | 'cash' | 'digital' | 'other'
}, {
    'username': mobile,
    'ticket_kind': ticket_kind_id,
    'notify_customer': false,
    'amount': 3,
    'pool': 'new,
    'paid_to': 'eo',
    'free': false,
    'payment_method': 'pin' | 'cash' | 'digital' | 'other'
}]
Schema
{
    "type": "array",
    "items": {
        "type": "object",
        "required": [
            "username",
            "ticket_kind",
        ],
        "properties": {
            "username": {"type": "string"},
            "ticket_kind": {"type": "integer"},
            "notify_customer": {"type": "boolean", "default": True,
                                "description": "send email or sms to user"},
            "amount": {"type": "integer", "default": 1, "minimum": 1,
                    "description": "this value is ignored when privileges are specified"},
            "pool": {
                "type": "string", "default": "available",
                "pattern": "available|new|locked",
                "description": "options are available, locked, new."
                "Determines which pool to user for the privileges"
            },
            "free": {"type": "boolean", "default": true},
            "privileges": {
                "type": "array",
                "items": {"type": "integer"},
                "description": "ids of privileges to be used. Will only work for non combi tickets. Will create a tickets for each privileges
            },
            "payment_method": {
                "type": ["string", "null"],
                "pattern": "pin|cash|digital|other",
                "description": "How was the payment done, if any"
            },
            "paid_to": {
                "type": ["string", "null"],
                "description": "To whom was the payment done"
            }
        }
    }
}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
    'status': 'success',
    'tickets': [{
        'id': 17, 
        'state': 'sold',
        'guest': false,
        'kind_name': 'entrance regular',
        'kind_description': '',
        'owner_id': 55,
        'kind_id': 28,
        'price': '0.00',
        'event': 82,
        'resellable': false,
        'type', 'normal',
        'privileges': [{
            'id': 410,
            'type_id': 29,
            'allocated_id': 17,
            'info': null,
            'seat': null,
            'created': '2019-04-25T11:01:53.583184+02:00',
            'modified': '2019-04-25T11:01:53.583209+02:00',
            'locked': false,
            'claimed': false
        }],
        'put_for_sale_by_id': null
    }]
}

Delete
DELETE/api/v1/tickets/{id}

Example URI

DELETE /api/v1/tickets/1
URI Parameters
HideShow
id
number (required) Example: 1

id of ticket

Response  204

Privileges

In GET protocol a privilege is the object that gives the user the privilege to perform certain actions. Examples:

  • User has the privilege to enter the theater A for show X and seat on Seat Y.

  • User has the privilege to park on a parking spot on theater X on day Y.

A Ticket is a collection of privileges. The privilege is the item that gets scanned (executed) when a user goes through the scanning process.

List
GET/api/v1/privileges/

Example URI

GET /api/v1/privileges/
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "previous": null,
  "next": null,
  "count": 2,
  "results": [
    {
      "id": 421,
      "type_id": 31,
      "allocated_id": 19,
      "note": "",
      "info": "NOTE",
      "seat": "INFO",
      "code": "code",
      "created": "2019-04-25T11:39:50.325983+02:00",
      "modified": "2019-04-25T11:39:50.712387+02:00",
      "locked": false,
      "claimed": true
    },
    {
      "id": 421,
      "type_id": 31,
      "allocated_id": 19,
      "note": "",
      "info": "NOTE",
      "seat": "INFO",
      "code": "code",
      "created": "2019-04-25T11:39:50.325983+02:00",
      "modified": "2019-04-25T11:39:50.712387+02:00",
      "locked": false,
      "claimed": true
    }
  ]
}

Edit
PATCH/api/v1/privileges/{id}

Example URI

PATCH /api/v1/privileges/1
URI Parameters
HideShow
id
number (required) Example: 1

id of privilege

Request
HideShow
Headers
Content-Type: application/json
Body
{
  "note": "NOTE",
  "info": "INFO"
}
Schema
{
  "type": "object",
  "properties": {
    "note": {
      "type": "string",
      "description": "internal text not visible to the customer"
    },
    "info": {
      "type": "string",
      "description": "Text visible to the customer"
    }
  }
}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 421,
  "type_id": 31,
  "allocated_id": 19,
  "note": "",
  "info": "NOTE",
  "seat": "INFO",
  "code": "code",
  "created": "2019-04-25T11:39:50.325983+02:00",
  "modified": "2019-04-25T11:39:50.712387+02:00",
  "locked": false,
  "claimed": true
}

Orders

List
GET/api/v1/orders/

A list of all the orders belonging to the user.

Example URI

GET /api/v1/orders/
Request
HideShow
Headers
Content-Type: application/json
Authorization: JWT <token>
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": 1,
      "total": "10.00",
      "state": "pending",
      "last_payment_status": "pending",
      "details": {
        "event_id": 10,
        "privacy_policy_url": null,
        "items": [
          {
            "kind": 3007,
            "rank": "Test",
            "amount": 1,
            "price": 10,
            "sub": 10
          }
        ],
        "title": "title"
      },
      "owner": "4",
      "success_text": "",
      "paid_to": null
    }
  ]
}

Detail
GET/api/v1/orders/{id}

Example URI

GET /api/v1/orders/1
URI Parameters
HideShow
id
number (required) Example: 1

id of order

Request
HideShow
Headers
Content-Type: application/json
Authorization: JWT <token>
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 1,
  "total": "10.00",
  "state": "pending",
  "last_payment_status": "pending",
  "details": {
    "event_id": 10,
    "privacy_policy_url": null,
    "items": [
      {
        "kind": 3007,
        "rank": "Test",
        "amount": 1,
        "price": 10,
        "sub": 10
      }
    ],
    "title": "title"
  },
  "owner": "4",
  "success_text": "",
  "paid_to": null
}

Start payment
POST/api/v1/orders/{id}/start_payment/

The psp_arguments are passed directly to your external payment provider. For development there is a dummy payment provider. The dummy requires one argument, return_page. This is the url you want the user return to after completing the dummy payments. The endpoint will return an url where the user can make its payment. If the order is not in a pending state it will return status: error.

Example URI

POST /api/v1/orders/1/start_payment/
URI Parameters
HideShow
id
number (required) Example: 1

id of order

Request
HideShow
Headers
Content-Type: application/json
Authorization: JWT <token>
Body
{
    psp_arguments: {"return_page": "your.app"}
}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "status": "redirect",
  "redirect": "psp_url"
}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "status": "error",
  "error": "invalid_order_state"
}

Carts

To buy tickets, they have to be put into a cart. Tickets that are in a cart are reserved and cannot be bought by somebody else. A cart can only hold tickets of a single event. Also events can have rules on the maximum amount of tickets each user can buy. These are also enforced.

guid Cart.

The Frontend needs to create guid of the cart itself. If it doesn’t exist yet the api will create it on the fly. The format is: <uuid4>-<event_id>. The actual reqex:

[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}-[0-9]+

Get cart
GET/api/v1/carts/{guid}

Example URI

GET /api/v1/carts/uuid
URI Parameters
HideShow
guid
string (required) Example: uuid

1 - guid of cart.

Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 413005,
  "guid": "uid",
  "tickets": []
}

Add tickets
PUT/api/v1/carts/{guid}

When updating tickets make sure you send the whole tickets state. Not just the tickets you want to add.

Example URI

PUT /api/v1/carts/uuid
URI Parameters
HideShow
guid
string (required) Example: uuid

1 - guid of cart.

Request
HideShow
Headers
Content-Type: application/json
Body
{
  "event": 1,
  "ranks": [
    {
      "kind": 2,
      "amount": 0
    },
    {
      "kind": 1,
      "amount": 2
    }
  ]
}
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "id": 413005,
  "guid": "uid",
  "tickets": [
    {
      "kind": 2,
      "amount": 0
    },
    {
      "kind": 1,
      "amount": 2
    }
  ]
}

Checkout
PUT/api/v1/carts/{guid}/checkout/

Checking out the cart will create an order to start a payment. The user needs to be logged in to perform this action. If the content of the cart is changed the order gets cancelled.

Example URI

PUT /api/v1/carts/uuid/checkout/
URI Parameters
HideShow
guid
string (required) Example: uuid

1 - guid of cart

Request
HideShow
Headers
Content-Type: application/json
Authorization: JWT <token>
Response  200
HideShow
Headers
Content-Type: application/json
Body
{
  "order": 1
}

Generated by aglio on 22 May 2019