Skip to main content
Enrichment lets Airdun read customer data that only your systems have — plan name, seat count, lifetime value, feature usage — and use it when building a recovery plan. You expose an HTTP endpoint. Airdun calls it, maps the JSON response onto named fields you define, and stores the result on the recovery case.
Airdun is the client; you are the server. There is no ingest API and no way to push data to Airdun. Enrichment is a read, performed by Airdun against an endpoint you host.

When Airdun calls your endpoint

Your endpoint is called once per recovery case, at case creation — not once per message, and not once per retry. The response is projected into a snapshot that is written onto the case. Every downstream step reads that frozen snapshot; your endpoint is never called again for that case. Data that changes after a case opens will not be reflected in that case. A new failed payment opens a new case, which triggers a new call.

The contract

URL

Your URL must contain the {customer_id} placeholder:
  • The placeholder is replaced with the Stripe customer ID (cus_…), URL-encoded.
  • Only the first occurrence of {customer_id} is substituted.
  • HTTPS is required. Plain HTTP is accepted only for localhost and 127.0.0.1.
  • Maximum length: 2048 characters.

Authentication

Three modes are available. Airdun stores your secret encrypted at rest (AES-256-GCM).
No authentication header is sent. Only appropriate if your endpoint is protected some other way — the Stripe customer ID is not a secret.
Airdun sends:
Airdun sends your secret as the raw value of a header you name — no Bearer prefix, no scheme:
The header name is required when this mode is selected. Maximum 128 characters.

Custom headers

You can add up to 20 additional headers (name ≤ 128 chars, value ≤ 1024 chars).
Custom headers are applied after the authentication header. A custom header whose name collides with your auth header — Authorization, or whatever you named your API key header — will silently overwrite it, and your endpoint will reject the call.

Timeout and failure

  • Timeout is configurable from 500 ms to 30 000 ms. Default: 3000 ms.
  • There are no retries. A single request is made per case. If it fails, it fails.
Enrichment never blocks recovery. If your endpoint times out, returns a non-2xx status, or returns a body that is not valid JSON, Airdun records the error on the case and the recovery case is created anyway with an empty snapshot. When the snapshot is empty:
  • The strategy and message-generation models receive no enrichment context.
  • Escalation rules that reference an enrichment.* field are skipped. Rules that do not reference enrichment still evaluate normally.
A response that is valid JSON but does not match your field mapping is not an error. Unmatched paths simply resolve to null, and the case proceeds silently. Check the call log in your dashboard if fields arrive empty.

Mapping the response to fields

Airdun does not care about your response shape. You define up to 100 fields, each of which extracts one value from the JSON. Every field is optional. A path that does not resolve yields null for that field and nothing else happens — the other fields are unaffected and the case proceeds. There is no way to declare a field mandatory, and a missing field is never an error.

Supported path syntax

The path syntax is a deliberately small subset and is not general-purpose JSONPath. A path must match:
In practice, this means only two operations, starting from $:
  • Dot access on identifier-shaped keys — $.plan.name
  • Numeric array indexing$.seats[0].email
Wildcards ($.items[*]), filter expressions ($.items[?(@.active)]), recursive descent ($..name), slices, and bracket-quoted keys ($['my-key']) are not supported and will be rejected.A key that is not identifier-shaped — total-revenue, 2fa_enabled — is unreachable. Rename it in your response, or expose an alias.

Type coercion

The declared type controls how the extracted value is coerced. Anything that cannot be coerced becomes null.

Where enriched data is used

Once snapshotted, your fields feed three consumers:

Recovery strategy

Fields are passed to the model that designs the recovery plan, as a name → value map. They influence channel ordering, touchpoint count, and timing.

Message generation

The same context is available to the model that writes each message.

Escalation rules

Fields are addressable as enrichment.<field_name> in escalation conditions — for example enrichment.plan.

Language resolution

One field can be nominated to carry the customer’s language. See below.
Enriched values are passed to the model as context. They are not template variables — there is no {{enrichment.field}} interpolation, and you cannot force a value to appear verbatim in a message.

Language field

You can nominate one of your fields as the language field. Its name must match an existing field name. Airdun resolves a customer’s language in this order, taking the first that yields a value:
  1. The language declared on the customer in Airdun
  2. Stripe’s preferred_locales
  3. Your nominated enrichment field
  4. A country-to-language mapping
  5. The workspace fallback language

Example

Your endpoint:
Your response:
A matching field mapping: With locale nominated as the language field, and an escalation rule on enrichment.revenue_ltv_usd.

Testing and observability

Use Test endpoint in the dashboard to fire a real request against your endpoint with a customer ID of your choice. This performs an actual call and shows you the raw response alongside the projected fields — the fastest way to check a path or an auth header. Every call Airdun makes is recorded, including failures, with its status, duration, and error category (timeout, network, http_4xx, http_5xx, http_other). Review them in the call log in your dashboard.
Recovery cases fired from the playground do not call your endpoint — the customer is synthetic, so the lookup would be meaningless. The snapshot for those cases is whatever the playground supplies.

Implementation notes

  • Respond fast. The default budget is 3 seconds with no retry. Serve from a cache or a precomputed table rather than doing expensive joins on the request path.
  • Handle unknown IDs. Stripe customer IDs may exist that your system has no record of. Return 2xx with the fields you have rather than a 404 — a non-2xx discards the entire snapshot, including fields you could have supplied.
  • Keep keys identifier-shaped so the path syntax can reach them.
  • Do not gate on the customer ID alone. It travels in the URL and is not a secret. Use BEARER or API_KEY.