Why Webhooks

Gathering utility data is an inherently asynchronous process because it's somewhat dependent on the performance and availability of utility websites. We recommend ingesting customer data into your application using webhooks to avoid the resource-intensive process of polling Arc's servers. It will simplify your implementation and help maintain the performance of Arc.

How To Register A Webhook Endpoint

You can register webhook endpoints (your URLs that Arc will send webhook data to) from the Arc dashboard, or from the console.

The do so from the dashboard, visit https://arc.arcadia.com/configuration/webhooks. From here, you can create webhook endpoints by supplying a URL, and choosing if sandbox or live webhooks will be sent there. You can also send test events to the endpoints after you've configured them.

To set up a webhook endpoint via the console, do the following:

// First request an Access Token
$ curl -i -X POST https://api.arcadia.com/auth/access_token \
  -F "client_id=$YOUR_ARC_API_CLIENT_ID" \
  -F "client_secret=$YOUR_ARC_API_CLIENT_SECRET"

// Then register the webhook URI with the new Access Token that was generated in the previous command
$ curl -i -X POST https://api.arcadia.com/webhook/endpoints \
  -H "Authorization: Bearer $YOUR_NEW_ACCESS_TOKEN" \
  -d "url=$YOUR_WEBHOOK_URI"

How To Verify Webhook Signatures

In order to validate that webhooks are actually from Arc and not from a malicious source, we recommend you verify the unique signature included in the webhook header. When you create a webhook, the API response will include a webhook_signing_key which you'll need for verification.

Below is a Node.js implementation but the process should be similar across languages.

import { createHmac } from 'crypto';
import { env } from 'process';
import timingSafeCompare from 'tsscmp';

const secondsToStale = 300; // 5 minutes
const nowTimestamp = Math.floor( Date.now() / 1000 ); // Seconds since epoch

// 1. Extract the timestamp and signatures from the header
const webhookTimestamp = req.header('Arc-Webhook-Timestamp');
const webhookSignature = req.header('Arc-Webhook-Signature');

// 2. Prepare the payload string by concatenating the timestamp with the body
const payloadToSign = `${webhookTimestamp}.${req.body}`;

// 3. Calculate the Signature using the Webhook Secret
const hmac = createHmac('sha256', <WEBHOOK_SIGNING_KEY>);
const calculatedSignature = hmac.update(payloadToSign).digest('hex');

// 4. If the timestamp is older than the threshold, this may be a replay attack
if ((nowTimestamp - webhookTimestamp) > secondsToStale) {
  throw Error('This webhook was received outside of the defined tolerance.');

// 5. If the signatures don't match, this may be a fraudulent webhook
// Be sure to use a constant time string comparison algorithm to prevent timing attacks
if (!timingSafeCompare(webhookSignature, calculatedSignature)) {
  throw Error('The calculated signature does not match the signature provided in the request header');

Disabling Failing Webhook Endpoints

Arc will automatically disable a webhook endpoint if it has not responded successfully to events for multiple days in a row. This will occur silently for sandboxed webhook endpoints, but we will attempt to contact you via email if one of your live webhook endpoints is consistently failing. This email will contain the date on which we will automatically disable the webhook endpoint unless it begins responding with a successful HTTP status code. If one of your endpoints is disabled in this way, you may reenable it using the Arc API once you have fixed the underlying issue.