Nami ML

Nami ML Documentation

Welcome to the Nami ML documentation hub. You'll find comprehensive guides and documentation to help you start working with Nami ML as quickly as possible, as well as support if you get stuck. Let's jump right in!

Get Started    

Enabling Webhooks

📘

Webhooks are part of our Enterprise plans. Please contact us if you are interested in this feature.

What does Nami provide via Webhook?

Nami provides a variety of data generated by use of our platform that can be sent via webhook to your servers or a third-party platform.

See our list of webhooks event types for everything Nami supports.

The Webhook Payload

The webhook payload will always have the following fields:

  • created_date ISO 8601 format time field for when the event was created
  • event_type the hierarchial event type
  • id unique id for the event
  • user_id Nami's unique user ID associated with the event

Additional data will be available based on the event_type. Take a look at the event types guide for more details.

A full JSON schema for all event payloads is also available here.

📘

Receiving Only the Events you Want

We will be adding new functionality to allow you to subscribe to only the events you wish to receive in the Control Center soon.

For now, you can check the event_type when you process the events to only use the ones you need.

For example, maybe you want to process all user.subscription events or just user.subscription.purchased and user.subscription.cancelled events.

Sending of the Webhook

Nami sends events as a UTF-8 encoded JSON body with a header nami-signutare that allows for validation.

Nami expects your application will return a 2xx status code upon a successful webhook receipt. If we receive any other status code, we will continue to retry sending the message. The retry logic has exponential backoff and some randomness. On average it will continue to retry once an hour for up to 24-hours before it stops trying to send a particular payload.

👍

Nami Best Practice

Because of the retry logic and the asynchronous nature of the sending of the webhooks there is no guarantee that you will receive each event in time order.

We recommend that you check the time stamp on the data you are receiving. In particular for user.subscription events, if you've received a more recent event, you can ignore the old one if all you need to know is your user's current subscription status.

Setting up the Webhook in the Control Center

🚧

Note that we are in the process of improving and expanding our capabilities for delivery data from Nami to you and any 3rd parties you would like to integrate with. While this work is underway, please contact support and provide the URL you would like us to send the webhook data to and we will get it set up for you.

To send data to your endpoint, log in to the Control Center, navigate to the App Settings screen, and enter the URL in the Webhook URL field.

Nami will start sending data to this URL immediately.

Validation and Security

We provide a couple of options that you may use to both secure your webhook endpoint and validate that the data you are receiving is coming from Nami.

  1. Nami hashes the payload of all data sent with HMAC-SHA-256 and a shared secret that is available in our Control Center. The result of this hash is added as nami-signature to the header of the request. You can validate that the signature is correct on your end after receiving the data.

📘

Read here for more information on managing the Nami shared secret.

The following code sample can be used to receive a webhook, validate the signature, and respond to the webhook as either successful or failed.

from flask import Flask, request
import hashlib
import hmac
import os

NAMI_SIGNING_SECRET = bytes(os.environ["NAMI_SIGNING_SECRET"].encode("utf-8"))

app = Flask(__name__)


def compute_signature(data: bytes, secret: bytes) -> str:
  return hmac.new(
    key=secret,
    msg=data,
    digestmod=hashlib.sha256,
  ).hexdigest()


@app.route("/webhook", methods=["POST"])
def webhook():
  unverified_event = request.data
  received_nami_signature = request.headers.get("nami-signature")
  expected_signature = compute_signature(unverified_event, NAMI_SIGNING_SECRET)

  if not received_nami_signature:
    return ({"error": "nami-signature header not received."}, 400)

  if hmac.compare_digest(expected_signature, received_nami_signature):
    # Do Webhook Processing.
    validated_event = request.json
    print(validated_event)

    # Notify server the request succeeded
    return ("", 204)
  else:
    # Webhook fails validation, do not process the event.
    return (
      {
        "error": "Failed Signature Validation",
        "received": received_nami_signature,
        "expected": expected_signature,
      },
      400,
    )
  1. Nami webhooks come from a fixed IP address so you may explicitly allow traffic from our servers. You can retrieve the current list of IPs to add to your allow list from this endpoint and then look at the array for the key "webhook_outbound_ips".
https://api.namiml.com/allowlist.json

👍

Nami Best Practice

We recommend that you poll this endpoint on a regular basis and update your system with the latest list of outbound IPs for our webhooks. Once a day should be sufficient.

Updated 4 days ago


Enabling Webhooks


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.