Documentation

Custom HTTP integration

Connect a custom HTTP delivery provider to FounderHQ Sequences.

Send through any provider with an HTTP API, by describing the request FounderHQ should make. About 20 minutes with the provider's API docs open.

Before you start

Check Sequences providers first — if your provider already ships as a recipe, use that instead and skip this page. You need the provider's send-endpoint documentation and an API credential. Then open Sequences in FounderHQ and add an HTTP integration.

How it works

You define one HTTP integration: a request template plus how to read the response. You then create a channel connection that points at it and picks the channel — email, SMS, WhatsApp, or push.

For every message the sequence sends, FounderHQ fills your template with that message's data, calls your endpoint, and reads the reply to learn whether it worked.

Build the request

Method — GET, POST, PUT, PATCH, or DELETE.

URL — must be a public http or https address. It can contain variables.

Headers and query parameters — plain key/value pairs. Values can contain variables.

Body — pick one of three modes:

ModeWhat you writeWhen to use it
jsonA JSON structure. Variables run inside string values.Most JSON APIs
formField names and values. Each value is URL-encoded after it renders.Form-encoded APIs. You never need escaping filters.
rawOne string, sent exactly as it renders.Anything else, or when you need a conditional around whole branches of JSON

Templating uses Liquid. The include, render, and layout tags are turned off.

{ "to": {{ recipient.phone | json }},
  "text": {{ message.text | json }},
  "callback": {{ channel.statusCallbackUrl | json }} }

The json filter is worth using on every value in raw mode. It quotes and escapes the value, so an apostrophe in a message body cannot break your JSON.

A variable with no value renders as an empty string rather than failing — with one exception, described under Guards.

Variables you can use

The person

VariableValue
recipient.valueWhatever address this channel sends to
recipient.emailEmail channel only
recipient.phoneSMS and WhatsApp channels
recipient.tokenPush channel — the device token
recipient.externalIdYour own ID for the contact, when the provider resolves people itself

The message

VariableValue
message.outboundMessageIdFounderHQ's ID for this send. Pass it through if the provider echoes a reference back.
message.contactIdThe contact this send belongs to
message.subjectEmail subject
message.textPlain-text body
message.htmlHTML body
message.titlePush title
message.bodyPush body
message.templateNameThe approved template name, on template sends
message.senderIdIndia DLT sender header, from the SMS template
message.dltTemplateIdIndia DLT template ID, from the SMS template
message.smsTypeIndia DLT category
message.payloadThe whole rendered payload, for anything not listed above

The connection

VariableValue
channel.typeEMAIL, SMS, WHATSAPP, or PUSH
channel.providerTypeThe provider kind behind this connection
channel.connectionIdThis connection's ID
channel.statusCallbackUrlA delivery-report address unique to this connection, with its own token

WhatsApp template sends also get message.metaTemplate (the whole Cloud API template object, for providers that pass Meta's format through), message.bodyParamTexts (the body variables in order), and message.bodyParamMap (the same values keyed by name or position).

Authenticate

You store exactly one secret per integration. Pick how it is sent:

TypeWhat FounderHQ sends
noneNothing
bearerAuthorization: Bearer <secret>
basicAuthorization: Basic <base64 of username:secret>
custom_headerA header you name, with an optional literal prefix before the secret — for example Basic for a key you already encoded
body_fieldThe secret as a top-level field of the JSON body, under a name you choose
hmac_sha256An HMAC-SHA256 of the request body, signed with the secret, in a header you name. Defaults to x-founderhq-signature and a sha256= prefix.

The secret is applied after the template renders, so it never appears in anything FounderHQ stores or shows you.

Read the response

Point FounderHQ at the fields it should read, using dotted paths like data.id or messages.0.id.

SettingWhat it finds
idPathThe provider's message ID. Delivery reports match against it. Falls back to a top-level id.
urlPathA link to the message at the provider. Falls back to a top-level url.
statusPathA status value in the body. Falls back to a top-level status.
errorPathThe error text to show you when the send fails. Falls back to error, then message.
failStatusA status value that means failure even on an HTTP 200. Set this for APIs that answer 200 with {"type":"error"}.

FounderHQ retries on 429 and on 5xx responses. Every other failure is permanent — a bad key or a rejected recipient stops rather than looping. Requests time out after 15 seconds.

Delivery reports

channel.statusCallbackUrl is a per-connection address carrying its own token. Two ways to use it:

  • Put it in the send request, if the provider takes a callback URL per message. Nothing to configure at the provider.
  • Paste it into the provider's dashboard, if that is where webhooks are set.

FounderHQ understands the Meta WhatsApp envelope and the delivery-receipt formats of the SMS providers it ships recipes for. A provider with a shape of its own can POST FounderHQ's normalized status format instead.

If you wire no callback at all the integration still works. Messages just stop at Sent, and sequence steps cannot wait on delivery.

Guards

FounderHQ refuses to send a request it knows is wrong:

  • No recipient. Your template must reference the right recipient variable for the channel, and it must have a value. Otherwise the send fails instead of going out addressed to nobody.
  • Empty regulatory fields. If your template references an India DLT variable, that variable must have a value. It is never sent blank. See India DLT.
  • Session messages the provider cannot take. A connection marked as template-only rejects free-text WhatsApp sends outright.

Verify

  1. Use the integration's test send. It shows the exact request FounderHQ built and the provider's raw reply.
  2. The reply's message ID appears in the mapped result. If it reads empty, fix idPath.
  3. Build a sequence with one step on this connection and run yourself through it. The message arrives, and the sequence shows it as Sent.

Troubleshoot

The test send says a required variable is missing

Your template references something the test context has no value for. Check the variable names against the tables above.

The provider answers 200 but nothing arrives

The API is reporting failure inside a successful response. Set statusPath and failStatus so FounderHQ treats it as a failure too.

Messages send but never reach Delivered

No callback is wired. Either add channel.statusCallbackUrl to the send request, or paste it into the provider's webhook settings.

The body is malformed when a message contains quotes

You are in raw mode without the json filter. Write {{ message.text | json }}, not "{{ message.text }}".

AI agent or LLM? Read this page as markdown

On this page