NAV Navbar
shell

Introduction

Welcome to the Cronhooks API! You can use our API to access Cronhooks API endpoints, which can get information on your scheduled webhooks.

Schedules

Schedule a new webhook

  curl https://api.cronhooks.io/schedules /
  -X POST \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <YOUR_API_TOKEN>' \
  -d \
  '{
     "group": 0 | group id : int | group name : string,
     "title": "Send email to inactive users",
     "description": "Send an email to users who are inactive for more than 60 days and offer a discount for upgrading subscriptions.",
     "url": "https://example.com/webhooks/inactive-email",
     "timezone": "asia/karachi",
     "method": "POST",
     "headers": {
       "additionalProp1": "string",
       "additionalProp2": "string",
       "additionalProp3": "string"
     },
     "payload": {
       "additionalProp1": "string",
       "additionalProp2": "string",
       "additionalProp3": "string"
     },
     "contentType": "application/json; charset=utf-8",
     "isRecurring": false,
     "cronExpression": "",
     "runAt": "2019-02-01T12:48:26.983Z",
     "sendCronhookObject": true
  }'

The above command returns JSON structured like this:

{
   "success": true,
   "error": null,
   "result":
    {
      "id": 1,
      "groupId": 1,
      "title": "Send email to inactive users",
      "description": "Send an email to users who are inactive for more than 60 days and offer a discount for upgrading subscriptions.",
      "url": "https://example.com/webhooks/inactive-email",
      "timezone": "asia/karachi",
      "method": "POST",
      "headers": {
        "additionalProp1": "string",
        "additionalProp2": "string",
        "additionalProp3": "string"
      },
      "payload": "{
          \"additionalProp1\": \"string\",
          \"additionalProp2\": \"string\",
          \"additionalProp3\": \"string\"
      }",
      "contentType": "application/json; charset=utf-8",
      "status": "scheduled",
      "errorMessage": "",
      "isRecurring": false,
      "cronExpression": "",
      "runAt": "2019-02-01T12:48:26.983Z",
      "sendCronhookObject": true,
      "creationTime": "2019-02-01T09:35:27.568Z",
      "lastModificationTime": "2019-02-01T09:35:27.568Z"
    }
}

This endpoint creates a new scheduled webhook.

HTTP Request

POST https://api.cronhooks.io/schedules

Parameters

Parameter Required Description
group Optional provide group's cronhooks id or group name.
title Required title of webhook schedule.
url Required webhook url.
timezone Required IANA Timezone
method Required Http METHOD
headers Optional {} Object
payload Optional {} Object or "" String
contentType Required Content Type for recieving webhook
isRecurring Required Trigger webhook repeatedly or not
runAt Required (if isRecurring false) Webhook will be triggered at given DateTime
sendCronhookObject Required Send Cronhook schedule object along with provided payload
cronExpression Required (if isRecurring true) Valid cron expression for recurring schedules

List Schedules

curl "https://api.cronhooks.io/schedules?skip=0&limit=10"
  -H "Authorization: Bearer <YOUR_API_KEY>"

The above command returns JSON structured like this:

{
  "success": true,
  "error": null,
  "result":
  {
    "totalCount": 0,
    "items": [
      {
        "id": 1,
        "groupId": 1,
        "title": "Send email to inactive users",
        "description": "Send an email to users who are inactive for more than 60 days and offer a discount for upgrading    subscriptions.",
        "url": "https://example.com/webhooks/inactive-email",
        "timezone": "asia/karachi",
        "method": "POST",
        "headers": {
          "additionalProp1": "string",
          "additionalProp2": "string",
          "additionalProp3": "string"
        },
        "payload": "{
          \"additionalProp1\": \"string\",
          \"additionalProp2\": \"string\",
          \"additionalProp3\": \"string\"
        }",
        "contentType": "application/json; charset=utf-8",
        "status": "scheduled",
        "errorMessage": "",
        "isRecurring": false,
        "cronExpression": "",
        "runAt": "2019-02-01T12:48:26.983Z",
        "sendCronhookObject": true,
        "creationTime": "2019-02-01T09:35:27.568Z",
        "lastModificationTime": "2019-02-01T09:35:27.568Z"
      }
    ]
  }
}

