Sagenda API v3

Re-designed system interface for more productivity

Introduction

Sagenda’s new refined Application Programming Interface (API) provides clarity and expressiveness to interaction with our booking system for third-party developers.

You can follow a step-by-step guide laid out in this page for detailed info and then try it out using PostMan Doc. Please don’t use Rapid API (formerly named Mashape) anymore.

All requests to API v3 endpoints are to be performed via HTTPS. HTTP requests are redirected to HTTPS endpoint with HTTP 301 code

Authentication

For most API operations you will be required to provide an access token. Note that this is different from your Authentication Code in Account Settings, but you’ll still need one to obtain an actual token. Authentication code can be found in the Dashboard or in Settings / General Settings / Authentication code. Your authentication code looks like a 32 chars alphanumeric string.

Please, note: all path to API endpoints in this document are given relative to the website (sagenda.net) domain

Getting access token

Endpoint URL: /api/v3/token

Method: POST

Authentication required: No

Submit a POST request with the Content-Type: x-www-form-urlencoded header, with a body like this:

grant_type=api_token&api_token=[authentication-code]

You should substitute [authentication-code] with the code you’ve got from your Sagenda account settings.

Sample call (ajax)

$.ajax({
  "async": true,
  "crossDomain": true,
  "url": "https://sagenda.net/api/v3/token",
  "method": "POST",
  "headers": {
    "content-type": "application/x-www-form-urlencoded"
  },
  "data": {
    "grant_type": "api_token",
    "api_token": "[authentication-code]"
  }
}).done(function (response) {
  console.log(response);
});

In case of a valid token, you’ll receive a JSON response with a following format:

{
  "access_token": "[access-token]",
  "token_type": "bearer",
  "expires_in": [expiration]
}

Where [access-token] is a string containing an access token, [expiration] is time in seconds before this token expires. We suggest that you store this information locally and request a new token only when this one expires. A token, once issued, is valid for all requests.

Using your access token

Endpoint URL: /api/v3/status/oauth

Method: GET

Authentication required: Yes

To authenticate using access token, you should supply it in the HTTP Authentication header, using the Bearer scheme. It looks like this:

Authentication: Bearer [access-token]

Please note that access token shouldn’t be wrapped in quotes, it’s just a string value you’ve got from authentication endpoint. Unsuccessful authentication attempts will result in HTTP 403 Forbidden response.

From now, for each endpoint that says “Authentication required: Yes” you’re required to include valid Authentication header within your request

To check you have an authentication working, you can submit a GET request with the authentication header as described above to this endpoint. HTTP 200 response means you’re all set to use API with this temporary token! Invalid token will return HTTP 403. Please note that this is just for your convenience while developing, you are not required to call this.

Sample call (ajax)

$.ajax({
  "async": true,
  "crossDomain": true,
  "url": "https://sagenda.net/api/v3/status/oauth",
  "method": "GET",
  "headers": {
   "Authorization": "Bearer [access-token]"
  }
}).done(function (response) {
  console.log(response);
});

Getting bookable items

Endpoint URL: /api/v3/bookableItems

Method: GET

Authentication required: Yes

Make sure you have some bookable items defined in your Sagenda account, then call this endpoint to get a list of them in simple JSON array. Only identifier and name fields are guaranteed to be present in objects, other fields are optional and undefined by default.

 

Sample call (ajax)

 

Example response:

[
    {
        "identifier": "589261684dec5221a430bc28",
        "name": "Car",
        "location": "Mountainville, CA",
        "description": "Economy deal"
    },
    {
        "identifier": "5a00e9e54dec521ad8fd88a8",
        "name": "Boat"
    }
]

Where:

identifier: string (Item id)

name: string (Item name)

location: string, undefined (Optional. Item location field. If empty – undefined)

description: string, undefined (Optional. Item description field. If empty – undefined)

Fetching events for bookable item

Endpoint URL: /api/v3/events/[startDate]/[endDate]/[bookableItem]

Method: GET

Authentication required: Yes

Now that you have a list of bookable items, you can pick an identifier of one of them and request events from associated event schedules you’ve defined in your Sagenda account. This routine only returns events that are in future and available for booking.

Parameters are passed via URL:

startDate: string (An inclusive search start date in ISO 8601 format –  YYYY-MM-DD, e.g. 2018-03-24)

endDate: string (An inclusive search end date in ISO 8601 format –  YYYY-MM-DD)

bookableItem: string (Alphanumeric identifier of the requested bookable item)

Sample call (ajax)

$.ajax({
  "async": true,
  "crossDomain": true,
  "url": "https://sagenda.net/api/v3/events/2018-04-01/2018-04-23/5a424886dc94451bb0242e0f",
  "method": "GET"
}).done(function (response) {
  console.log(response);
});

