Memory API

Webhooks

Send events from an issue tracker, a CRM, a chat tool or your own application into Harny as data points, and check the signature on the webhooks Harny sends to you.

Copy page
View as Markdown

To check that a webhook came from Harny, go to Check that an event came from Harny.

Send events from another system

Send events with POST /v1/memory/ingest. Each event becomes one data point. Map the event to the ingest body in your own code: the text of the event goes in content, the time it happened in timestamp, and your id for the event in id. A repeated id replaces the earlier data point.

curl -X POST https://api.harny.ai/v1/memory/ingest \
  -H "Authorization: Bearer $HARNY_APP_KEY" \
  -H "X-Harny-User: demo-user" \
  -H "Content-Type: application/json" \
  -d '{ "id": "issue-4412",
        "content": "Acme asked to move the pilot review to Friday.",
        "label": "Issue 4412",
        "timestamp": "2026-07-28T16:00:00Z" }'

A stored event answers 202 with the ingestionId, the sourceId and status: "queued". The other fields of the event go in metadata, and recall returns them in sources[].metadata.

An event is not metered on its own. A person counts toward your monthly-active end users when they use your app. Pricing explains the meter. Sending data covers batches and idempotency.

Check that an event came from Harny

When you add a webhook to an app in the console, Harny shows its signing secret once. Save it then. Harny calls your address with a POST and signs each call, so your server can tell a real call from a forged one.

HeaderWhat it holds
X-Harny-Signaturesha256= followed by the HMAC-SHA256 of the raw request body, written in hex and keyed with the signing secret.
X-Harny-Event-TypeThe event, for example scenario.complete.
X-Harny-Event-IdOne id per event. A retry of the same event carries the same id, so you can ignore one you have already handled.
X-Harny-Delivery-IdOne id per delivery attempt.

Compute the signature over the body exactly as received, before you parse it, and compare it with the header in constant time:

import hashlib, hmac

def is_from_harny(secret: str, raw_body: bytes, header: str) -> bool:
    expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, header)

Answer with any 2xx status within 10 seconds to confirm. If your address fails or times out, Harny tries again after 1 minute, 5 minutes, 25 minutes and 2 hours, five attempts in all. The console lists failed deliveries.