This endpoint retrieves all scheduled webhooks.

HTTP Request

GET https://api.cronhooks.io/schedules?skip=0&limit=10

Query Parameters

Parameter Required Description
skip Required Number of records to skip.
limit Required Number of records to return in response.

Retrieve a Scheduled Webhook

curl "https://api.cronhooks.io/schedules/1"
  -H "Authorization: Bearer <YOUR_API_TOKEN>"

The above command returns JSON structured like this:

{
  "success": true,
  "error": null,
  "result":
  {
    "id": 1,
    "groupId": 1,
    "title": "Send email to inactive users",
    "description": "Send an email to users who are inactive for more than 60 days and offer a discount for upgrading subscriptions.",
    "url": "https://example.com/webhooks/inactive-email",
    "timezone": "asia/karachi",
    "method": "POST",
    "headers": {
      "additionalProp1": "string",
      "additionalProp2": "string",
      "additionalProp3": "string"
    },
    "payload": "{
        \"additionalProp1\": \"string\",
        \"additionalProp2\": \"string\",
        \"additionalProp3\": \"string\"
    }",
    "contentType": "application/json; charset=utf-8",
    "status": "scheduled",
    "errorMessage": "",
    "isRecurring": false,
    "cronExpression": "",
    "runAt": "2019-02-01T12:48:26.983Z",
    "sendCronhookObject": true,
    "creationTime": "2019-02-01T09:35:27.568Z",
    "lastModificationTime": "2019-02-01T09:35:27.568Z"
  }
}

This endpoint retrieves a specific schedule.

HTTP Request

GET https://api.cronhooks.io/schedules/{id}

URL Parameters

Parameter Required Description
id Required The ID of the schedule to retrieve

Update Scheduled Webhook

curl "https://api.cronhooks.io/schedules/2"
  -X PUT \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <YOUR_API_TOKEN>' \
  -d \
  '{
     "group": 0 | gorup id : int | group name : string,
     "title": "Send email to inactive users",
     "description": "Send an email to users who are inactive for more than 60 days and offer a discount for upgrading subscriptions.",
     "url": "https://example.com/webhooks/inactive-email",
     "timezone": "asia/karachi",
     "method": "POST",
     "headers": {
       "additionalProp1": "string"
     },
     "payload": {
       "additionalProp1": "string",
       "additionalProp2": "string",
       "additionalProp3": "string",
       "additionalProp4": "string"
     },
     "contentType": "application/json; charset=utf-8",
     "isRecurring": true,
     "cronExpression": "*/5 * * * *",
     "sendCronhookObject": true,
  }'

The above command returns JSON structured like this:

{
  "success": true,
  "error": null,
  "result":
  {
     "id": 2,
     "groupId": 1,
     "title": "Send email to inactive users",
     "description": "Send an email to users who are inactive for more than 60 days and offer a discount for upgrading subscriptions.",
     "url": "https://example.com/webhooks/inactive-email",
     "timezone": "asia/karachi",
     "method": "POST",
     "headers": {
       "additionalProp1": "string"
     },
     "payload": "{
        \"additionalProp1\": \"string\",
        \"additionalProp2\": \"string\",
        \"additionalProp3\": \"string\"
      }",
     "contentType": "application/json; charset=utf-8",
     "isRecurring": true,
     "cronExpression": "*/5 * * * *",
     "nextRunAt": "2019-02-01T12:48:26.983Z",
     "sendCronhookObject": true,
     "creationTime": "2019-02-01T09:35:27.568Z",
     "lastModificationTime": "2019-02-01T09:35:27.568Z"
  }
}