Let’s have a look at an example response and go through all the options presented:

[
  {
      "identifier": "NWE2ZWI3Y2ZkYzk0NDUyZjk4MmJmMzI3OzQvMjMvMjAxOCAxMjowMCBBTTs1YTQyNDg4NmRjOTQ0NTFiYjAyNDJlMGY=",
      "type": "allDay",
      "date": "2018-04-23",
      "endDate": "2018-04-25",
      "payment": {
          "amount": 14.88,
          "currencyCode": "USD",
          "note": "Pre-payment for reservation"
      },
      "membership": {
          "maximum": 3,
          "reserved": 1
      }
  },
  {
      "identifier": "NWFiZDkyM2JkYzk0NDUyZmY0N2UyY2E1OzQvMjMvMjAxOCA1OjAwIEFNOzVhNDI0ODg2ZGM5NDQ1MWJiMDI0MmUwZg==",
      "type": "schedule",
      "from": "2018-04-23T05:00Z",
      "to": "2018-04-23T07:00Z"
  },
  {
      "identifier": "NWFiZDkyM2JkYzk0NDUyZmY0N2UyY2E1OzQvMjMvMjAxOCA1OjAwIEFNOzVhNDI0ODg2ZGM5NDQ1MWJiMDI0MmUwZg==",
      "type": "dateAndTime",
      "from": "2018-04-23T12:00Z",
      "to": "2018-04-25T18:00Z"
  }
]

As you can see, there are many possibilities, so let’s break them down. Response from this endpoint is always a JSON array, containing zero or more events that belong to the requested time range.

Each object is guaranteed to have a unique identifier (you will need it later for booking), type (corresponds to your event schedule type), and some variables, depending on type:

for “allDay” type (All Day event):

date: string (Date of the event beginning in YYYY-MM-DD format)

endDate: string (Date of the event end in YYYY-MM-DD format)

for “schedule” or “dateAndTime” type (Schedule or Date and time event):

 from: string (Timestamp of the event beginning in YYYY-MM-DD’T’HH:MM’Z’ format – ISO 8601 w/o seconds)

to: string (Timestamp of the event end in YYYY-MM-DD’T’HH:MM’Z’ format – ISO 8601 w/o seconds)

Although time is denoted as being UTC (Z), it is actually user-defined time not belonging to a particular timezone (we don’t ask people to specify timezone for events). You should treat every timestamp as local time and do not perform any operations on it

Other variables are only present for certain types of events:

for paid events (with our PayPal module):

payment: object (Represents an info about payment for this particular occurrence)

amount: decimal (Actual amount to be paid)

currencyCode: string (Three-letter ISO code for currency, e.g. USD, CHF, CNY)

note: string (Optional. Note to the buyer concerning this payment)

for multi-user events:

membership: object (Represents an info about this event occupancy)

maximum: integer (Maximum amount of member allowed under this event)

reserved: integer (How many member have already booked this event and are actively booking right now)

Please note that all these fields are for display purpose and your convenience. You need only event identifiers to book an event.

Acquiring event lock

Endpoint URL: /api/v3/eventLocks

Method: POST

Authentication required: Yes

You’ve picked an event identifier from previous step and now you need to put a hold on it, to prevent other users from booking it until a provided expiration timestamp. You need to send a POST request with application/json body, that looks like this:

{
  "eventIdentifier": "[event-identifier]",
  "userIdentifier": "[user-identifier]", // Optional
  "participants": 1 // Optional
}

Where eventIdentifier is the identifier string you’ve picked from event search response, and participants is the number of places you want to book under one member (default is one). Participant requests larger than two are only valid for multiuser events (see membership object in previous step).

userIdentifier field is set only if you want to manage (cancel or book) your event locks in bulk. A new identifier will be assigned for you if you don’t specify in the event lock request. After that you can use this received identifier in subsequent request just in case you need to book or cancel them all at once.

 

Please note that setting user identifier does not extend the expiration time of your event lock. If you’re booking many events, be sure to keep track of the lock’s expiry time

Sample call (ajax)

 

If your request was successful, you’ll receive a uniform response:

{
    "identifier": "15b59439d53142b9a463eddd",
    "eventIdentifier": "NWE0MjRiMThkYzk0NDUxYzk0NGI2ZTViO1R1ZSwgMjYgRGVjIDIwMTcgMDA6MDA6MDAgR01UOzVhNDI0ODU1ZGM5NDQ1MWJiMDI0MmUwYw==",
    "userIdentifier": "6fad1f1e-cf01-4c1b-9c5b-549d17916ece",
    "expires": "2017-12-26T21:27Z",
    "participants": 1
}

