# Introduction

API Reference

The Harmonizely API is organized around [REST](http://en.wikipedia.org/wiki/Representational_State_Transfer). Our API has predictable resource-oriented URLs,  uses JSON format for request bodies, returns [JSON-encoded](http://www.json.org/) responses, and uses standard HTTP response codes, authentication, and verbs.

{% hint style="danger" %}
Access to the Harmonizely API can be requested from the [Integrations](https://harmonizely.com/integrations) page in your dashboard.
{% endhint %}

![](/files/-M8FyQxI7N8PQXnf10Bd)

#### Base URL

```bash
https://harmonizely.com/api
```

The Harmonizely API Docs demonstrate using curl to interact with the API over HTTP.

{% hint style="warning" %}
The Harmonizely API is still in beta, this documentation is a work in progress, feel free to send us your feedback at <support@harmonizely.com>.
{% endhint %}


# Authentication

The Harmonizely API uses API keys to authenticate requests. You can view your API key in the [Harmonizely Integrations](https://harmonizely.com/integrations).

API requests without authentication will fail.

Do not share your secret API keys in publicly accessible areas such as GitHub, client-side code, and so forth.

Add your API key to the `X-API-KEY` header to get the access to the API endpoints.

{% hint style="info" %}
To test requests using your account, replace the **\<your\_api\_key>** API key with your actual API key.
{% endhint %}

```bash
curl -H "X-API-KEY: <your_api_key>" https://harmonizely.com/api/users/me/meeting-types
```


# Pagination


# Errors


# Meeting Types

## List all user meeting types

<mark style="color:blue;">`GET`</mark> `https://harmonizely.com/api/users/me/meeting-types`

Returns a list of user meeting types. The meeting types are returned in sorted order, with the most recent meeting types appearing first.

#### Query Parameters

| Name    | Type   | Description                                                         |
| ------- | ------ | ------------------------------------------------------------------- |
| sorting | object | Sorting parameters, e.g. sorting\[created\_at]=desc                 |
| limit   | string | A limit on the number of objects to be returned. The default is 10. |
| page    | number | Page number. The default is 1.                                      |

#### Headers

| Name      | Type   | Description  |
| --------- | ------ | ------------ |
| X-API-KEY | string | Your API key |

{% tabs %}
{% tab title="200 A dictionary with a \_embedded property that contains items property that contains an array of up to limit meeting types." %}

```javascript
{
   "page":1,
   "limit":10,
   "pages":1,
   "total":1,
   "_embedded":{
      "items":[
         {
            "name":"15 min meeting",
            "description":"15 min meeting description",
            "duration":15,
            "slug":"15min",
            "uuid":"7ab22519-0135-2941-0bd6-a3381d173110"
         }
      ]
   },
   "_links":{
      "self":{
         "href":"/api/users/me/meeting-types?page=1&limit=10"
      },
      "first":{
         "href":"/api/users/me/meeting-types?page=1&limit=10"
      },
      "last":{
         "href":"/api/users/me/meeting-types?page=1&limit=10"
      }
   }
}
```

{% endtab %}
{% endtabs %}

### Examples

```bash
curl -H "X-API-KEY: <your_api_key>" https://harmonizely.com/api/users/me/meeting-types   
```


# Single-Use Links

Single-use links are used to create a meeting once which can't be used again. Once someone schedules a meeting with you, the link is no longer valid.

## Create a Single-Use Link

<mark style="color:green;">`POST`</mark> `https://harmonizely.com/api/single-use-link`

Create new single-use link based on the existing meeting type.

#### Headers

| Name         | Type   | Description      |
| ------------ | ------ | ---------------- |
| Content-Type | string | application/json |
| X-API-KEY    | string | Your API key.    |

#### Request Body

| Name                | Type   | Description                        |
| ------------------- | ------ | ---------------------------------- |
| meeting\_type\_uuid | string | UUID of the existing Meeting Type. |

{% tabs %}
{% tab title="200 Single-Use Link successfully created." %}

```javascript
{
   "code":"random-string",
   "url":"https://harmonizely.com/s/random-string"
}
```

{% endtab %}

{% tab title="422 Meeting Type could not be found." %}

```javascript
{
   "message":"Invalid arguments",
   "errors":{
      "meetingTypeUuid":[
         "Meeting Type with uuid 7ab22519-0135-2941-0bd6-a3381d173110 was not found."
      ]
   }
}
```

{% endtab %}
{% endtabs %}

### Examples

```bash
curl --location --request POST 'https://harmonizely.com/api/single-use-link' \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: YOUR_API_KEY' \
--data-raw '    {
      "meeting_type_uuid": "7ab22519-0135-2941-0bd6-a3381d173110"
    }'
```


# Webhooks

You can configure webhook endpoints via the API to be notified about events that happen in your Harmonizely account.

## Create a webhook

<mark style="color:green;">`POST`</mark> `https://harmonizely.com/api/webhooks`

Creates a new webhook object.

#### Headers

| Name         | Type   | Description      |
| ------------ | ------ | ---------------- |
| Content-Type | string | application/json |
| X-API-KEY    | string | Your API key     |

#### Request Body

| Name   | Type   | Description                                                                                                                                                |
| ------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| events | array  | <p>The list of events to enable for this endpoint.<br>Possible values:<br><code>\["meetingScheduled", "meetingCancelled", "meetingRescheduled"]</code></p> |
| secret | string | The endpoint's secret used to generate webhook signatures.                                                                                                 |
| url    | string | The webhook URL.                                                                                                                                           |

{% tabs %}
{% tab title="201 Webhook successfully created." %}

```javascript
{
    "events": [
        "meetingScheduled",
        "meetingCancelled",
        "meetingRescheduled"
    ],
    "url": "https://example.com/webhook",
    "secret": "something",
    "created_at": "2021-05-25T06:17:58+00:00",
    "uuid": "3e687c78-a8b8-4837-9333-57e3d807e61c"
}
```

{% endtab %}

{% tab title="422 Invalid arguments." %}

```javascript
{
    "message": "Invalid arguments",
    "errors": {
        "url": [
            "This value is not a valid URL."
        ]
    }
}
```

{% endtab %}
{% endtabs %}

## List all webhooks

<mark style="color:blue;">`GET`</mark> `https://harmonizely.com/api/webhooks`

Lists all webhooks.

#### Headers

| Name         | Type   | Description      |
| ------------ | ------ | ---------------- |
| Content-Type | string | application/json |
| X-API-KEY    | string | Your API key     |

{% tabs %}
{% tab title="200 Returns a list of all webhooks." %}

```javascript
{
    "page": 1,
    "limit": 10,
    "pages": 1,
    "total": 1,
    "_embedded": {
        "items": [
            {
                "events": [
                    "meetingRescheduled",
                    "meetingCancelled",
                    "meetingScheduled"
                ],
                "url": "https://example.com/webhook",
                "secret": null,
                "created_at": "2021-05-24T11:04:11+00:00",
                "uuid": "2ba9ee0b-e62a-43bd-aed0-31b26056ecdc"
            }
        ]
    },
    "_links": {
        "self": {
            "href": "/api/webhooks?page=1&limit=10"
        },
        "first": {
            "href": "/api/webhooks?page=1&limit=10"
        },
        "last": {
            "href": "/api/webhooks?page=1&limit=10"
        }
    }
}
```

{% endtab %}
{% endtabs %}

## Delete a webhook

<mark style="color:red;">`DELETE`</mark> `https://harmonizely.com/api/webhooks/:id`

Deletes a webhook.

#### Path Parameters

| Name | Type   | Description                              |
| ---- | ------ | ---------------------------------------- |
| id   | string | Unique identifier of the webhook (UUID4) |

#### Headers

| Name         | Type   | Description      |
| ------------ | ------ | ---------------- |
| Content-Type | string | application/json |
| X-API-KEY    | string | Your API key.    |

{% tabs %}
{% tab title="204 Webhook successfully deleted." %}

```
```

{% endtab %}

{% tab title="404 Webhook not found." %}

```javascript
{
    "code": 404,
    "message": "Not found."
}
```

{% endtab %}
{% endtabs %}


# Webhook

A representation of the webhook object

| Property     | Type   | Description                                                                                                                      |
| ------------ | ------ | -------------------------------------------------------------------------------------------------------------------------------- |
| `url`        | string | The URL of the webhook endpoint.                                                                                                 |
| `secret`     | string | The endpoint’s secret used to generate webhook signatures.                                                                       |
| `events`     | array  | The list of events to enable for this endpoint. Allowed values: `["meetingScheduled", "meetingCancelled", "meetingRescheduled"]` |
| `created_at` | string | The ISO-8601 time at which the object was created.                                                                               |
| `uuid`       | string | Unique identifier (UUID v4) of the object.                                                                                       |

## The example webhook object

```javascript
{
   "events":[
      "meetingRescheduled",
      "meetingCancelled",
      "meetingScheduled"
   ],
   "url":"https://example.com/webhook",
   "secret":null,
   "created_at":"2021-05-24T11:04:11+00:00",
   "uuid":"2ba9ee0b-e62a-43bd-aed0-31b26056ecdc"
}
```

## The example request that's being made when the meeting is scheduled

**Request Method:** POST

**Request headers:**

| **Header**          | Description                                                                                                                                                                                                                               |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `webhook-signature` | Harmonizely can optionally sign the webhook events it sends to your endpoints by including a signature in each event’s Webhook-Signature header. This allows you to verify that the events were sent by Harmonizely, not by a third party |
| `user-agent`        | The user agent. Always set to `Harmonizely`.                                                                                                                                                                                              |

**Request payload**:

```javascript
{
  "data": {
    "rescheduling": null,
    "pretty_canceled_at": null,
    "pretty_scheduled_at": "Wednesday, June 23, 2021 09:30",
    "pretty_scheduled_at_in_invitee_timezone": "Wednesday, June 23, 2021 at 9:30 AM",
    "pretty_canceled_at_in_invitee_timezone": null,
    "event_type": {
      "name": "Demo Call",
      "location": null,
      "location_label": null,
      "description": null,
      "duration": 15,
      "slug": "demo-call",
      "is_secret": false,
      "confirmation_page_type": "internal",
      "confirmation_page_url": null,
      "notification_type": "email",
      "pass_details_to_redirected_page": false,
      "type": "regular",
      "position": 0
    },
    "scheduled_at": "2021-06-23T07:30:00+00:00",
    "end_date": "2021-06-23T07:45:00+00:00",
    "invitee": {
      "first_name": "Bernice",
      "email": "bernice@example.com",
      "full_name": "Bernice J. Cervantez",
      "timezone": "Europe/Warsaw",
      "phone_number": "+48123456789",
      "locale": "en"
    },
    "state": "new",
    "canceled_at": null,
    "uuid": "601f15fb-c7e8-4988-863e-78a6ac4446df",
    "notes": null,
    "details": null,
    "answers": [
      {
        "question_label": "Details",
        "value": "My extra details",
        "question_type": "textarea"
      },
      {
        "question_label": "Agree to terms?",
        "value": 1,
        "question_type": "checkbox"
      }
    ],
    "location": "https://zoom.us/j/xxxxxx",
    "cancellation": null,
    "payment": null
  },
  "event": "meetingScheduled",
  "uuid": "ccc3d816-c44d-4a38-9eb1-e1c7d05538dc"
}
```

### Verifying signature manually

Harmonizely generates webhook signatures using a hash-based message authentication code ([HMAC](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code)) with [SHA-256](https://en.wikipedia.org/wiki/SHA-2) which is then base64 encoded.

1. **Determine the expected signature**

Compute an HMAC with the SHA256 hash function and encode it using base64. Use the webhook’s signing **secret** as the key, and use the **request's payload** string as the message.

Example in PHP:

```php
$signature = base64_encode(hash_hmac('sha256', $payload, $secret, true));
```

2\. **Compare the signatures**

Compare the signature in the `webhook-signature` header to the expected signature.


