For SaaS products and IT teams

Connect your product to email and WhatsApp with one API call

Your system sends Peikly an event: a sign-up, a trial ending, an invoice due. A Peikly workflow turns it into the right email or WhatsApp message, and every reply lands in your team's shared inbox.

  • Signed requests
  • Duplicate-safe events
  • Official WhatsApp Business Platform

The problem

Your product knows the moment. Your messages miss it.

  • Messaging code in every service

    Email templates in one repo, a WhatsApp provider in another, and a developer pulled in whenever someone wants to change a sentence.

  • WhatsApp has rules of its own

    Templates need Meta's approval, numbers have quality ratings and sending limits, and the 24-hour window decides what you may send.

  • Retries that send twice

    A timeout, a retry, and the customer gets the same message twice. Making sends idempotent is work nobody planned for.

  • Replies go nowhere

    Customers answer your notifications, and the replies sit in a no-reply inbox nobody reads.

How Peikly works

Peikly takes the event from your system and handles the messages, the channel rules and the replies.

  1. Step 1

    API token created

  2. Step 2

    Event signed and sent

  3. Step 3

    Checked for duplicates

  4. Step 4

    Workflow starts

  5. Step 5

    Email or WhatsApp sent

  6. Step 6

    Replies in one inbox

One event, end to end

Here's what happens when a trial is about to end

Your system sends one event. Peikly does the rest, and the run history shows every step.

  1. Your app sends trial.ending One signed POST with the customer's name, email and WhatsApp number.

  2. Peikly accepts the event 202 Accepted: a new event, one workflow triggered.

  3. The contact is matched Created or updated from the customer details in the event.

  4. Email sent A reminder with the upgrade link, from your own mailbox.

  5. WhatsApp sent An approved template message to the customer's number.

  6. The customer replies The question lands in your shared inbox, next to the contact's history.

Read the API guide

Your first event

One signed request. That's the whole integration.

Create a token in Peikly, sign the timestamp, a fresh nonce and the exact body you send, and post it. Build the message itself in a workflow, so changing a sentence never needs a deploy.

  • The timestamp must be within 5 minutes of Peikly's clock
  • A nonce can't be reused for 10 minutes
  • A repeated externalEventId starts nothing
Every header, field and error code
import crypto from "node:crypto";

const token = process.env.PEIKLY_TOKEN;
const body = JSON.stringify({
  provider: "acme-app",
  connection: { externalInstanceId: "eu-1" },
  eventType: "trial.ending",
  externalEventId: "evt_8421",
  customer: {
    fullName: "Daniel Ross",
    email: "daniel@acme.io",
    whatsAppNumber: "+971501234567"
  },
  data: { plan: "Team", daysLeft: 3 }
});
const timestamp = Math.floor(Date.now() / 1000).toString();
const nonce = crypto.randomUUID();
const signature = crypto.createHmac("sha256", token)
  .update(`${timestamp}\n${nonce}\n${body}`).digest("hex");

await fetch("https://app.peikly.com/api/integrations/events", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${token}`,
    "Content-Type": "application/json",
    "X-ArtinCRM-Timestamp": timestamp,
    "X-ArtinCRM-Nonce": nonce,
    "X-ArtinCRM-Signature": `sha256=${signature}`
  },
  body
});
import hashlib, hmac, json, os, time, uuid
import requests

token = os.environ["PEIKLY_TOKEN"]
body = json.dumps({
    "provider": "acme-app",
    "connection": {"externalInstanceId": "eu-1"},
    "eventType": "trial.ending",
    "externalEventId": "evt_8421",
    "customer": {
        "fullName": "Daniel Ross",
        "email": "daniel@acme.io",
        "whatsAppNumber": "+971501234567",
    },
    "data": {"plan": "Team", "daysLeft": 3},
})
timestamp = str(int(time.time()))
nonce = str(uuid.uuid4())
message = f"{timestamp}\n{nonce}\n{body}".encode()
signature = hmac.new(token.encode(), message, hashlib.sha256).hexdigest()

requests.post(
    "https://app.peikly.com/api/integrations/events",
    data=body.encode(),
    headers={
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
        "X-ArtinCRM-Timestamp": timestamp,
        "X-ArtinCRM-Nonce": nonce,
        "X-ArtinCRM-Signature": f"sha256={signature}",
    },
)
TOKEN="$PEIKLY_TOKEN"
BODY='{"provider":"acme-app","connection":{"externalInstanceId":"eu-1"},"eventType":"trial.ending","externalEventId":"evt_8421","customer":{"fullName":"Daniel Ross","email":"daniel@acme.io"}}'
TS=$(date +%s)
NONCE=$(uuidgen)
SIG=$(printf '%s\n%s\n%s' "$TS" "$NONCE" "$BODY" | openssl dgst -sha256 -hmac "$TOKEN" | sed 's/^.* //')

curl https://app.peikly.com/api/integrations/events \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-ArtinCRM-Timestamp: $TS" \
  -H "X-ArtinCRM-Nonce: $NONCE" \
  -H "X-ArtinCRM-Signature: sha256=$SIG" \
  -d "$BODY"

202 Accepted Response

{ "ok": true, "isDuplicate": false, "eventType": "trial_ending",
  "triggeredWorkflowCount": 1, "workflowDispatchStatus": "triggered", … }

Before and after

Less glue code. More answered customers.

Without Peikly

  • Message code spread across services
  • A separate WhatsApp provider to build against
  • Retries that send duplicates
  • A deploy for every copy change
  • Replies lost in a no-reply inbox
  • No record of what was sent

With Peikly

  • One signed API for every event
  • Email and WhatsApp in one place
  • Duplicate events skipped automatically
  • Message copy edited in Peikly, no deploy
  • Every reply in a shared inbox
  • A run history for every event

Questions

Questions IT teams ask

Something the guide does not cover? Message us and an engineer answers.

Ask us on WhatsApp
Is there an endpoint that sends a message directly?

No. Your system sends an event, and a Peikly workflow sends the message. Message content, timing and channel rules stay in Peikly instead of in your code.

How do we sign a request?

Compute HMAC-SHA256 over the timestamp, the nonce and the raw request body, joined by new lines, with the raw token as the key. Send it in X-ArtinCRM-Signature, with the timestamp and nonce in their own headers.

What if we send the same event twice?

Peikly stores each event once per connection and externalEventId. A repeat gets a success response marked as a duplicate and starts nothing.

Can we limit what a token can do?

Yes. Give each token only the scopes it needs, set an expiry date if you want one, and deactivate or remove it at any time. The secret is shown only once.

Do you have a plugin for WordPress or WooCommerce?

Yes. The Peikly plugin sends the store and site events you choose, without any code.

Which plan includes API access?

API access is included in selected plans, and starting workflows from events needs automation. See our pricing for details.

Send your first event today.

Create an API token, post one signed event and watch the workflow run. The guide walks you through every header and field.

  • Signed and duplicate-safe
  • Official WhatsApp platform
  • Cancel anytime
Scroll to Top