# Trigger

> The first step of every automation — the event that starts a run for a contact.

A **trigger** is the first step in every automation. It defines which event starts the automation when SendPing receives it.

When your application sends an event to SendPing, every **enabled** automation with a matching trigger **on the event's domain** executes its workflow for the identified contact. Every automation belongs to one of your sending domains (shown on the trigger step), and [`POST /events/send`](https://www.sendping.co/docs/api/events-send) names the domain it targets — so the same event name used across several products never cross-fires. See [Using automations](https://www.sendping.co/docs/automations/overview) for how the steps fit together.

## How it works

The trigger is the first node in the editor. Choose an existing [custom event](https://www.sendping.co/docs/automations/custom-events) or type a new event name, and pick the **domain** the automation belongs to (selected automatically when you have one domain). When creating an automation over the API, the trigger is the first item in the `steps` array with `type: "trigger"`, and `domain` is a required top-level field.

**Node.js**

```js
import { SendPing } from 'sendping';

const mb = new SendPing('mb_xxxxxxxxx');

const { data, error } = await mb.automations.create({
  "name": "Welcome series",
  "domain": "yourdomain.com",
  "steps": [
    {
      "key": "start",
      "type": "trigger",
      "config": { "event_name": "user.created" }
    }
  ],
  "connections": []
});
console.log({ data, error });
```

**Ruby**

```ruby
require "sendping"

SendPing.api_key = "mb_xxxxxxxxx"

SendPing::Automations.create({
  "name": "Welcome series",
  "domain": "yourdomain.com",
  "steps": [
    {
      "key": "start",
      "type": "trigger",
      "config": {
        "event_name": "user.created"
      }
    }
  ],
  "connections": []
})
```

**PHP**

```php
<?php
require 'vendor/autoload.php';

use SendPing\SendPing;

$sendping = SendPing::client('mb_xxxxxxxxx');

$sendping->automations->create([
  'name' => "Welcome series",
  'domain' => "yourdomain.com",
  'steps' => [
    [
      'key' => "start",
      'type' => "trigger",
      'config' => [
        'event_name' => "user.created"
      ]
    ]
  ],
  'connections' => []
]);
```

**Python**

```python
import sendping

sendping.api_key = "mb_xxxxxxxxx"

sendping.Automations.create({
  "name": "Welcome series",
  "domain": "yourdomain.com",
  "steps": [
    {
      "key": "start",
      "type": "trigger",
      "config": {
        "event_name": "user.created"
      }
    }
  ],
  "connections": []
})
```

**Go**

```go
import "github.com/shekhu10/sendping-sdks/sendping-go"

client := sendping.NewClient("mb_xxxxxxxxx")

automation, err := client.Automations.Create(&sendping.CreateAutomationRequest{
    Name:   "Welcome series",
    Domain: "yourdomain.com",
    Steps: []sendping.AutomationStepInput{
        {
            Key:    "start",
            Type:   "trigger",
            Config: map[string]any{"event_name": "user.created"},
        },
    },
    Connections: []sendping.AutomationConnectionInput{},
})
```

**Rust**

```rust
use sendping::{AutomationStepInput, CreateAutomationOptions, SendPing};

let mb = SendPing::new("mb_xxxxxxxxx");

let params = CreateAutomationOptions::new("Welcome series", "yourdomain.com")
    .with_step(AutomationStepInput::new("trigger")
        .with_key("start")
        .with_config(serde_json::json!({"event_name":"user.created"})));
let _automation = mb.automations.create(params).await?;
```

**Java**

```java
import co.sendping.SendPing;
import co.sendping.SendPingResponse;
import co.sendping.requests.AutomationStep;
import co.sendping.requests.CreateAutomationRequest;
import java.util.List;

SendPing sendping = new SendPing("mb_xxxxxxxxx");

CreateAutomationRequest request = CreateAutomationRequest.builder()
        .name("Welcome series")
        .domain("yourdomain.com")
        .step(AutomationStep.builder()
                .key("start")
                .type("trigger")
                .config("event_name", "user.created")
                .build())
        .connections(List.of())
        .build();

SendPingResponse response = sendping.automations().create(request);
```

**.NET**

```csharp
using SendPing;

ISendPing sendping = SendPingClient.Create("mb_xxxxxxxxx");

var resp = await sendping.AutomationCreateAsync(new AutomationCreateOptions
{
    Name = "Welcome series",
    Domain = "yourdomain.com",
    Steps = new List<AutomationStepInput>
    {
        new()
        {
            Key = "start",
            Type = "trigger",
            Config = new Dictionary<string, object?>
            {
                ["event_name"] = "user.created",
            },
        },
    },
    Connections = new List<AutomationConnection>(),
});
```

**cURL**

```bash
curl -X POST 'https://www.sendping.co/api/automations' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Welcome series",
  "domain": "yourdomain.com",
  "steps": [
    {
      "key": "start",
      "type": "trigger",
      "config": { "event_name": "user.created" }
    }
  ],
  "connections": []
}'
```

> **Warning:** Custom event names cannot start with the `sendping:` prefix, which is reserved for system events. The one built-in exception is the `sendping:schedule` scheduled trigger — set it with a `trigger_config` of `{ at, timezone }` to run the automation once for every contact in the domain’s audience at that time (see [Create Automation](https://www.sendping.co/docs/api/automations-create)).

## Engagement triggers

Besides custom events, an automation can start when a contact **engages** with one of your emails. Set the trigger to one of these built-in events — no code required, the platform enrolls the contact automatically:

| Trigger | Starts a run when… |
| --- | --- |
| `email.opened` | the contact opens one of your emails |
| `email.clicked` | the contact clicks a link in one of your emails |
| `email.replied` | the contact replies to one of your emails |
| `email.bounced` | an email to the contact bounces (e.g. tag or notify on bounce) |
| `email.delivered` | an email to the contact is delivered (post-delivery sequences) |

In the editor, pick one under **Event trigger… → When a recipient…**. Over the API, pass the event name as the trigger string (or the trigger step's `config.event_name`).

**Node.js**

```js
import { SendPing } from 'sendping';

const mb = new SendPing('mb_xxxxxxxxx');

const { data, error } = await mb.automations.create({
  "name": "Re-engage on click",
  "domain": "yourdomain.com",
  "trigger": "email.clicked",
  "steps": [
    { "key": "start", "type": "trigger", "config": { "event_name": "email.clicked" } }
  ],
  "connections": []
});
console.log({ data, error });
```

**Ruby**

```ruby
require "sendping"

SendPing.api_key = "mb_xxxxxxxxx"

SendPing::Automations.create({
  "name": "Re-engage on click",
  "domain": "yourdomain.com",
  "trigger": "email.clicked",
  "steps": [
    {
      "key": "start",
      "type": "trigger",
      "config": {
        "event_name": "email.clicked"
      }
    }
  ],
  "connections": []
})
```

**PHP**

```php
<?php
require 'vendor/autoload.php';

use SendPing\SendPing;

$sendping = SendPing::client('mb_xxxxxxxxx');

$sendping->automations->create([
  'name' => "Re-engage on click",
  'domain' => "yourdomain.com",
  'trigger' => "email.clicked",
  'steps' => [
    [
      'key' => "start",
      'type' => "trigger",
      'config' => [
        'event_name' => "email.clicked"
      ]
    ]
  ],
  'connections' => []
]);
```

**Python**

```python
import sendping

sendping.api_key = "mb_xxxxxxxxx"

sendping.Automations.create({
  "name": "Re-engage on click",
  "domain": "yourdomain.com",
  "trigger": "email.clicked",
  "steps": [
    {
      "key": "start",
      "type": "trigger",
      "config": {
        "event_name": "email.clicked"
      }
    }
  ],
  "connections": []
})
```

**Go**

```go
import "github.com/shekhu10/sendping-sdks/sendping-go"

client := sendping.NewClient("mb_xxxxxxxxx")

automation, err := client.Automations.Create(&sendping.CreateAutomationRequest{
    Name:    "Re-engage on click",
    Domain:  "yourdomain.com",
    Trigger: "email.clicked",
    Steps: []sendping.AutomationStepInput{
        {
            Key:    "start",
            Type:   "trigger",
            Config: map[string]any{"event_name": "email.clicked"},
        },
    },
    Connections: []sendping.AutomationConnectionInput{},
})
```

**Rust**

```rust
use sendping::{AutomationStepInput, CreateAutomationOptions, SendPing};

let mb = SendPing::new("mb_xxxxxxxxx");

let params = CreateAutomationOptions::new("Re-engage on click", "yourdomain.com")
    .with_trigger("email.clicked")
    .with_step(AutomationStepInput::new("trigger")
        .with_key("start")
        .with_config(serde_json::json!({"event_name":"email.clicked"})));
let _automation = mb.automations.create(params).await?;
```

**Java**

```java
import co.sendping.SendPing;
import co.sendping.SendPingResponse;
import co.sendping.requests.AutomationStep;
import co.sendping.requests.CreateAutomationRequest;
import java.util.List;

SendPing sendping = new SendPing("mb_xxxxxxxxx");

CreateAutomationRequest request = CreateAutomationRequest.builder()
        .name("Re-engage on click")
        .domain("yourdomain.com")
        .trigger("email.clicked")
        .step(AutomationStep.builder()
                .key("start")
                .type("trigger")
                .config("event_name", "email.clicked")
                .build())
        .connections(List.of())
        .build();

SendPingResponse response = sendping.automations().create(request);
```

**.NET**

```csharp
using SendPing;

ISendPing sendping = SendPingClient.Create("mb_xxxxxxxxx");

var resp = await sendping.AutomationCreateAsync(new AutomationCreateOptions
{
    Name = "Re-engage on click",
    Domain = "yourdomain.com",
    Trigger = "email.clicked",
    Steps = new List<AutomationStepInput>
    {
        new()
        {
            Key = "start",
            Type = "trigger",
            Config = new Dictionary<string, object?>
            {
                ["event_name"] = "email.clicked",
            },
        },
    },
    Connections = new List<AutomationConnection>(),
});
```

**cURL**

```bash
curl -X POST 'https://www.sendping.co/api/automations' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Re-engage on click",
  "domain": "yourdomain.com",
  "trigger": "email.clicked",
  "steps": [
    { "key": "start", "type": "trigger", "config": { "event_name": "email.clicked" } }
  ],
  "connections": []
}'
```

> **Note:** Engagement on an email that an automation itself sent does not re-trigger an automation — this prevents send → open → re-enrol loops. Only opens, clicks and replies on your regular (API, campaign, or manual) sends start engagement automations. Engagement triggers are domain-scoped like everything else: a click on an email sent from `abc.com` only starts `abc.com`'s automations.

A **poll vote** also emits a trigger. When a recipient answers an in-email poll, a `poll.responded` event fires for the contact with the chosen answer available as `event.answer` — set an automation trigger (or a `wait_for_event` step) to `poll.responded` to branch on how they voted. Only existing contacts trigger it.

## Identifying contacts

When you send an event to start an automation, you must identify the contact with either a `contact_id` or an `email`, and name the `domain` the event belongs to. Use `contact_id` when the contact already exists in your [audience](https://www.sendping.co/docs/audiences/overview); use `email` to look the contact up by address. If no contact with the provided email exists in that domain's contacts, SendPing creates one when the run starts — each domain keeps its own contact records, so unsubscribe state stays separate per product.

**Node.js**

```js
import { SendPing } from 'sendping';

const mb = new SendPing('mb_xxxxxxxxx');

const { data, error } = await mb.events.send({
  "event": "user.created",
  "domain": "yourdomain.com",
  "contact_id": "26e2b838-bf6d-4515-b6a7-17525b12b05a",
  "payload": { "plan": "pro" }
});
console.log({ data, error });
```

**Ruby**

```ruby
require "sendping"

SendPing.api_key = "mb_xxxxxxxxx"

SendPing::Events.send({
  "event": "user.created",
  "domain": "yourdomain.com",
  "contact_id": "26e2b838-bf6d-4515-b6a7-17525b12b05a",
  "payload": {
    "plan": "pro"
  }
})
```

**PHP**

```php
<?php
require 'vendor/autoload.php';

use SendPing\SendPing;

$sendping = SendPing::client('mb_xxxxxxxxx');

$sendping->events->send([
  'event' => "user.created",
  'domain' => "yourdomain.com",
  'contact_id' => "26e2b838-bf6d-4515-b6a7-17525b12b05a",
  'payload' => [
    'plan' => "pro"
  ]
]);
```

**Python**

```python
import sendping

sendping.api_key = "mb_xxxxxxxxx"

sendping.Events.send({
  "event": "user.created",
  "domain": "yourdomain.com",
  "contact_id": "26e2b838-bf6d-4515-b6a7-17525b12b05a",
  "payload": {
    "plan": "pro"
  }
})
```

**Go**

```go
import "github.com/shekhu10/sendping-sdks/sendping-go"

client := sendping.NewClient("mb_xxxxxxxxx")

event, err := client.Events.Send(&sendping.SendEventRequest{
    Event:     "user.created",
    Domain:    "yourdomain.com",
    ContactId: "26e2b838-bf6d-4515-b6a7-17525b12b05a",
    Payload:   map[string]any{"plan": "pro"},
})
```

**Rust**

```rust
use sendping::{SendEventOptions, SendPing};

let mb = SendPing::new("mb_xxxxxxxxx");

let params = SendEventOptions::new("user.created", "yourdomain.com")
    .with_contact_id("26e2b838-bf6d-4515-b6a7-17525b12b05a")
    .with_payload_entry("plan", serde_json::json!("pro"));
let _event = mb.events.send(params).await?;
```

**Java**

```java
import co.sendping.SendPing;
import co.sendping.SendPingResponse;
import co.sendping.requests.SendEventRequest;

SendPing sendping = new SendPing("mb_xxxxxxxxx");

SendEventRequest request = SendEventRequest.builder()
        .event("user.created")
        .domain("yourdomain.com")
        .contactId("26e2b838-bf6d-4515-b6a7-17525b12b05a")
        .payload("plan", "pro")
        .build();

SendPingResponse response = sendping.events().send(request);
```

**.NET**

```csharp
using SendPing;

ISendPing sendping = SendPingClient.Create("mb_xxxxxxxxx");

var resp = await sendping.EventSendAsync(new EventSendOptions
{
    Event = "user.created",
    Domain = "yourdomain.com",
    ContactId = "26e2b838-bf6d-4515-b6a7-17525b12b05a",
    Payload = new Dictionary<string, object?> { ["plan"] = "pro" },
});
```

**cURL**

```bash
curl -X POST 'https://www.sendping.co/api/events/send' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
  "event": "user.created",
  "domain": "yourdomain.com",
  "contact_id": "26e2b838-bf6d-4515-b6a7-17525b12b05a",
  "payload": { "plan": "pro" }
}'
```

**CLI**

```bash
sendping events send \
  --name 'user.created' \
  --domain 'yourdomain.com' \
  --contact-id '26e2b838-bf6d-4515-b6a7-17525b12b05a' \
  --data '{"plan":"pro"}'
```

**Node.js**

```js
import { SendPing } from 'sendping';

const mb = new SendPing('mb_xxxxxxxxx');

const { data, error } = await mb.events.send({
  "event": "user.created",
  "domain": "yourdomain.com",
  "email": "user@example.com",
  "payload": { "plan": "pro" }
});
console.log({ data, error });
```

**Ruby**

```ruby
require "sendping"

SendPing.api_key = "mb_xxxxxxxxx"

SendPing::Events.send({
  "event": "user.created",
  "domain": "yourdomain.com",
  "email": "user@example.com",
  "payload": {
    "plan": "pro"
  }
})
```

**PHP**

```php
<?php
require 'vendor/autoload.php';

use SendPing\SendPing;

$sendping = SendPing::client('mb_xxxxxxxxx');

$sendping->events->send([
  'event' => "user.created",
  'domain' => "yourdomain.com",
  'email' => "user@example.com",
  'payload' => [
    'plan' => "pro"
  ]
]);
```

**Python**

```python
import sendping

sendping.api_key = "mb_xxxxxxxxx"

sendping.Events.send({
  "event": "user.created",
  "domain": "yourdomain.com",
  "email": "user@example.com",
  "payload": {
    "plan": "pro"
  }
})
```

**Go**

```go
import "github.com/shekhu10/sendping-sdks/sendping-go"

client := sendping.NewClient("mb_xxxxxxxxx")

event, err := client.Events.Send(&sendping.SendEventRequest{
    Event:   "user.created",
    Domain:  "yourdomain.com",
    Email:   "user@example.com",
    Payload: map[string]any{"plan": "pro"},
})
```

**Rust**

```rust
use sendping::{SendEventOptions, SendPing};

let mb = SendPing::new("mb_xxxxxxxxx");

let params = SendEventOptions::new("user.created", "yourdomain.com")
    .with_email("user@example.com")
    .with_payload_entry("plan", serde_json::json!("pro"));
let _event = mb.events.send(params).await?;
```

**Java**

```java
import co.sendping.SendPing;
import co.sendping.SendPingResponse;
import co.sendping.requests.SendEventRequest;

SendPing sendping = new SendPing("mb_xxxxxxxxx");

SendEventRequest request = SendEventRequest.builder()
        .event("user.created")
        .domain("yourdomain.com")
        .email("user@example.com")
        .payload("plan", "pro")
        .build();

SendPingResponse response = sendping.events().send(request);
```

**.NET**

```csharp
using SendPing;

ISendPing sendping = SendPingClient.Create("mb_xxxxxxxxx");

var resp = await sendping.EventSendAsync(new EventSendOptions
{
    Event = "user.created",
    Domain = "yourdomain.com",
    Email = "user@example.com",
    Payload = new Dictionary<string, object?> { ["plan"] = "pro" },
});
```

**cURL**

```bash
curl -X POST 'https://www.sendping.co/api/events/send' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
  "event": "user.created",
  "domain": "yourdomain.com",
  "email": "user@example.com",
  "payload": { "plan": "pro" }
}'
```

**CLI**

```bash
sendping events send \
  --name 'user.created' \
  --domain 'yourdomain.com' \
  --email 'user@example.com' \
  --data '{"plan":"pro"}'
```

## Event payload

Include a `payload` object with your event to pass data into the automation. This data becomes available as variables in later steps through the `event.*` namespace.

**Node.js**

```js
import { SendPing } from 'sendping';

const mb = new SendPing('mb_xxxxxxxxx');

const { data, error } = await mb.events.send({
  "event": "payment.failed",
  "domain": "yourdomain.com",
  "contact_id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
  "payload": {
    "amount": 49.99,
    "currency": "USD",
    "retryDate": "2026-11-01"
  }
});
console.log({ data, error });
```

**Ruby**

```ruby
require "sendping"

SendPing.api_key = "mb_xxxxxxxxx"

SendPing::Events.send({
  "event": "payment.failed",
  "domain": "yourdomain.com",
  "contact_id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
  "payload": {
    "amount": 49.99,
    "currency": "USD",
    "retryDate": "2026-11-01"
  }
})
```

**PHP**

```php
<?php
require 'vendor/autoload.php';

use SendPing\SendPing;

$sendping = SendPing::client('mb_xxxxxxxxx');

$sendping->events->send([
  'event' => "payment.failed",
  'domain' => "yourdomain.com",
  'contact_id' => "e169aa45-1ecf-4183-9955-b1499d5701d3",
  'payload' => [
    'amount' => 49.99,
    'currency' => "USD",
    'retryDate' => "2026-11-01"
  ]
]);
```

**Python**

```python
import sendping

sendping.api_key = "mb_xxxxxxxxx"

sendping.Events.send({
  "event": "payment.failed",
  "domain": "yourdomain.com",
  "contact_id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
  "payload": {
    "amount": 49.99,
    "currency": "USD",
    "retryDate": "2026-11-01"
  }
})
```

**Go**

```go
import "github.com/shekhu10/sendping-sdks/sendping-go"

client := sendping.NewClient("mb_xxxxxxxxx")

event, err := client.Events.Send(&sendping.SendEventRequest{
    Event:     "payment.failed",
    Domain:    "yourdomain.com",
    ContactId: "e169aa45-1ecf-4183-9955-b1499d5701d3",
    Payload: map[string]any{
        "amount":    49.99,
        "currency":  "USD",
        "retryDate": "2026-11-01",
    },
})
```

**Rust**

```rust
use sendping::{SendEventOptions, SendPing};

let mb = SendPing::new("mb_xxxxxxxxx");

let params = SendEventOptions::new("payment.failed", "yourdomain.com")
    .with_contact_id("e169aa45-1ecf-4183-9955-b1499d5701d3")
    .with_payload_entry("amount", serde_json::json!(49.99))
    .with_payload_entry("currency", serde_json::json!("USD"))
    .with_payload_entry("retryDate", serde_json::json!("2026-11-01"));
let _event = mb.events.send(params).await?;
```

**Java**

```java
import co.sendping.SendPing;
import co.sendping.SendPingResponse;
import co.sendping.requests.SendEventRequest;

SendPing sendping = new SendPing("mb_xxxxxxxxx");

SendEventRequest request = SendEventRequest.builder()
        .event("payment.failed")
        .domain("yourdomain.com")
        .contactId("e169aa45-1ecf-4183-9955-b1499d5701d3")
        .payload("amount", 49.99)
        .payload("currency", "USD")
        .payload("retryDate", "2026-11-01")
        .build();

SendPingResponse response = sendping.events().send(request);
```

**.NET**

```csharp
using SendPing;

ISendPing sendping = SendPingClient.Create("mb_xxxxxxxxx");

var resp = await sendping.EventSendAsync(new EventSendOptions
{
    Event = "payment.failed",
    Domain = "yourdomain.com",
    ContactId = "e169aa45-1ecf-4183-9955-b1499d5701d3",
    Payload = new Dictionary<string, object?>
    {
        ["amount"] = 49.99,
        ["currency"] = "USD",
        ["retryDate"] = "2026-11-01",
    },
});
```

**cURL**

```bash
curl -X POST 'https://www.sendping.co/api/events/send' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
  "event": "payment.failed",
  "domain": "yourdomain.com",
  "contact_id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
  "payload": {
    "amount": 49.99,
    "currency": "USD",
    "retryDate": "2026-11-01"
  }
}'
```

**CLI**

```bash
sendping events send \
  --name 'payment.failed' \
  --domain 'yourdomain.com' \
  --contact-id 'e169aa45-1ecf-4183-9955-b1499d5701d3' \
  --data '{"amount":49.99,"currency":"USD","retryDate":"2026-11-01"}'
```

In this example, `event.amount`, `event.currency`, and `event.retryDate` become available in email templates, [conditions](https://www.sendping.co/docs/automations/condition), and other steps.

## Configuration

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `config.event_name` | string | Yes | The name of the event that triggers the automation. |

```json
{
  "key": "start",
  "type": "trigger",
  "config": {
    "event_name": "user.created"
  }
}
```