This endpoint updates a scheduled webhook.

HTTP Request

PUT https://api.cronhooks.io/schedules/{id}

Parameters

Parameter Required Description
group Optional provide group's cronhooks id or group name.
id Required id of updated schedule.
title Required title of webhook schedule.
url Required webhook url.
timezone Required IANA Timezone
method Required Http METHOD
headers Optional {} Object
payload Optional {} Object or "" String
contentType Required Content Type for recieving webhook
isRecurring Required Trigger webhook repeatedly or not
runAt Required (if isRecurring false) Webhook will be triggered at given DateTime
cronExpression Required (if isRecurring true) Valid cron expression for recurring schedules
sendCronhookObject Required Send Cronhook schedule object along with provided payload

Trigger Webhook

curl "https://api.cronhooks.io/schedules/2/trigger"
  -X POST
  -H "Authorization: Bearer <YOUR_API_TOKEN>"

The above command returns JSON structured like this:

{
  "success" : true,
  "error": null,
}

This endpoint triggers a specific webhook immediately. It does not affect the schedule.

HTTP Request

POST https://api.cronhooks.io/schedules/{id}/trigger

URL Parameters

Parameter Required Description
id Required The ID of the schedule to trigger

Pause Schedule

curl "https://api.cronhooks.io/schedules/2/pause"
  -X POST
  -H "Authorization: Bearer <YOUR_API_TOKEN>"

The above command returns JSON structured like this:

{
  "success" : true,
  "error": null,
}

This endpoint pause's given schedule.

HTTP Request

POST https://api.cronhooks.io/schedules/{id}/pause

URL Parameters

Parameter Required Description
id Required The ID of the schedule

Resume Schedule

curl "https://api.cronhooks.io/schedules/2/resume"
  -X POST
  -H "Authorization: Bearer <YOUR_API_TOKEN>"

The above command returns JSON structured like this:

{
  "success" : true,
  "error": null,
}

This endpoint resume's given schedule.

HTTP Request

POST https://api.cronhooks.io/schedules/{id}/resume

URL Parameters

Parameter Required Description
id Required The ID of the schedule

Delete Scheduled Webhook

curl "https://api.cronhooks.io/schedules/2"
  -X DELETE
  -H "Authorization: Bearer <YOUR_API_TOKEN>"

The above command returns JSON structured like this:

{
  "success" : true,
  "error": null,
}

This endpoint deletes a specific schedule.

HTTP Request

DELETE https://api.cronhooks.io/schedules/{id}

URL Parameters

Parameter Required Description
id Required The ID of the schedule to delete

Groups

List Groups

curl "https://api.cronhooks.io/groups?skip=0&limit=10"
  -H "Authorization: Bearer <YOUR_API_KEY>"

The above command returns JSON structured like this:

{
  "success": true,
  "error": null,
  "result":
  {
    "totalCount": 2,
    "items": [
      {
        "id": 1,
        "name": "Group #1",
        "creationTime": "2019-02-01T09:35:27.568Z",
        "lastModificationTime": "2019-02-01T09:35:27.568Z"
      },
      {
        "id": 2,
        "name": "Group #2",
        "creationTime": "2019-02-01T09:35:27.568Z",
        "lastModificationTime": "2019-02-01T09:35:27.568Z"
      }
    ]
  }
}

This endpoint retrieves all groups.

HTTP Request

GET https://api.cronhooks.io/groups?skip=0&limit=10

Query Parameters

Parameter Required Description
skip Required Number of records to skip.
limit Required Number of records to return in response.

Retrieve Group by Id

curl "https://api.cronhooks.io/groups/1"
  -H "Authorization: Bearer <YOUR_API_TOKEN>"

The above command returns JSON structured like this:

