Gareth Wilson Gareth Wilson

Guide to Smile API Webhooks: Features and Best Practices

Published


Smile API webhooks notify your application when a user's account connects, a data-pull task finishes, or income and employment records are added. If you're building on Smile API for employment and income data in Southeast Asia, webhooks are how you react to these events without polling.

This guide covers how Smile API webhooks work, the events you'll handle, how to verify the Smile-Signature (it's SHA-512), and the best practices for production.

This covers Smile API (getsmileapi.com), the Southeast Asia employment/income data aggregator. It is not Smile.io (loyalty) or Smile Identity (KYC), which are unrelated companies.

What are Smile API webhooks?

Smile API webhooks are HTTP POSTs delivered over HTTPS to a URL you register. Each is signed with a Smile-Signature header (note: no X- prefix). The value is an HMAC-SHA512 (not SHA256) hex digest of the entire raw, unmodified request body, keyed with the per-endpoint secret (1 to 64 characters) you set at registration. This is not Standard Webhooks.

Smile API webhook features

FeatureDetails
Configurationportal.getsmileapi.com/webhooks or POST /webhooks; set a per-endpoint secret
Signature headerSmile-Signature (no X- prefix)
Signature schemeHMAC-SHA512 (hex) over the entire raw body, keyed with the per-endpoint secret
EventsUPPER_SNAKE_CASE (ACCOUNT_CONNECTED, TASK_FINISHED, ...); ALL_EVENTS subscribes to everything
DeliveryAt-least-once; non-2xx retried up to 2 times seconds apart, dedupe on id
PayloadOptional includePayload inlines full data (max 300 list items) for TASK_FINISHED / ACCOUNT_SYNC_TASK_FINISHED
Source IPStatic 18.142.61.230 (HTTPS only)
SDKNone

Common events

Smile API events are UPPER_SNAKE_CASE. There are roughly 35 types, some with _ADDED / _UPDATED variants. A common set:

EventFires when
ACCOUNT_CONNECTEDA user connects an account
TASK_FINISHEDA data-pull task finishes
INCOMES_ADDEDIncome records are added
EMPLOYMENTS_ADDEDEmployment records are added
IDENTITY_ADDEDIdentity data is added
RECORD_COMPLETEDA record completes

Subscribe to ALL_EVENTS to receive everything, or pick the specific UPPER_SNAKE_CASE names you handle.

Setting up Smile API webhooks

Create webhooks at portal.getsmileapi.com/webhooks or via POST /webhooks, and set a per-endpoint secret (1 to 64 characters) for verification. Deliveries originate from the static IP 18.142.61.230 over HTTPS, so you can allowlist it as an extra layer.

Securing Smile API webhooks

The Smile-Signature header is an HMAC-SHA512 hex digest of the entire raw body, keyed with your per-endpoint secret. To verify, compute the SHA-512 HMAC over the raw body and compare. Digest the full raw payload with no leading or trailing whitespace, not re-serialized JSON.

const crypto = require("crypto");

const SECRET = process.env.SMILE_WEBHOOK_SECRET;

function verify(rawBody, signature) {
  // HMAC-SHA512 (not SHA256) over the entire raw body
  const expected = crypto.createHmac("sha512", SECRET).update(rawBody).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(signature || "");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
  if (!verify(req.body, req.headers["smile-signature"])) {
    return res.sendStatus(401);
  }

  res.sendStatus(200); // acknowledge fast
  processQueue.add(JSON.parse(req.body)); // dedupe on id, async
});

The same check in Python:

import hashlib
import hmac
import os

SECRET = os.environ["SMILE_WEBHOOK_SECRET"].encode()


def verify(raw_body: bytes, signature: str) -> bool:
    expected = hmac.new(SECRET, raw_body, hashlib.sha512).hexdigest()  # SHA-512, not 256
    return hmac.compare_digest(expected, signature or "")

Smile API webhook limitations and pain points

It's SHA-512, and the header has no X- prefix

The Problem: The HMAC is SHA-512, not SHA-256, and the header is Smile-Signature with no X- prefix. A SHA-256 verifier, or code that looks for X-Smile-Signature, fails.

Why It Happens: Smile API uses SHA-512 and a non-prefixed header name.

Workarounds:

  • Use SHA-512 over the raw body, and read the exact Smile-Signature header.

How Hookdeck Can Help: Hookdeck verifies the signature at the edge with the right algorithm and header, so your app doesn't hard-code either.

It's Smile API, not Smile.io or Smile Identity

The Problem: Three unrelated companies share the "Smile" name. Applying one's verification or event model to another fails.

Why It Happens: The name collides across loyalty (Smile.io), KYC (Smile Identity), and data aggregation (Smile API).

Workarounds:

  • Confirm you're integrating getsmileapi.com, and use its SHA-512 Smile-Signature scheme.

How Hookdeck Can Help: Hookdeck verifies each source with its own scheme, so a name collision doesn't lead to the wrong verification.

At-least-once delivery

The Problem: Non-2xx responses are retried up to two times seconds apart, so the same event can arrive more than once.

Why It Happens: Smile API guarantees at-least-once delivery.

Workarounds:

  • Dedupe on the event id and make handlers idempotent.

How Hookdeck Can Help: Hookdeck deduplicates deliveries at the edge, so retries don't double-process. See our guide to webhook idempotency.

Payload is inlined only with a flag

The Problem: Full data is inlined only when includePayload is set (and capped at 300 list items) for TASK_FINISHED / ACCOUNT_SYNC_TASK_FINISHED. Otherwise you fetch the data separately.

Why It Happens: Smile API keeps payloads lean unless you opt in.

Workarounds:

  • Set includePayload where you need inline data, and fetch via the API otherwise.

How Hookdeck Can Help: Hookdeck durably queues events so your worker can enrich them via the API at its own pace.

Best practices

Verify the SHA-512 HMAC over the raw body

Compute HMAC-SHA512 over the entire raw body with your per-endpoint secret and compare against Smile-Signature in constant time.

Dedupe on the event id

Delivery is at-least-once, so dedupe on id and make handlers idempotent.

Allowlist the static source IP

Deliveries come from 18.142.61.230 over HTTPS, so allowlisting it adds a layer alongside signature verification.

Return 200 and process asynchronously

Acknowledge quickly and defer work to a queue. See why to process webhooks asynchronously.

Make Smile API webhooks production-ready

Hookdeck verifies Smile-Signature, deduplicates, and durably queues every event

Conclusion

Smile API (getsmileapi.com) webhooks are verified with a Smile-Signature header, an HMAC-SHA512 over the entire raw body keyed with your per-endpoint secret. This is Smile API, not Smile.io or Smile Identity. Verify SHA-512 over the raw body, use the UPPER_SNAKE_CASE event names, dedupe on id across the at-least-once retries, and optionally allowlist the static source IP.

Hookdeck verifies the signature, deduplicates, and durably queues every event at the edge, so your app only ever processes verified, unique events.

Get started with Hookdeck for free and handle Smile API webhooks reliably in minutes.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.