---
title: "Configuring webhooks through the API"
description: "Declare, replace and remove a webhook receiving URL with the Ciklik API, and load the OpenAPI contract into your own tools."
url: https://www.ciklik.academy/en/webhooks/configurer-les-webhooks-par-lapi/
lang: en
lastUpdated: 2026-10-23
---

# Configuring webhooks through the API

> Box and PrestaShop
>
> This page applies to both box stores and PrestaShop stores.

> For developers
>
> This page describes the API that lets you declare, replace and remove a receiving URL programmatically, without going through the back office every time something changes. For the contract of the deliveries themselves (method, headers, timeouts, retries), see [Understanding a webhook delivery](https://www.ciklik.academy/en/webhooks/comprendre-un-envoi-de-webhook/).

## Authentication

The vendors API authenticates with a **Bearer** token. You create it yourself: **Settings > Sites**, click your site, then the **Create an API token** action. Give it a name that says what it is for, then copy the token shown: it will never be shown again. Your tokens are listed in the **API tokens** section of the site record. Every request must carry two headers:

```
Authorization: Bearer <token>
Accept: application/json
```

The `Accept: application/json` header is **required**. Without it, the server does not recognise the request as an API call: an authentication or validation error then comes back as an HTML redirect, not as a JSON response your code can interpret.

The API is limited to **200 requests per minute and per IP address**, not per token: if several integrations go out through the same network address (the same server, the same outbound proxy), they share this quota. Beyond that, the response is a 429 code whose body is not JSON.

On a PrestaShop site, a token is created automatically when the payment module is configured. For any other integration, create a dedicated token with the **Create an API token** action.

## Declaring a receiving URL

```
POST https://app.ciklik.co/api/v3/webhooks
```

| Field        | Type         | Required | Description                                                                   |
| ------------ | ------------ | -------- | ----------------------------------------------------------------------------- |
| `hook_url`   | string (URL) | Yes      | Receiving URL, syntactically valid                                            |
| `event_type` | string       | Yes      | Event key, see the [event catalogue](https://www.ciklik.academy/en/webhooks/) |

**cURL :**

```bash
curl -X POST https://app.ciklik.co/api/v3/webhooks \
  -H "Authorization: Bearer <token>" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"hook_url": "https://boutique.example.com/webhooks/ciklik", "event_type": "updated_subscription"}'
```

**200 response :**

```json
{
  "data": {
    "id": 1,
    "host": "boutique.example.com",
    "name": "Boutique Exemple",
    "paymentMethods": ["stripe"],
    "webhooks": {
      "updated_subscription": "https://boutique.example.com/webhooks/ciklik"
    },
    "metadata": null
  }
}
```

**422 error :**

```json
{
  "message": "The selected event type is invalid.",
  "errors": {
    "event_type": [
      "The selected event type is invalid."
    ]
  }
}
```

Three things to know before integrating:

- a second call on the same `event_type` **replaces** the previous URL, without warning;
- the new URL takes effect within **one minute at most**;
- `updated_change_choices` is **not accepted** by this endpoint: this key is not part of the validated list and returns a 422. Add it in the **Webhooks** field of your site’s **Advanced** tab.

> Validation does not test your URL
>
> The check only covers the syntax of `hook_url`. An `http://` URL is accepted, and so is an unreachable one: no test call is made when the URL is declared. Use HTTPS, and check on your side that the address responds.

## Removing a receiving URL

```
DELETE https://app.ciklik.co/api/v3/webhooks
```

```bash
curl -X DELETE https://app.ciklik.co/api/v3/webhooks \
  -H "Authorization: Bearer <token>" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"event_type": "updated_subscription"}'
```

The response has the same shape as for a declaration: the full `webhooks` object, without the key you just removed.

## Knowing which URLs are declared

The `POST` and `DELETE` responses already carry the full `webhooks` object: this is the reliable way to know the state of your configuration after each call. The same content is shown in the **Webhooks** field of your site’s **Advanced** tab. To read the configuration without changing it, call `GET /whoiam`: the response contains the same object, in `data.webhooks`. The delivery history is available in the back-office menu **Settings > Advanced > Webhooks**.

## Response codes

| Code | Meaning                                           | What to do                                               |
| ---- | ------------------------------------------------- | -------------------------------------------------------- |
| 200  | Request processed                                 | -                                                        |
| 401  | Authentication required: token missing or invalid | Check the `Authorization` header                         |
| 422  | Invalid parameter or unknown event key            | Check `hook_url` and `event_type`                        |
| 429  | Per-IP quota exceeded (plain-text body, no JSON)  | Space out your calls, stay under 200 requests per minute |

## The OpenAPI contract

The [`/openapi/ciklik-webhooks.yaml`](https://www.ciklik.academy/openapi/ciklik-webhooks.yaml) file formally describes the whole system: the 18 event keys under `webhooks`, the three configuration operations described on this page, every object schema used in the payloads, and one complete real example per event key.

Three practical uses:

- load it into an API client (Postman, Insomnia, Bruno) to get the requests ready immediately;
- generate types (TypeScript, PHP) from the contract instead of writing them by hand;
- hand it to a coding assistant so it writes your receiving endpoint directly from the schemas and examples.

> Best practice
>
> Start from the OpenAPI file rather than copying the tables of this section by hand: it is the version that stays in sync with the code.

## See also

[Understanding a webhook delivery](https://www.ciklik.academy/en/webhooks/comprendre-un-envoi-de-webhook/)

[Best practices and troubleshooting](https://www.ciklik.academy/en/webhooks/bonnes-pratiques-et-depannage/)

[Activating and testing a webhook](https://www.ciklik.academy/en/webhooks/activer-et-tester-un-webhook/)