{
  "success": true,
  "error": null,
  "result":
  {
    "id": 1,
    "name": "Group #1",
    "creationTime": "2019-02-01T09:35:27.568Z",
    "lastModificationTime": "2019-02-01T09:35:27.568Z"
  }
}

This endpoint retrieves a specific group.

HTTP Request

GET https://api.cronhooks.io/groups/{id}

URL Parameters

Parameter Required Description
id Required Group Id

Retrieve Group by Name

curl "https://api.cronhooks.io/groups/getByName?name=Group%20%231"
  -H "Authorization: Bearer <YOUR_API_TOKEN>"

The above command returns JSON structured like this:

{
  "success": true,
  "error": null,
  "result":
  {
    "id": 1,
    "name": "Group #1",
    "creationTime": "2019-02-01T09:35:27.568Z",
    "lastModificationTime": "2019-02-01T09:35:27.568Z"
  }
}

This endpoint retrieves a specific group by name.

HTTP Request

GET https://api.cronhooks.io/groups/getByName?name=Group%20%231

URL Parameters

Parameter Required Description
name Required The url encoded (encodeURIComponent) group name

Create Group

curl "https://api.cronhooks.io/groups"
  -X POST \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <YOUR_API_TOKEN>' \
  -d \
  '{
     "name": "Group #1"  
   }'

The above command returns JSON structured like this:

{
  "success": true,
  "error": null,
  "result":
  {
     "id": 1,
     "name": "Group #1",
     "creationTime": "2019-02-01T09:35:27.568Z",
     "lastModificationTime": "2019-02-01T09:35:27.568Z"
  }
}

This endpoint creates a group.

HTTP Request

POST https://api.cronhooks.io/groups

Parameters

Parameter Required Description
name Required group name.

Update Group

curl "https://api.cronhooks.io/groups/2"
  -X PUT \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <YOUR_API_TOKEN>' \
  -d \
  '{
     "name": "Group #2"  
   }'

The above command returns JSON structured like this:

{
  "success": true,
  "error": null,
  "result":
  {
     "id": 2,
     "name": "Group #2",
     "creationTime": "2019-02-01T09:35:27.568Z",
     "lastModificationTime": "2019-02-01T09:35:27.568Z"
  }
}

This endpoint updates a group.

HTTP Request

PUT https://api.cronhooks.io/groups/{id}

Parameters

Parameter Required Description
id Required group id.
name Required group name.

Delete Group

curl "https://api.cronhooks.io/groups/2"
  -X DELETE
  -H "Authorization: Bearer <YOUR_API_TOKEN>"

The above command returns JSON structured like this:

{
  "success" : true,
  "error": null,
}

This endpoint deletes a specific schedule.

HTTP Request

DELETE https://api.cronhooks.io/groups/{id}

URL Parameters

Parameter Required Description
id Required The ID of the schedule to delete

List Group Schedules

curl "https://api.cronhooks.io/groups/{groupId}/schedules?skip=0&limit=10"
  -H "Authorization: Bearer <YOUR_API_KEY>"

The above command returns JSON structured like this:

{
  "success": true,
  "error": null,
  "result":
  {
    "totalCount": 2,
    "items": [
      {
        "id": 2,
        "groupId": 1,
        "title": "Send email to inactive users",
        "description": "Send an email to users who are inactive for more than 60 days and offer a discount for upgrading subscriptions.",
        "url": "https://example.com/webhooks/inactive-email",
        "timezone": "asia/karachi",
        "method": "POST",
        "headers": {
          "additionalProp1": "string"
        },
        "payload": "{}",
        "contentType": "application/json; charset=utf-8",
        "isRecurring": true,
        "cronExpression": "*/5 * * * *",
        "nextRunAt": "2019-02-01T12:48:26.983Z",
        "sendCronhookObject": true,
        "creationTime": "2019-02-01T09:35:27.568Z",
        "lastModificationTime": "2019-02-01T09:35:27.568Z"
      }
    ]
  }
}

