SendBeam

Kestra setup

Connect SendBeam to Kestra: what you need, the steps, and the code.

View as Markdown

Via API

Kestra describes a pipeline as YAML — inputs, tasks, triggers — and runs it on a schedule or on an event. SendBeam is a JSON API behind one header, so a flow that adds a customer or sends an order confirmation is an HTTP task with a secret, and SendBeam's webhooks can start a flow the same way.

Before you start

  • A Kestra instance (0.18 or later)
  • A SendBeam API key with the permissions the flow needs
  • A verified sending domain, for site email

Set it up

  1. Create an API key. Settings → API keys in SendBeam, with contacts:write and transactional:send (and lists:write if you add a list task: POST /api/v1/lists/{id}/contacts with the same headers). The full key is shown once. Store it as the Kestra secret SENDBEAM_API_KEY (base64-encoded in the SECRET_SENDBEAM_API_KEY environment variable on a self-hosted instance).
  2. Add the flow. Paste the YAML below into a new flow. Its inputs become the form you fill in when running it by hand.
  3. Run it once with your own address, check the contact and the email in SendBeam, then add a schedule or a trigger.
  4. Optional: let SendBeam start a flow. The second file below has a webhook trigger; add its URL under Settings → Webhooks in SendBeam.

Code

The flow: add a contact and welcome them

sendbeam-welcome.yaml

id: sendbeam_welcome
namespace: company.marketing

inputs:
  - id: email
    type: STRING
  - id: name
    type: STRING
    defaults: ""

tasks:
  - id: add_contact
    type: io.kestra.plugin.core.http.Request
    uri: https://sendbeam.io/api/v1/contacts
    method: POST
    contentType: application/json
    headers:
      x-api-key: "{{ secret('SENDBEAM_API_KEY') }}"
    body: |
      {
        "email": "{{ inputs.email }}",
        "first_name": "{{ inputs.name | split(' ') | first }}",
        "source": "kestra"
      }
    # 409 means the address is already a contact: carry on.
    allowFailed: true

  - id: welcome_email
    type: io.kestra.plugin.core.http.Request
    uri: https://sendbeam.io/api/v1/transactional
    method: POST
    contentType: application/json
    headers:
      x-api-key: "{{ secret('SENDBEAM_API_KEY') }}"
    body: |
      {
        "to": { "email": "{{ inputs.email }}", "name": "{{ inputs.name }}" },
        "subject": "Welcome aboard",
        "html": "<p>Hi {{ inputs.name | split(' ') | first | default('there') }}, thanks for signing up.</p>"
      }

The trigger: a SendBeam event starts a flow

sendbeam-events.yaml

id: sendbeam_events
namespace: company.marketing

triggers:
  - id: sendbeam
    type: io.kestra.plugin.core.trigger.Webhook
    # Kestra's webhook URL for this flow ends in the namespace, the flow id and this key.
    key: "{{ secret('SENDBEAM_WEBHOOK_KEY') }}"

tasks:
  - id: route
    type: io.kestra.plugin.core.flow.Switch
    value: "{{ trigger.body.type }}"
    cases:
      contact.created:
        - id: on_contact
          type: io.kestra.plugin.core.log.Log
          message: "New contact {{ trigger.body.data.email }}"
      email.clicked:
        - id: on_click
          type: io.kestra.plugin.core.log.Log
          message: "Click from {{ trigger.body.data.email }}"
    defaults:
      - id: ignore
        type: io.kestra.plugin.core.log.Log
        message: "Ignored {{ trigger.body.type }}"

The webhook key in the URL is what authenticates SendBeam to Kestra; keep it as a secret and rotate it from Settings → Webhooks if it leaks. For signature verification as well, put a small script task (Python or Node) before route that checks X-SendBeam-Signature the way the Webhooks docs show.

Things to know

  • Use one secret per environment so a development instance never writes to your production list.
  • POST /api/v1/contacts answers 409 for an address that already exists; allowFailed: true lets the flow carry on, which makes a re-run safe.
  • Kestra’s Schedule trigger turns the first flow into a nightly sync when its inputs come from a query or a file task earlier in the flow.
  • Only add people to a marketing list if they agreed to hear from you. Site email through /api/v1/transactional needs no marketing consent.

← Back to the Kestra integration