Pro and Enterprise plans (beta)

Webhooks

When something happens in Reshta (a contact is created, a deal is won, an order is placed) Reshta sends a signed POST request to your URL. No need to keep polling the API.

1Add your URLIn the Reshta app: Connection → Developer → Webhooks → Add webhook. Enter your HTTPS URL and choose the events.
2Keep the signing secretReshta shows the signing secret (whsec_…) only that once. Keep it on your server to check the signature of every request.
3Answer with 2xxEach event is sent once to each webhook. A 2xx answer within 10 seconds means delivered; anything else means we retry.
  • Only HTTPS URLs on public addresses are accepted; private network addresses are refused and redirects are not followed.
  • Only events that happen after the webhook is created are sent.
  • Records that come from file imports or sample data do not send webhook events.

Event catalogue

18 events

Each event is named object.verb. The body carries only IDs (and, for updates, the names of the changed fields); read the record through the API for details.

Contacts
contact.createdA contact was createdcontact_id
contact.updatedA contact was updatedcontact_id, fields
Companies
company.createdA company was createdcompany_id
company.updatedA company was updatedcompany_id, fields
Leads
lead.createdA lead was createdlead_id
lead.updatedA lead was updatedlead_id, fields
Products
product.createdA product was createdproduct_id
product.updatedA product was updatedproduct_id, fields
Deals
deal.createdA deal was createddeal_id
deal.updatedA deal was updateddeal_id, fields
deal.stage_changedA deal moved to another stagedeal_id, from_stage_id, to_stage_id, pipeline_id
deal.wonA deal was wondeal_idsample
deal.lostA deal was lostdeal_id, lost_reason_id
Orders
order.createdAn order was placedorder_id, contact_idsample
order.status_changedAn order status changedorder_id, contact_id, from, to
Forms
form.submittedA form was submittedform_id, submission_id, contact_id
Appointments
booking.createdAn appointment was bookedbooking_id, booking_type_id, contact_id, status, start_at, end_at
booking.cancelledAn appointment was cancelledbooking_id, contact_id, status, reason
Sample request
POST https://example.com/reshta/webhook​Content-Type: application/json​User-Agent: Reshta-Webhooks/1​Reshta-Event: deal.won​Reshta-Delivery: 0192c5a1-3a5b-7c6d-8e7f-90a1b2c3d4e5​Reshta-Signature: t=1793022003,v1=b5230efdbd5ecead2c10e5373c02395791808788f66ebe612cd0bf9557a6bfc6​​{​  "id": "0192c5a1-2f4e-7a10-8b3c-1d2e3f405162",​  "type": "deal.won",​  "created_at": "2026-10-26T14:20:03.000Z",​  "data": {​    "deal_id": "0192c5a0-9e8d-7c6b-5a49-382716051f2e"​  }​}​

Every event has the same envelope: a unique event id for de-duplication, type, created_at and data. The Reshta-Event and Reshta-Delivery headers carry the event name and the delivery ID.

The sample signature is computed over this exact body with the secret whsec_example.

Verify signatures

Every request carries a Reshta-Signature header: t is the send time (Unix seconds) and v1 is the HMAC-SHA256 signature with that webhook’s signing secret.

Signature header
HTTP
Reshta-Signature: t=1793022003,v1=b5230efdbd5ecead2c10e5373c02395791808788f66ebe612cd0bf9557a6bfc6​
  1. 1Split t and v1 out of the header.
  2. 2Compute HMAC-SHA256 of “t, a dot, the raw body” with the signing secret (hex).
  3. 3Compare the result with v1 in constant time.
  4. 4Our advice: reject the request if t is more than 5 minutes from your clock; t is inside the signed string, so it cannot be forged.
Verify the signature
import crypto from "node:crypto";​​// rawBody: the request body exactly as received (a string or Buffer).​export function verify(rawBody, header, secret) {​  const p = Object.fromEntries(header.split(",").map((kv) => kv.split("=")));​  const expected = crypto​    .createHmac("sha256", secret)​    .update(`${p.t}.${rawBody}`)​    .digest("hex");​  const fresh = Math.abs(Date.now() / 1000 - Number(p.t)) < 300;​  const a = Buffer.from(expected), b = Buffer.from(p.v1 ?? "");​  return fresh && a.length === b.length && crypto.timingSafeEqual(a, b);​}​
The signature covers the raw bytes of the body. If your framework parses JSON before your code sees it, keep the raw body; re-serialised JSON has a different signature.

Retries & delivery history

If your URL does not answer 2xx, Reshta resends the same event at these intervals; about 24 hours in total.

  1. 1First sendnow
  2. 21 minlater
  3. 35 minlater
  4. 430 minlater
  5. 52 hlater
  6. 66 hlater
  7. 715 hlater
  8. ✕Failedkept in history
After 7 attemptsThe delivery is marked failed and stays in the history.
20 failures in a rowThe webhook is disabled. Deliveries are held, not dropped, until you Enable it again.
ReplayResend any delivery from the history; the same body goes out as a new delivery.

Delivery history in the app

Connection → Developer → Webhooks
EventStatusAttemptsLast responseCreatedReplay
deal.wonDelivered1 of 7200Today 14:20
order.createdRetrying3 of 7503Today 14:05
contact.createdFailed7 of 7500Yesterday 09:12Replay
deal.stage_changedDelivered2 of 7200Yesterday 08:40Replay
form.submittedWaiting to send0 of 7—Today 14:21

Create an API key and send your first request

Keys are created in the Reshta app and shown once. The API and webhooks (beta) are on the Pro and Enterprise plans, and only a business admin can create a key.

  1. 1Sign in at app.reshta.ir
  2. 2Connection → Developer
  3. 3Create API key