This endpoint retrieves all schedules for a given group.

HTTP Request

GET https://api.cronhooks.io/groups/{groupId}/schedules?skip=0&limit=10

Query Parameters

Parameter Required Description
groupId Required group id
skip Required Number of records to skip.
limit Required Number of records to return in response.

Notifications Integrations

Webhook

You will recieve schedule failure payload as follows

{
  "action": "webhook.failed",
  "webhook":
  {
    ...
  }
}

A POST request will be sent to your provided webhook in case of failure if your shceduled webhook does not return 2xx status code.

Slack

In order to integrate Slack with your cronhooks account, you should follow these steps

  1. Go to the "Alerts" page from top right menu of "User Name" and there you will see "Add to Slack" button. Click on it. Cronhooks Slack Integration

  2. "Add to Slack" button will redirect you to the slack auth page where you can choose the channel you want to get Cronhooks alerts to (see the screenshot below). Cronhooks Slack Authorization

  3. After choosing the channel "Authorize" it and you will be redirected back to Cronhooks alerts page. Here you can see all your slack channels in the list. You can add & delete as many channels as you like.

Webhook Signature Verification

To verify the the authenticity that your scheduled webhook was triggered by cronhooks you can check the signature.

[Route("api/[controller]")]
public class CronhooksFailureWebHook : Controller
{
    // You can find your endpoint's secret in your API Keys settings
    const string secret = "wh_...";

    [HttpPost]
    public void Index()
    {
      var json = new StreamReader(HttpContext.Request.Body).ReadToEnd();
      var computedSignature = ComputeSignature(secret, json);
      var cronhooksSignature = Request.Headers["Cronhooks-Signature"];

      if (SecureCompare(computedSignature, cronhooksSignature))
      {
        // Verified
      }
    }

    private string ComputeSignature(string secret, string payload)
    {
      var secretBytes = Encoding.UTF8.GetBytes(secret);
      var payloadBytes = Encoding.UTF8.GetBytes(payload);

      using (var cryptographer = new HMACSHA256(secretBytes))
      {
        var hash = cryptographer.ComputeHash(payloadBytes);
        return BitConverter.ToString(hash).Replace("-", string.Empty).ToLowerInvariant();
      }
    }

    private bool SecureCompare(string a, string b)
    {
      if (a.Length != b.Length)
      {
        return false;
      }

      var result = 0;
      for (var i = 0; i < a.Length; i++)
      {
        result |= a[i] ^ b[i];
      }
      return result == 0;
    }
}

  $webhook_secret = 'wh_...';

  $payload = @file_get_contents('php://input');
  $cronhooks_sig_header = $_SERVER['HTTP_CRONHOOKS_SIGNATURE'];

  $signature = computeSignature($payload, $cronhooks_sig_header);

  if(secureCompare($webhook_secret, $signature)){
    // Verified
  }

  private function computeSignature($payload, $secret){
     return hash_hmac("sha256", $payload, $secret);
  }

  private function secureCompare($secret, $computed){
    if(function_exists('hash_equals')){
      return hash_equals($secret, $computed);
    }

    if (strlen($secret) != strlen($computed)) {
      return false;
    }

    $result = 0;
    for ($i = 0; $i < strlen($secret); $i++) {
      $result |= ord($secret[$i]) ^ ord($computed[$i]);
    }
    return ($result == 0);
  }

Errors

The Cronhooks API uses the following error codes:

Error Code Meaning
400 Bad Request -- Your request is invalid.
401 Unauthorized -- Your API key is wrong.
403 Forbidden -- You shouldn't be here.
404 Not Found -- The specified webhook could not be found.
405 Method Not Allowed -- You tried to access a kitten with an invalid method.
406 Not Acceptable -- You requested a format that isn't json.
429 Too Many Requests -- You're sending too many requests!
500 Internal Server Error -- We had a problem with our server. Try again later.
503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.