# Custom Events

> Define custom events to trigger automations.

Custom events are used to [trigger](https://www.mailblastr.com/docs/automations/trigger) automations and can be defined with an optional schema for payload validation.

If a schema is defined, payloads are validated when the event is sent. Fields that don't match the expected type are rejected with a `422` error and the event is not delivered.

## How it works

In the dashboard, the **Events** page shows all existing events. Click **Add event**, enter the event name and an optional schema to define the event payload you will send with the event, then **Save**.

Over the API, all existing events can be retrieved with the [List Events API](https://www.mailblastr.com/docs/api/events-list). To create a new event, use the [Create Event API](https://www.mailblastr.com/docs/api/events-create).

**Node.js**

```js
import { MailBlastr } from 'mailblastr';

const mb = new MailBlastr('mb_xxxxxxxxx');

const { data, error } = await mb.events.create({
  "name": "user.created",
  "schema": {
    "plan": "string"
  }
});
console.log({ data, error });
```

**Ruby**

```ruby
require "mailblastr"

Mailblastr.api_key = "mb_xxxxxxxxx"

Mailblastr::Events.create({
  "name": "user.created",
  "schema": {
    "plan": "string"
  }
})
```

**PHP**

```php
$mailblastr = Mailblastr::client('mb_xxxxxxxxx');

$mailblastr->events->create([
  'name' => "user.created",
  'schema' => [
    'plan' => "string"
  ]
]);
```

**Python**

```python
import mailblastr

mailblastr.api_key = "mb_xxxxxxxxx"

mailblastr.Events.create({
  "name": "user.created",
  "schema": {
    "plan": "string"
  }
})
```

**Go**

```go
package main

import (
    "fmt"
    "io"
    "net/http"
    "strings"
)

func main() {
    req, _ := http.NewRequest("POST", "https://api.mailblastr.com/events", strings.NewReader(`{
  "name": "user.created",
  "schema": {
    "plan": "string"
  }
}`))
    req.Header.Set("Authorization", "Bearer mb_xxxxxxxxx")
    req.Header.Set("Content-Type", "application/json")
    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()
    out, _ := io.ReadAll(res.Body)
    fmt.Println(string(out))
}
```

**Rust**

```rust
use reqwest::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let res = Client::new()
        .post("https://api.mailblastr.com/events")
        .header("Authorization", "Bearer mb_xxxxxxxxx")
        .header("Content-Type", "application/json")
        .body(r#"{
  "name": "user.created",
  "schema": {
    "plan": "string"
  }
}"#)
        .send()
        .await?;
    println!("{}", res.text().await?);
    Ok(())
}
```

**Java**

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.mailblastr.com/events"))
    .header("Authorization", "Bearer mb_xxxxxxxxx")
    .header("Content-Type", "application/json")
    .method("POST", HttpRequest.BodyPublishers.ofString("""
{
  "name": "user.created",
  "schema": {
    "plan": "string"
  }
}
"""))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
```

**.NET**

```csharp
using System.Net.Http;
using System.Text;

var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.mailblastr.com/events");
request.Headers.Add("Authorization", "Bearer mb_xxxxxxxxx");
request.Content = new StringContent(@"{
  ""name"": ""user.created"",
  ""schema"": {
    ""plan"": ""string""
  }
}", Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

**cURL**

```bash
curl -X POST 'https://api.mailblastr.com/events' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "user.created",
  "schema": {
    "plan": "string"
  }
}'
```

**CLI**

```bash
mailblastr events create \
  --name 'user.created' \
  --schema '{"plan":"string"}'
```

**Response**

```json
{
  "object": "event",
  "id": "b6d24b8e-af0b-4c3c-be0c-359bbd97381e",
  "name": "user.created",
  "schema": {
    "plan": "string"
  },
  "created_at": "2026-06-23T10:00:00.000Z",
  "updated_at": "2026-06-23T10:00:00.000Z"
}
```

> **Note:** The event name can be any string (e.g. `user.created`, `welcome`, `my-custom-event`). Dot notation is a recommended convention but is not required. If multiple enabled automations use the same event name, **all** of them will be triggered.

## Sending events

Trigger your automations by sending an event with [`POST /events/send`](https://www.mailblastr.com/docs/api/events-send). Name the `domain` the event belongs to (only that domain's automations fire), identify the contact by `contact_id` or `email`, and optionally attach a `payload` object — its fields become available as `event.*` variables in templates, [conditions](https://www.mailblastr.com/docs/automations/condition), and other steps. See [Trigger](https://www.mailblastr.com/docs/automations/trigger) for details.

**Node.js**

```js
import { MailBlastr } from 'mailblastr';

const mb = new MailBlastr('mb_xxxxxxxxx');

const { data, error } = await mb.events.send({
  "event": "user.created",
  "domain": "yourdomain.com",
  "contact_id": "479e3145-dd38-476b-932c-529ceb705947",
  "payload": {
    "plan": "pro"
  }
});
console.log({ data, error });
```

**Ruby**

```ruby
require "mailblastr"

Mailblastr.api_key = "mb_xxxxxxxxx"

Mailblastr::Events.send({
  "event": "user.created",
  "domain": "yourdomain.com",
  "contact_id": "479e3145-dd38-476b-932c-529ceb705947",
  "payload": {
    "plan": "pro"
  }
})
```

**PHP**

```php
$mailblastr = Mailblastr::client('mb_xxxxxxxxx');

$mailblastr->events->send([
  'event' => "user.created",
  'domain' => "yourdomain.com",
  'contact_id' => "479e3145-dd38-476b-932c-529ceb705947",
  'payload' => [
    'plan' => "pro"
  ]
]);
```

**Python**

```python
import mailblastr

mailblastr.api_key = "mb_xxxxxxxxx"

mailblastr.Events.send({
  "event": "user.created",
  "domain": "yourdomain.com",
  "contact_id": "479e3145-dd38-476b-932c-529ceb705947",
  "payload": {
    "plan": "pro"
  }
})
```

**Go**

```go
client := mailblastr.NewClient("mb_xxxxxxxxx")

params := &mailblastr.SendEventRequest{
    Name:   "signup.completed",
    Domain: "yourdomain.com",
    Email:  "jane@example.com",
}
event, err := client.Events.Send(params)
```

**Rust**

```rust
let mb = Mailblastr::new("mb_xxxxxxxxx");

let event = SendEventOptions::new("signup.completed", "yourdomain.com")
    .with_email("jane@example.com");
let _sent = mb.events.send(event).await?;
```

**Java**

```java
Mailblastr mailblastr = new Mailblastr("mb_xxxxxxxxx");

SendEventRequest request = SendEventRequest.builder()
    .name("signup.completed")
    .domain("yourdomain.com")
    .email("jane@example.com")
    .build();
mailblastr.events().send(request);
```

**.NET**

```csharp
IMailblastr mailblastr = MailblastrClient.Create("mb_xxxxxxxxx");

var resp = await mailblastr.EventSendAsync(new EventSendOptions
{
    Name = "signup.completed",
    Domain = "yourdomain.com",
    Email = "jane@example.com",
});
```

**cURL**

```bash
curl -X POST 'https://api.mailblastr.com/events/send' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
  "event": "user.created",
  "domain": "yourdomain.com",
  "contact_id": "479e3145-dd38-476b-932c-529ceb705947",
  "payload": {
    "plan": "pro"
  }
}'
```

## Configuration

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | Yes | The name of the custom event to create. Used to match events to automation triggers. Cannot start with the `mailblastr:` prefix, which is reserved for system events. |
| `schema` | object | No | An optional schema definition for the event payload. Must be an object with flat key/type pairs. Supported types: `string`, `number`, `boolean`, `date`. |

**Example**

```json
{
  "schema": {
    "plan": "string",
    "amount": "number",
    "date": "date",
    "is_active": "boolean"
  }
}
```

> **Warning:** Event names cannot start with the `mailblastr:` prefix, which is reserved for system events. Creating a definition with a name that already exists returns a `validation_error`.