Let’s go through variables:

identifier: string (Event lock identifier to be supplied for final booking step)

eventIdentifier: string (Copy of eventIdentifier this lock represents. For reference)

userIdentifier: string (Unique user identifier. If the valid identifier was supplied to the endpoint, returns it. Else, generates a new one)

expires: string (Expiry date/time for this event lock in ISO 8601 combined date-time format (YYYY-MM-DD’T’HH’:’MM’Z’) string, e.g. 2018-03-09T19:28Z)

Booking an event

Endpoint URL: /api/v3/events
Method: POST
Authentication required: Yes

Finally, after all the hard work, we get to book an event. You’ll need your event and lock identifiers, plus some user date that you are to collect. Booking request is sent as a JSON body and looks like this:

{
  "eventIdentifier": "[event-identifier]",
  "lockIdentifier": "[event-lock-identifier]",
  "member": { 
    "email": "mary_smiths@example.com",
    "courtesy": "Mrs.",
    "firstName": "Mary",
    "lastName": "Smiths",
    "phoneNumber": "+15082749385",
    "description": "Can be late by about 15 minutes"
  }
}

Where eventIdentifier is event identifier from event search response (also available within lock object for your convenience), and lockIdentifier should be valid and non-exprired lock identifier for that event,

Good news is, all of the member object fields are optional. But if you want to personalize your customer experience and keep track of your business, hang on:
– email: string (Customer e-mail. Will be used to send a booking confirmation)
firstName, lastName: string, string (Customer names, if applicable)
phoneNumber: string (Customer phone number. If you’re using our SMS module and want customer to be notified of the event, you should provide a valid international phone number here (with + prefix))
description: string (A place for customer notes to be communicated to event organizer)

You can mix and match any of member variable in your request.

Sample call (ajax)

$.ajax({
  "async": true,
  "crossDomain": true,
  "url": "https://sagenda.net/api/v3/events",
  "method": "POST",
  "headers": {
    "Content-Type": "application/json"
  },
  "processData": false,
  "data": "{\"eventIdentifier\": \"[event-identifier]\", \"lockIdentifier\": \"[event-lock-identifier]\",\"member\": { \"email\": \"example@example.com\" }}"
}).done(function (response) {
  console.log(response);
});

The routine returns HTTP 201 Created, if booking was successful for free event, and HTTP 202 Accepted, if booking accepted for paid event processing. Response for paid event booking will look like this:

{ 
  "message": "Please finish event booking by paying via supplied URL", 
  "paymentUrl": "https://paypal.com/..." 
}

So if you get this response, you should redirect a user to complete a payment on payment gateway website located at paymentUrl. After successful payment, it will be automatically processed and confirmation will be sent to member’s email

Request multiple event locks

Endpoint URL: /api/v3/eventLocks/multi

Method: POST

Authentication required: Yes

Using this endpoint, you can request multiple event lock at the same time, either for single or multi-booking use. Make sure to use same userIdentifier for all of the bookings supposed to be booked at the same time (you can just omit it in the first request to the endpoint in user session, and then just use the received value in every consequent request)

Requested events must belong to the same account you’re providing a token for. 

You need to send a POST request with application/json body that looks like this:

{
  "userIdentifier": "[user-identifier]", // Optional
  "events": [
	{
	    "eventIdentifier": "[event-identifier]",
  	    "participants": 1 // Optional

	},
  ]
}

 

This endpoint accepts booking requests in form of event-member mappings. Each object in mappings array should contain an:  

– eventIdentifier of a particular event and members array with at least one entry (member fields are optional and you can mix and match different properties).

– userIdentifier should represent a shared identifier used in event lock requests for events and members in question

– events is an array of single event lock requests (see “Acquiring event lock”), except userIdentifier is supplied outside the scope of the single event

Response status code meaning:

HTTP 201: Event locks created. If errors field is present, some errors occurred in the process and no locks created for events in question.

Response fields:

  • userIdentifier: string (Identifier to user to keep track of events in the same user session)
  • locks: object EventLock[] (Resultant event locks, you can keep track of them separately, if you’re using them across multiple single-booking request, or if you’re multi-booking, it is enough to store the userIdentifier)
    • For EventLock fields see “Acquiring event lock”

Booking multiple events

Endpoint URL: /api/v3/events/multi

Method: POST

Authentication required: Yes

If you want to book multiple events at once with Sagenda API, use this endpoint.

Rules for multi-booking:

  • Events should be from your current Sagenda account (the one you’re providing a token for)
  • You can mix paid and free events in one booking
  • Paid events should all be in the same currency

You need to send a POST request with application/json body, that looks like this:

