API Overview
Welcome to the GReminders API.
GReminders API is currently in BETA. We have developed some API endpoints and Webhooks functionality. We are looking to work with customers who have special use cases they want to enable.
For access or details please contact [email protected]
Webhooks Overview
Webhooks allow developers to trigger actions off things that happen in GReminders. Webhooks are triggered for New Bookings, Reschedules, Cancellations and Event Confirmations. This guide introduces how webhooks work, including how to configure a webhook for your app and manage webhooks.
Any breaking changes made to the API will result in a new version of the Webhook API. Currently we are on version 1.
Concepts
Webhook: A single event message. GReminders sends a webhook to an Webhook receiving endpoint URL. A webhook contains a JSON payload in the body, and metadata in the headers.
object_type: type of the object that triggers an webhook event. Could be event, event_type and user
change_type: This reflects the type of callback you're receiving. Could be created, updated or deleted. Also, you may encounter url_verification during the configuration process.
Webhook subscription: A persisted data object, which defines the object_type and the change_type that the app wants to receive.
A webhook receiving endpoint URL is where GReminders sends webhooks for the specified object_type and change_type.
Payload
Webhook payload structure:
{
"object_type": "event",
"change_type": "created"
"data": {
...
}
}
Each webhook sent by GReminders has the same structure
Parameter | Description |
---|---|
object_type string |
Type of the object that triggers an webhook event |
change_type string |
Change Type of callback (created, updated, etc...) |
data one of Api Object |
data representing object |
Headers
In addition to the message payload, each webhook message has a predefined set of HTTP headers containing metadata.
HTTP Header | Use |
---|---|
X-Greminders-Api-Version | Version of the Webhook API |
X-Greminders-Request-Timestamp | UNIX Timestamp of the request |
X-Greminders-Signature | Used for verification of the request |
X-Greminders-Retry-Num | Indicates the delivery retry attempt number: 1, 2, or 3. |
X-Greminders-Retry-Reason | Describes why the request was retried |
Delivery Retries
GReminders will try to deliver a failed request up to 3 times in a gradually increasing timetable.
We'll tell you why we're retrying the request in the X-Greminders-Retry-Reason
HTTP header. Possible values are:
- http_timeout - Your server took longer than 3 seconds to respond to the previous webhook delivery attempt.
- too_many_redirects - If we encounter more than 5 redirects, we'll retry the request in hopes it won't be that many this time.
- connection_failed - Couldn't to connect to your server.
- http_error - We encountered an HTTP status code that was not in the HTTP 200 OK range.
- unknown_error - For some reason it didn't work and we don't know why.
Working with Webhooks
Webhook Subscription
To create webhook subscription follow next steps:
- Navigate to your GRemidners account and go to Org Settings > API. Click on the Webhooks Tab.
- Enable Webhooks
- create a New Webhook
- provide webhook Name, Receiving Endpoint URL, check desired Event Hooks and enable webhook by hitting Active toggle
- Save your webhook
- Copy your Signing Secret (to be used later, optional)
Verification of Receiving Endpoint URL
We'll dispatch a HTTP POST containing following body to your request URL:
{
"change_type": "url_verification",
"verification_key": "85cfdbc3dab3d0124aad1158b90b9fa745a1a00a4d15eea85f7d8db2ffc81400"
}
To ensure that webhooks are being delivered to a server under your control, GReminders must verify your ownership by sending you a url_verification request. You'll automatically receive url_verification request whenever configuring an Webhook Receiving Endpoint URL.
Once you receive the url_verification request, verify it and then respond in plaintext with the verification_key attribute value:
HTTP 200 OK
85cfdbc3dab3d0124aad1158b90b9fa745a1a00a4d15eea85f7d8db2ffc81400
Receive the Webhook
After you register an endpoint, GReminders sends an HTTP POST request to the URL specified every time that event occurs. The HTTP POST request's parameters contain the JSON data relevant to the event that triggered the request.
Verify the Webhook (Optional)
The following example uses pseudocode to verify a webhook request
function verifyRequest(): bool {
$request = getRequest();
$signing_secret = 'your signing sexret generated by GReminders';
$requestSignature = $request->headers('X-Greminders-Signature');
$timestamp = $request->headers('X-Greminders-Request-Timestamp');
$payload = $request->getBody();
$calculatedSignature = $hash_hmac('sha256', "$timestamp:$body", $signing_secret);
return $requestSignature === $calculatedSignature;
}
app.MapPost("/webhook",async delegate(HttpContext context) {
using (StreamReader reader = new StreamReader(context.Request.Body, Encoding.UTF8))
{
var signature = context.Request.Headers["X-Greminders-Signature"];
var timestamp = context.Request.Headers["X-Greminders-Request-Timestamp"];
var signingSecret = "4d7df8f838cffac21219a7b74a77c3c2a6f1927c341c1b0d800296f5b772565a";
var body = await reader.ReadToEndAsync();
var hmacSha256 = new HMACSHA256(Encoding.UTF8.GetBytes(signingSecret));
var hash = hmacSha256.ComputeHash(Encoding.UTF8.GetBytes($"{timestamp}:{body}"));
var controlSignature = Convert.ToHexString(hash).ToLower();
if (signature == controlSignature)
{
Console.WriteLine("verified");
}
else
{
Console.WriteLine("not verified");
}
}
});
Before you respond to a webhook, you need to verify that the webhook was sent from GReminders. You can verify the webhook by calculating a digital signature and comparing it to the value of the X-Greminders-Signature HTTP header.
Respond to the webhook
Your webhook acknowledges that it received data by sending a 200 OK response.
API Objects
Event
Example:
{
"id": "2142ba19-64a3-4109-9e60-64f47d9bcb49",
"external_id": "26jkvg7t3sp1ugmkd72tih91hk",
"user_id": "d287cc96-ff37-4c47-b703-5309a7171ea1",
"calendar_id": "87e5e15e-cdc8-467e-a256-ae6aada02a54",
"event_type_id": "6474fc7c-2023-48c7-9d35-52451a34cacf",
"url": "https://app.greminders.com/event/2142ba19-64a3-4109-9e60-64f47d9bcb49",
"weburl": "https://www.google.com/calendar/event?eid=MjZqa3ZnN3Qzc3AxdWdta2Q3MnRpaDkxaGsgbG9wYXRpbnNreXN2LnNkYWlAbQ",
"reschedule_url": "https://www.greminders.com/r/TDL7xW",
"cancel_url": "https://www.greminders.com/c/TDL7xW",
"location": "https://meet.google.com/utd-yois-fsp",
"body": "Review Value Proposition of ACME",
"name": "Demo Meeting with ACME Inc",
"status": "confirmed",
"freebusy": "busy",
"provider": "google",
"timezone": "America/Los_Angeles",
"categories": [],
"origination_date": "2022-07-07T02:16:35-07:00",
"start_date": "2022-07-07T23:30:00-07:00",
"end_date": "2022-07-08T00:00:00-07:00",
"created_date": "2022-07-07T02:16:35-07:00",
"updated_date": "2022-07-07T09:16:57+00:00",
"is_organizer": true,
"reply_status": null,
"all_day_event": false,
"client_timezone": "America/Los_Angeles",
"meeting_urls": [
{
"url": "https://meet.google.com/utd-yois-fsp",
"provider": "google_meet"
}
],
"organizer": {
"role": "organizer",
"email": "[email protected]",
"phone": null,
"status": "registered",
"internal": true,
"timezone": "America/Los_Angeles",
"last_name": "Person",
"questions": [],
"cancel_url": "https://www.greminders.com/c/BgIzRz",
"first_name": "Some",
"confirm_url": "https://www.greminders.com/f/BgIzRz",
"created_date": "2022-07-07T02:49:06-07:00",
"source_email": null,
"source_phone": "user",
"updated_date": "2022-07-07T02:49:06-07:00",
"external_role": "sender",
"reschedule_url": "https://www.greminders.com/r/BgIzRz"
},
"registrants": [
{
"role": "participant",
"email": "[email protected]",
"phone": null,
"status": "registered",
"internal": false,
"timezone": "America/Los_Angeles",
"last_name": "Person",
"questions": [
{
"key": "f52105e8-94dd-4c11-9666-b1a42e72970d",
"label": "sample question",
"value": "sample answer"
}
],
"cancel_url": "https://www.greminders.com/c/BgIzRz",
"first_name": "Another",
"confirm_url": "https://www.greminders.com/f/BgIzRz",
"created_date": "2022-07-07T02:49:06-07:00",
"source_email": "eventregistration",
"source_phone": null,
"updated_date": "2022-07-07T02:50:21-07:00",
"external_role": "recipient",
"reschedule_url": "https://www.greminders.com/r/BgIzRz"
}
],
"participants": [
{
"role": "participant",
"email": "[email protected]",
"phone": null,
"status": "registered",
"internal": false,
"timezone": "America/Los_Angeles",
"last_name": "Person",
"questions": [],
"cancel_url": "https://www.greminders.com/c/BgIzRz",
"first_name": "Another",
"confirm_url": "https://www.greminders.com/f/BgIzRz",
"created_date": "2022-07-07T02:49:06-07:00",
"source_email": "eventregistration",
"source_phone": null,
"updated_date": "2022-07-07T02:50:21-07:00",
"external_role": "recipient",
"reschedule_url": "https://www.greminders.com/r/BgIzRz"
},
{
"role": "organizer",
"email": "[email protected]",
"phone": null,
"status": "registered",
"internal": true,
"timezone": "America/Los_Angeles",
"last_name": "Person",
"questions": [],
"cancel_url": "https://www.greminders.com/c/BgIzRz",
"first_name": "Some",
"confirm_url": "https://www.greminders.com/f/BgIzRz",
"created_date": "2022-07-07T02:49:06-07:00",
"source_email": null,
"source_phone": "user",
"updated_date": "2022-07-07T02:49:06-07:00",
"external_role": "sender",
"reschedule_url": "https://www.greminders.com/r/BgIzRz"
}
],
}
Parameter | Description |
---|---|
id uuid |
Internal ID |
external_id string |
ID of the External Event (from Google, Microsoft, etc...) Could be used to match up the Event against the Source Provider. |
user_id uuid |
Internal User ID |
calendar_id uuid |
Internal Calendar ID |
event_type_id uuid |
Internal Event Type ID |
url string |
GReminders Web UI URL |
weburl string |
External Event Provider URL (Link to the Google, Microsoft, etc... Event) |
reschedule_url string |
Public URL to be used for client rescheduling |
cancel_url string |
Public URL to be used for client cancellations |
location string |
Location of the Event |
body string |
Description of the Event |
name string |
Title/Subject of the Event |
status string |
Status of the Source Event (confirmed, tentative, cancelled) If event is "cancelled" it has been deleted from the source calendar |
freebusy string |
"free" or "busy", if busy the event is not considered as part of the availability check |
provider string |
Source Provider of the Event (google, microsoft, etc...) |
timezone string |
Time Zone of Event in IANA Time Zone format |
client_timezone string |
Client Time Zone of Event in IANA Time Zone format See Article |
reply_status string |
Internal Reply State (confirmed,rescheduling,optout,cancelled) GReminders Event Status. Result of client replies to notifications. |
is_organizer bool |
This user is the Organizer of this Meeting |
all_day_event bool |
This event is an all day event |
categories array |
Categories of this Event from Source Event/Calendar (only applies to Office 365 / Exchange Calendar Events) |
origination_date date |
Original Date the Event was created on the Source Calendar, ISO8601 format |
start_date date |
Start Date & Time of the Event, ISO8601 format |
end_date date |
End Date & Time of the Event, ISO8601 format |
created_date date |
Date & Time Event was created in GReminders, ISO8601 format |
updated_date date |
Date & Time Event was last updated in GReminders, ISO8601 format |
meeting_urls array of Meeting Url |
|
organizer Registrant |
Organizer of the Meeting |
participants array of Registrant |
List of People that are ON the Event Invitation List. |
registrants Registrant |
List of People who Registered for the Event via GReminders. In most cases this is one registrant, for Group Events this may contain more than one registrant. |
Event type
Example:
{
"id": "6474fc7c-2023-48c7-9d35-52451a34cacf",
"url": "https://app.greminders.com/c/someperson/demomeeting",
"name": "Demo Meeting",
"type": "single",
"active": true,
"team_id": null,
"user_id": "d287cc96-ff37-4c47-b703-5309a7171ea1",
"location": "",
"shortname": "demomeeting",
"show_home": true,
"calendar_id": null,
"description": "",
"availability": {
"advanced_availability": false,
"default_availability_end": "17:00:00",
"default_availability_start": "09:00:00",
"availability_observe_holidays": true
},
"created_date": "2022-07-07T08:56:22+00:00",
"updated_date": "2022-07-07T08:56:22+00:00",
"location_type": "google_meet",
"event_duration_max": null,
"event_duration_min": null,
"event_duration_type": "fixed",
"max_events_per_slot": null,
"can_schedule_from_date": null,
"can_schedule_until_date": null,
"can_schedule_within_days": 60,
"event_duration_in_minutes": 30,
"prevent_events_scheduled_hours": 2,
"add_customer_to_calendar_invite": true
}
Parameter | Description |
---|---|
id uuid |
Internal ID |
active bool |
Active Flag |
user_id uuid |
Internal User ID |
team_id uuid |
Internal Team ID |
url string |
Public Scheduling Link for this Event Type |
shortname string |
Shortname of the User or Team (used in the url above) |
type string |
|
calendar_id uuid |
Internal Calendar ID the Event will be booked on (if NULL then the Primary Calendar is used) |
name string |
Title of the Event Type |
description string |
Description of the Event Type |
location string |
Location of the Event Type |
location_type string |
If Location is "custom" this is the location of the Event Type |
event_duration_in_minutes int |
Event Type Duration in Minutes |
can_schedule_within_days int |
Event can be scheduled within X Days |
prevent_events_scheduled_hours int |
Prevent Events being scheduled less than X hours from now |
show_home bool |
Will the Event Type show on the main Booking Screen |
event_duration_type string |
Event Type Duration Type (fixed, variable) |
event_duration_min int |
if Event Type Duration Type = fixed, this is the min time duration for the event in minutes |
event_duration_max int |
if Event Type Duration Type = fixed, this is the max time duration for the event in minutes |
max_events_per_slot int |
Max # of Events per Time Slot (Overlapping Bookings), default null |
can_schedule_from_date date |
Can schedule between this Start Date, ISO8601 format |
can_schedule_until_date date |
Can schedule between this End Date, ISO8601 format |
add_customer_to_calendar_invite bool |
Are we adding the client to the participant list (onto the Event Invitation) |
availability Availability |
Availability Settings of the Event Type |
created_date date |
Date & Time Event Type was originally created, ISO8601 format |
updated_date date |
Date & Time Event Type was last modified, ISO8601 format |
User
Example:
{
"id": "d287cc96-ff37-4c47-b703-5309a7171ea1",
"url": "https://app.greminders.com/c/someperson",
"email": "[email protected]",
"title": "",
"active": true,
"language": "en",
"timezone": "America/Los_Angeles",
"shortname": "someperson",
"country_code": "US",
"created_date": "2022-06-13T10:58:45-07:00",
"mobile_phone": "19495556666",
"updated_date": "2022-07-07T09:05:23+00:00",
"email_verified": false
}
Parameter | Description |
---|---|
"id" uuid | Internal ID |
"url" string | Public Scheduling Link for this User |
"email" string | |
"title" string | Job Title |
"active" bool | Is user Active? |
"language" string | Default Language |
"timezone" string | Time Zone of User in IANA Time Zone format |
"shortname" string | Shortname for User |
"country_code" string | ISO 3166-1 2 character Country Code |
"created_date" date | Date & Time User was originally created, ISO8601 format |
"mobile_phone" string | Mobile Number in E.164 format |
"updated_date" date | Date & Time User was last modified, ISO8601 format |
"email_verified" bool | Has this email address been verified? |
Registrant
Example:
{
"first_name": "Some",
"last_name": "Person",
"email": "[email protected]",
"phone": null,
"role": "organizer",
"external_role": "required",
"status": "registered",
"internal": true,
"timezone": "America/Los_Angeles",
"confirm_url": "https://www.greminders.com/f/TDL7xW",
"reschedule_url": "https://www.greminders.com/r/TDL7xW",
"cancel_url": "https://www.greminders.com/c/TDL7xW",
"questions": [
{
"key": "f52105e8-94dd-4c11-9666-b1a42e72970d",
"label": "sample question",
"value": "sample answer"
}
],
"source_email": "eventregistration",
"source_phone": "user",
"created_date": "2022-07-07T02:16:39-07:00",
"updated_date": "2022-07-07T02:16:39-07:00",
}
Parameter | Description |
---|---|
first_name string |
First Name |
last_name string |
Last Name |
email string |
|
phone string |
Phone Number in E.164 Format |
role string |
Internal Role (organizer |
external_role string |
Role as defined by the External Calendar Event (sender,recipient,required,optional) |
status string |
Internal Status (registered,pending,confirmed,cancelled) |
internal bool |
Is this an Internal User (GReminders calculated) |
timezone string |
Time Zone of Registrant in IANA Time Zone format |
confirm_url string |
Public Confirmation URL |
reschedule_url string |
Public Reschedule URL |
cancel_url string |
Cancellation URL |
questions array of Question |
Custom Questions/Answers |
source_email string |
Source of the Email (where the email address was first found) |
source_phone string |
Source of the Phone Number (where the phone number was first found) |
created_date date |
Date & Time User was created, ISO8601 format |
updated_date date |
Date & Time User was last modified, ISO8601 format |
Meeting Url
Example:
{
"provider": "google_meet",
"url": "http://meetingurl"
}
Parameter | Description |
---|---|
provider string |
Provider Name (zoom, google_meet, etc...) |
url string |
URL of the Web Meeting |
Availability
Example:
{
"advanced_availability": false,
"default_availability_start": "09:00:00",
"default_availability_end": "17:00:00",
"availability_observe_holidays": true
}
Parameter | Description |
---|---|
advanced_availability bool |
Is advanced availability enabled? |
default_availability_start time |
Availability Start Time |
default_availability_end time |
Availability End Time |
availability_observe_holidays bool |
Does Event Type observer Holidays |
Question
Example:
{
"key": "f52105e8-94dd-4c11-9666-b1a42e72970d",
"label": "What is your favorite Color?",
"value": "Green"
}
Parameter | Description |
---|---|
key string |
Question Key |
label string |
Question Label, the actual Question |
value string |
The Registrants Answer |