{
  "userIdentifier": "[user-identifier]",
  "member": {
     // Fields are optional, but you must supply an object
    "email": "mary_smiths@example.com",
    "courtesy": "Mrs.", 
    "firstName": "Mary",
    "lastName": "Smiths",
    "phoneNumber": "+15082749385",
    "description": "Can be late by about 15 minutes"
  }
}

Where userIdentifier is user identifier shared across your event locks. All events that have been locked using this identifier will be booked with the provided member object.

 

Sample call (ajax)

$.ajax({
  "async": true,
  "crossDomain": true,
  "url": "https://sagenda.net/api/v3/events/multi",
  "method": "POST",
  "headers": {
    "content-type": "application/json",
    "authorization": "Bearer [access-token]"
  },
  "processData": false,
  "data": "{\"userIdentifier\": \"2292a080-aa29-4c01-ab7f-b633c48d23bf\",\"member\": {\"email\": \"sagenda@testmail.com\"}}"
}).done(function (response) {
  console.log(response);
});

Response status code meaning:

HTTP 201: Some or all bookings were successful

HTTP 202: Some or all bookings were successful, but user needs to pay for some events via link in paymentUrl response field

Response fields:

– message: string (User-readable English message about booking result)
– (optional) paymentUrl: string (Link to payment service to complete paid events booking)
– (optional) failedBookings: string[] (If some requested bookings didn’t successfully complete, you will get an array of their eventIdentifier value you can use to manage the situation )

Booking multiple members

Endpoint URL: /api/v3/events/multi-member

Method: POST

Authentication required: Yes

Using this endpoint, you can book both complex event and member combinations; you can book multiple events for different members just in one call.

Rules for multi-booking remain the same (see “Booking multiple events”)

You need to send a POST request with application/json body that looks like this:

{
  "userIdentifier": "[user-identifier]",
  "mappings": 
  [
    {
      "eventIdentifier": "[event-identifier-1]",
      "members": 
      [
        {
          "email": "[email-1]",
        },
        {
          "email": "[email-2]", 
          "participants": N
        }
      ]
    },
    {
      "eventIdentifier": "[event-identifier-2]",
      "members": 
      [
        {
          "email": "[email-2]",
          "firstName": "[name]"
      }
      ]
    }
  ] 
}

This endpoint accepts booking requests in form of event-member mappings. Each object in mappings array should contain an eventIdentifier of a particular event and members array with at least one entry (member fields are optional and you can mix and match different properties).

userIdentifier should represent a shared identifier used in event lock requests for events and members in question. Pay attention to event lock participants count so it matches (or exceeds) your member count for a particular event.

Response status code meaning:

HTTP 201: Some or all bookings were successful

HTTP 202: Some or all bookings were successful, but user needs to pay for some events via link in paymentUrl response field

Response fields:

  • (optional) paymentUrl: string (Link to payment service to complete paid events booking)
  • (optional) failedBookings: object EventMemberMapping[] (If some of the requested bookings didn’t successfully complete, you will get an array of their mappings you can use to manage the situation)
    • EventMemberMapping fields:
      • eventIdentifier: string (Identifier of the event affected)
      • member: object[] (Member entities that failed to be booked

Cancel single event lock

Endpoint URL: /api/v3/eventLocks/{eventLockId}

Method: DELETE

Authentication required: Yes

If a user changed his mind and you need to get rid of event lock, you can issue a HTTP DELETE request to this endpoint using the identifier of event lock in question. You can only delete locks made for events that belong to the account

Response status code meaning:

HTTP 204: Event lock was deleted

HTTP 403: You do not have permission to delete this lock

HTTP 404: Event lock doesn’t exist

HTTP 500: Account does not exist anymore

Response fields:

Empty response

 

 

Cancel user event locks

Endpoint URL: /api/v3/eventLocks/user/{userIdentifier}

Method: DELETE

Authentication required: Yes

When you need to get rid of all of the event locks made in the same user session, for example, when user leaves service without completing the booking, you can cancel all of the event locks with the given userIdentifier to avoid redundant repetitive calls for each event lock individually.

Response status code meaning:

HTTP 204: Event lock(s) deleted

HTTP 403: Access token is invalid or you do not have permission to delete this (these) lock(s)

HTTP 404: Event lock(s) not found

HTTP 500: Invalid user identifier or account does not exist anymore

Response fields:

Empty response

Statistics and more endpoints…

You can also request some data about your booking rate via our Statistics endpoint. For more details or other endpoints please read our PostMan doc. or contact our support team.

Conclusion

This covers the basics of using new Sagenda API. We’re constantly improving it and adding new features, so don’t forget to check up this page every once in a while. Meanwhile, you might want to get your hands wet with our ready-made templates at PostMan !