# Webhooks API

> Registra endpoints que reciben notificaciones de eventos firmadas.

URL base: `https://api.emailit.com/v2`. Autentícate con `Authorization: Bearer <API key>`.

## Crear un webhook — POST /webhooks

> Registra un endpoint HTTP que recibe notificaciones de eventos firmadas, elige sus tipos de eventos y, a partir del plan Pro, un filtro de payload.

# Crear un webhook

Crea un endpoint de webhook en tu espacio de trabajo. Emailit envía los eventos que coinciden a la URL en lotes de hasta 100, como un array JSON firmado con el `secret` del webhook. Para el formato de la petición, consulta [Peticiones de webhook](/es/docs/webhooks/webhook-requests/). Requiere una clave de API con el permiso `full`.

`POST /webhooks`

## Cuerpo de la petición

- `name` (string, obligatorio): El nombre del webhook. Debe ser único en el espacio de trabajo; puedes usarlo en lugar del ID en los demás endpoints de webhooks.

- `url` (string, obligatorio): El endpoint que recibe los eventos. Se aceptan URL `http` y `https`; usa `https` en producción. Emailit resuelve el nombre de host al guardar y rechaza `localhost`, las direcciones IP privadas, las de enlace local y otras direcciones IP reservadas. Las redirecciones no se siguen en la entrega, así que usa la URL final.

- `all_events` (boolean): Envía todos los tipos de eventos, incluidos los que se añadan más adelante. Por defecto, `false`. Si es `true`, `events` se ignora.

- `enabled` (boolean): Si Emailit entrega eventos al webhook. Por defecto, `true`.

- `events` (string[]): Los tipos de eventos que se envían, por ejemplo `["email.delivered", "email.bounced"]`. Consulta [Tipos de eventos](/es/docs/webhooks/event-types/). Por defecto, `[]`, lo que, con `all_events: false`, significa que el webhook no recibe nada. Los nombres de eventos no se validan. Un tipo mal escrito se guarda, pero nunca coincide con ningún evento.

- `filter` (object | null): El filtro de payload. Emailit solo envía los eventos cuyo objeto cumple las reglas. Disponible en los planes Pro, Business y Custom; en Pay as you go, un filtro con reglas devuelve `403`.

- `filter.match` (string): `all` (por defecto) envía un evento si se cumplen todas las reglas. `any` lo envía si se cumple al menos una.

- `filter.rules` (object[]): Hasta 25 reglas.

- `filter.rules[].field` (string, obligatorio): La ruta con puntos dentro del objeto del evento, por ejemplo `to`, `status`, `meta.plan` o, en los eventos de clic y de apertura, `email.campaign.id`. Un prefijo `payload.` se ignora.

- `filter.rules[].operator` (string, obligatorio): `equals`, `not_equals`, `contains`, `not_contains`, `starts_with`, `ends_with`, `greater_than`, `less_than`, `is_set`, `is_not_set`, `in` o `not_in`. Los operadores de texto comparan los valores como cadenas; `greater_than` y `less_than` comparan números.

- `filter.rules[].value` (any): El valor con el que se compara. Obligatorio con todos los operadores salvo `is_set` e `is_not_set`. Usa un array con `in` y `not_in`.

## Devuelve

Devuelve `201 Created` con el objeto de webhook, incluido el `secret` de firma (`whsec_` seguido de 64 caracteres hexadecimales). Usa el secreto para [verificar las firmas de las peticiones](/es/docs/webhooks/request-signature/). Puedes volver a leerlo con [Obtener un webhook](/es/docs/api-reference/webhooks/get/) y rotarlo con [Rotar el secreto de firma](/es/docs/api-reference/webhooks/reset-secret/).

| Código | Cuándo |
| --- | --- |
| `400` | Falta `name` o `url`, la URL no es válida, no se puede resolver o apunta a una dirección no permitida, o el filtro no es válido. |
| `403` | El filtro tiene reglas y tu plan no incluye filtros de webhooks. El cuerpo es `{"error": "plan_required", "required_plan": "pro"}`. |
| `409` | Ya existe un webhook con este nombre. El cuerpo incluye en `existing` el `id` y el `name` del webhook existente. |
| `422` | El espacio de trabajo ha alcanzado el límite de webhooks de su plan. El cuerpo incluye `usage.used` y `usage.limit`. Consulta [Límites](/es/docs/limits/). |

**Petición** `POST /webhooks`

**Node.js**

```javascript
import { Emailit } from '@emailit/node';
const emailit = new Emailit('your_api_key');

const webhook = await emailit.webhooks.create({
    name: 'Production events',
    url: 'https://api.acme.com/webhooks/emailit',
    events: ['email.delivered']
});
```

**Python**

```python
from emailit import EmailitClient
client = EmailitClient("your_api_key")

webhook = client.webhooks.create({
    "name": "Production events",
    "url": "https://api.acme.com/webhooks/emailit",
    "events": ["email.delivered"]
})
```

**PHP**

```php
$emailit = Emailit::client('your_api_key');

$webhook = $emailit->webhooks()->create([
    'name' => 'Production events',
    'url' => 'https://api.acme.com/webhooks/emailit',
    'events' => ['email.delivered']
]);
```

**Ruby**

```ruby
require "emailit"
client = Emailit::EmailitClient.new("your_api_key")

webhook = client.webhooks.create(
    name: "Production events",
    url: "https://api.acme.com/webhooks/emailit",
    events: ["email.delivered"]
)
```

**Go**

```go
import "github.com/emailit/emailit-go/v2"
client := emailit.NewClient("your_api_key")

webhook, err := client.Webhooks.Create(&emailit.CreateWebhookRequest{
    Name:   "Production events",
    Url:    "https://api.acme.com/webhooks/emailit",
    Events: []string{"email.delivered"},
})
```

**Rust**

```rust
use emailit::Emailit;
let emailit = Emailit::new("your_api_key");

let webhook = emailit.webhooks.create(
    emailit::types::CreateWebhookParams::new(
        "Production events",
        "https://api.acme.com/webhooks/emailit"
    ).with_events(vec!["email.delivered".into()])
).await?;
```

**Java**

```java
import com.emailit.*;
import com.emailit.params.*;
EmailitClient emailit = new EmailitClient("your_api_key");

EmailitObject webhook = emailit.webhooks().create(
    WebhookCreateParams.builder()
        .setName("Production events")
        .setUrl("https://api.acme.com/webhooks/emailit")
        .setEvents(Arrays.asList("email.delivered"))
        .build()
);
```

**.NET**

```csharp
using Emailit;
var emailit = new EmailitClient("your_api_key");

var webhook = emailit.Webhooks.Create(new WebhookCreateOptions {
    Name = "Production events",
    Url = "https://api.acme.com/webhooks/emailit",
    Events = new[] { "email.delivered" }
});
```

**Laravel**

```php
use Emailit\Laravel\Facades\Emailit;

$webhook = Emailit::webhooks()->create([
    'name' => 'Production events',
    'url' => 'https://api.acme.com/webhooks/emailit',
    'events' => ['email.delivered']
]);
```

**cURL**

```bash
curl -X POST https://api.emailit.com/v2/webhooks \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production events",
    "url": "https://api.acme.com/webhooks/emailit",
    "events": ["email.delivered"]
  }'
```

**201**

```json
{
  "object": "webhook",
  "id": "wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e",
  "name": "Production events",
  "url": "https://api.acme.com/webhooks/emailit",
  "all_events": false,
  "enabled": true,
  "events": ["email.delivered", "email.bounced"],
  "filter": null,
  "filters_allowed": true,
  "last_used_at": null,
  "created_at": "2026-10-01T09:41:05.302000+00:00",
  "updated_at": "2026-10-01T09:41:05.302000+00:00",
  "secret": "whsec_175a02aca3fb7dc3107ca21e4224a73d058cacc628356a39e020422aec3ca434"
}
```

**400**

```json
{
  "error": "URL resolves to a private/reserved IP address"
}
```

**403**

```json
{
  "error": "plan_required",
  "required_plan": "pro"
}
```

**409**

```json
{
  "error": "Webhook with this name already exists",
  "existing": {
    "object": "webhook",
    "id": "wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e",
    "name": "Production events"
  }
}
```

**422**

```json
{
  "error": "Pay as you go includes 3 webhook endpoints.",
  "usage": {
    "used": 3,
    "limit": 3
  }
}
```

**Filtro**

```json
{
  "name": "Enterprise bounces",
  "url": "https://api.acme.com/webhooks/emailit",
  "events": ["email.bounced", "email.complained"],
  "filter": {
    "match": "all",
    "rules": [
      { "field": "meta.plan", "operator": "equals", "value": "enterprise" },
      { "field": "to", "operator": "not_contains", "value": "@acme.com" }
    ]
  }
}
```

---
Fuente: https://emailit.com/es/docs/api-reference/webhooks/create/

## Obtener un webhook — GET /webhooks/{id}

> Obtén un webhook por su ID o su nombre, con su URL, sus tipos de eventos, su filtro de payload y su secreto de firma.

# Obtener un webhook

Devuelve un webhook, buscado por su ID o por su nombre. Es el único endpoint de lectura que devuelve el `secret` de firma. Requiere una clave de API con el permiso `full`.

`GET /webhooks/:id`

## Parámetros de ruta

- `id` (string, obligatorio): El ID del webhook (`wh_…`) o su nombre, codificado para URL.

## Devuelve

Devuelve `200 OK` con el objeto de webhook, incluidos `secret` y `filters_allowed` (si tu plan permite que el webhook use un filtro de payload). `last_used_at` es la hora de la última entrega correcta, o `null` si todavía no se ha entregado nada.

Devuelve `404` con `error: "Webhook not found"` si ningún webhook coincide.

**Petición** `GET /webhooks/{id}`

**Node.js**

```javascript
import { Emailit } from '@emailit/node';
const emailit = new Emailit('your_api_key');

const webhook = await emailit.webhooks.get('wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e');
```

**Python**

```python
from emailit import EmailitClient
client = EmailitClient("your_api_key")

webhook = client.webhooks.get("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e")
```

**PHP**

```php
$emailit = Emailit::client('your_api_key');

$webhook = $emailit->webhooks()->get('wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e');
```

**Ruby**

```ruby
require "emailit"
client = Emailit::EmailitClient.new("your_api_key")

webhook = client.webhooks.get("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e")
```

**Go**

```go
import "github.com/emailit/emailit-go/v2"
client := emailit.NewClient("your_api_key")

webhook, err := client.Webhooks.Get("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e")
```

**Rust**

```rust
use emailit::Emailit;
let emailit = Emailit::new("your_api_key");

let webhook = emailit.webhooks.get("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e").await?;
```

**Java**

```java
import com.emailit.*;
EmailitClient emailit = new EmailitClient("your_api_key");

EmailitObject webhook = emailit.webhooks().get("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e");
```

**.NET**

```csharp
using Emailit;
var emailit = new EmailitClient("your_api_key");

var webhook = emailit.Webhooks.Get("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e");
```

**Laravel**

```php
use Emailit\Laravel\Facades\Emailit;

$webhook = Emailit::webhooks()->get('wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e');
```

**cURL**

```bash
curl https://api.emailit.com/v2/webhooks/wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e \
  -H "Authorization: Bearer your_api_key"
```

**200**

```json
{
  "object": "webhook",
  "id": "wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e",
  "name": "Production events",
  "url": "https://api.acme.com/webhooks/emailit",
  "all_events": false,
  "enabled": true,
  "events": ["email.delivered", "email.bounced"],
  "filter": {
    "match": "all",
    "rules": [
      { "field": "meta.plan", "operator": "equals", "value": "enterprise" }
    ]
  },
  "filters_allowed": true,
  "last_used_at": "2026-10-01T10:02:17.845000+00:00",
  "created_at": "2026-10-01T09:41:05.302000+00:00",
  "updated_at": "2026-10-01T09:41:05.302000+00:00",
  "secret": "whsec_175a02aca3fb7dc3107ca21e4224a73d058cacc628356a39e020422aec3ca434"
}
```

**404**

```json
{
  "error": "Webhook not found"
}
```

---
Fuente: https://emailit.com/es/docs/api-reference/webhooks/get/

## Actualizar un webhook — POST /webhooks/{id}

> Cambia el nombre, la URL, los tipos de eventos, el filtro de payload o el estado de activación de un webhook. Búscalo por su ID o por su nombre.

# Actualizar un webhook

Actualiza un webhook. Envía solo los campos que quieras cambiar; tienes que enviar al menos uno. El secreto de firma no cambia; para rotarlo, usa [Rotar el secreto de firma](/es/docs/api-reference/webhooks/reset-secret/). Requiere una clave de API con el permiso `full`.

`POST /webhooks/:id`

## Parámetros de ruta

- `id` (string, obligatorio): El ID del webhook (`wh_…`) o su nombre, codificado para URL.

## Cuerpo de la petición

- `name` (string): El nuevo nombre. Debe ser único en el espacio de trabajo.

- `url` (string): La nueva URL del endpoint, `http` o `https`. Se valida igual que al [crear](/es/docs/api-reference/webhooks/create/) el webhook.

- `all_events` (boolean): `true` envía todos los tipos de eventos y vacía la lista `events`. Si lo pones en `false`, envía también `events`; si no, el webhook no recibe nada.

- `enabled` (boolean): `false` detiene las entregas y `true` las reanuda. Los eventos que se producen mientras el webhook está desactivado no se ponen en cola para él ni se envían más tarde.

- `events` (string[]): Sustituye la lista de tipos de eventos. Se ignora mientras `all_events` sea `true`. Los nombres no se validan.

- `filter` (object | null): Sustituye el filtro de payload, con el mismo formato que al [crear](/es/docs/api-reference/webhooks/create/) el webhook. Envía `null` para quitarlo. Un filtro con reglas requiere un plan Pro, Business o Custom.

## Devuelve

Devuelve `200 OK` con el webhook actualizado. No incluye el `secret`; para leerlo, usa [Obtener un webhook](/es/docs/api-reference/webhooks/get/).

| Código | Cuándo |
| --- | --- |
| `400` | El cuerpo no incluye ninguno de los campos anteriores, o la URL o el filtro no son válidos. |
| `403` | El filtro tiene reglas y tu plan no incluye filtros de webhooks (`plan_required`). |
| `404` | Ningún webhook coincide con `id`. |
| `409` | Otro webhook ya usa el nuevo nombre. |

**Petición** `POST /webhooks/{id}`

**Node.js**

```javascript
import { Emailit } from '@emailit/node';
const emailit = new Emailit('your_api_key');

const webhook = await emailit.webhooks.update('wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e', {
    enabled: false
});
```

**Python**

```python
from emailit import EmailitClient
client = EmailitClient("your_api_key")

webhook = client.webhooks.update("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e", {
    "enabled": False
})
```

**PHP**

```php
$emailit = Emailit::client('your_api_key');

$webhook = $emailit->webhooks()->update('wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e', [
    'enabled' => false
]);
```

**Ruby**

```ruby
require "emailit"
client = Emailit::EmailitClient.new("your_api_key")

webhook = client.webhooks.update("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e", enabled: false)
```

**Go**

```go
import "github.com/emailit/emailit-go/v2"
client := emailit.NewClient("your_api_key")

webhook, err := client.Webhooks.Update("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e", &emailit.UpdateWebhookRequest{
    Enabled: false,
})
```

**Rust**

```rust
use emailit::Emailit;
let emailit = Emailit::new("your_api_key");

let webhook = emailit.webhooks.update("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e",
    emailit::types::UpdateWebhookParams {
        enabled: Some(false),
        ..Default::default()
    }
).await?;
```

**Java**

```java
import com.emailit.*;
import com.emailit.params.*;
EmailitClient emailit = new EmailitClient("your_api_key");

EmailitObject webhook = emailit.webhooks().update("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e",
    WebhookUpdateParams.builder()
        .setEnabled(false)
        .build()
);
```

**.NET**

```csharp
using Emailit;
var emailit = new EmailitClient("your_api_key");

var webhook = emailit.Webhooks.Update("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e", new WebhookUpdateOptions {
    Enabled = false
});
```

**Laravel**

```php
use Emailit\Laravel\Facades\Emailit;

$webhook = Emailit::webhooks()->update('wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e', [
    'enabled' => false
]);
```

**cURL**

```bash
curl -X POST https://api.emailit.com/v2/webhooks/wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"enabled": false}'
```

**200**

```json
{
  "object": "webhook",
  "id": "wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e",
  "name": "Production events",
  "url": "https://api.acme.com/webhooks/emailit",
  "all_events": false,
  "enabled": false,
  "events": ["email.delivered", "email.bounced"],
  "filter": null,
  "filters_allowed": true,
  "last_used_at": "2026-10-01T10:02:17.845000+00:00",
  "created_at": "2026-10-01T09:41:05.302000+00:00",
  "updated_at": "2026-10-01T10:15:40.000000+00:00"
}
```

**400**

```json
{
  "error": "No valid fields provided for update. Provide at least one of: name, url, all_events, enabled, events, filter"
}
```

**404**

```json
{
  "error": "Webhook not found"
}
```

**409**

```json
{
  "error": "Another webhook with this name already exists"
}
```

---
Fuente: https://emailit.com/es/docs/api-reference/webhooks/update/

## Listar webhooks — GET /webhooks

> Obtén los webhooks de tu espacio de trabajo con búsqueda, filtros y paginación por páginas, además del uso de webhooks de tu plan.

# Listar webhooks

Devuelve los webhooks de tu espacio de trabajo, del más reciente al más antiguo, y cuántos permite tu plan. El listado no incluye los secretos de firma. Requiere una clave de API con el permiso `full`.

`GET /webhooks`

## Parámetros de consulta

- `page` (integer): El número de página, empezando por `1`. Por defecto, `1`.

- `limit` (integer): Webhooks por página, de `1` a `100`. Por defecto, `10`.

- `search` (string): Búsqueda en el nombre o la URL del webhook, sin distinguir mayúsculas y minúsculas.

- `match`, `order`, `direction`: consulta [Filtrado](https://emailit.com/es/docs/api-reference/filtering/).

## Filtros y ordenación

Claves de filtro y de ordenación: consulta [Filtrado](https://emailit.com/es/docs/api-reference/filtering/).

## Devuelve

Devuelve `200 OK` con los webhooks en `data`, `next_page_url` y `previous_page_url` (`null` en los extremos) y un objeto `usage`: `used` es el número de webhooks del espacio de trabajo, `limit` es el máximo de tu plan y `filters_allowed` indica si tu plan incluye filtros de payload.

**Petición** `GET /webhooks`

**Node.js**

```javascript
import { Emailit } from '@emailit/node';
const emailit = new Emailit('your_api_key');

const webhooks = await emailit.webhooks.list();
```

**Python**

```python
from emailit import EmailitClient
client = EmailitClient("your_api_key")

webhooks = client.webhooks.list()
```

**PHP**

```php
$emailit = Emailit::client('your_api_key');

$webhooks = $emailit->webhooks()->list();
```

**Ruby**

```ruby
require "emailit"
client = Emailit::EmailitClient.new("your_api_key")

webhooks = client.webhooks.list
```

**Go**

```go
import "github.com/emailit/emailit-go/v2"
client := emailit.NewClient("your_api_key")

webhooks, err := client.Webhooks.List(nil)
```

**Rust**

```rust
use emailit::Emailit;
let emailit = Emailit::new("your_api_key");

let webhooks = emailit.webhooks.list(None).await?;
```

**Java**

```java
import com.emailit.*;
EmailitClient emailit = new EmailitClient("your_api_key");

EmailitObject webhooks = emailit.webhooks().list();
```

**.NET**

```csharp
using Emailit;
var emailit = new EmailitClient("your_api_key");

var webhooks = emailit.Webhooks.List();
```

**Laravel**

```php
use Emailit\Laravel\Facades\Emailit;

$webhooks = Emailit::webhooks()->list();
```

**cURL**

```bash
curl https://api.emailit.com/v2/webhooks \
  -H "Authorization: Bearer your_api_key"
```

**200**

```json
{
  "data": [
    {
      "object": "webhook",
      "id": "wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e",
      "name": "Production events",
      "url": "https://api.acme.com/webhooks/emailit",
      "all_events": false,
      "enabled": true,
      "events": ["email.delivered", "email.bounced"],
      "filter": null,
      "filters_allowed": true,
      "last_used_at": "2026-10-01T10:02:17.845000+00:00",
      "created_at": "2026-10-01T09:41:05.302000+00:00",
      "updated_at": "2026-10-01T10:02:17.845000+00:00"
    }
  ],
  "next_page_url": null,
  "previous_page_url": null,
  "usage": {
    "used": 1,
    "limit": 10,
    "filters_allowed": true
  }
}
```

**401**

```json
{
  "statusCode": 401,
  "error": "Unauthorized",
  "message": "Invalid API key"
}
```

---
Fuente: https://emailit.com/es/docs/api-reference/webhooks/list/

## Eliminar un webhook — DELETE /webhooks/{id}

> Elimina un webhook por su ID o su nombre. Emailit deja de enviar eventos a su URL, incluidos los reintentos pendientes.

# Eliminar un webhook

Elimina de forma permanente un webhook y sus suscripciones a eventos. Para detener las entregas temporalmente, [actualiza el webhook](/es/docs/api-reference/webhooks/update/) con `enabled: false` en lugar de eliminarlo. Requiere una clave de API con el permiso `full`.

`DELETE /webhooks/:id`

## Parámetros de ruta

- `id` (string, obligatorio): El ID del webhook (`wh_…`) o su nombre, codificado para URL.

## Devuelve

Devuelve `200 OK` con el `id` y el `name` del webhook eliminado y `deleted: true`. Devuelve `404` con `error: "Webhook not found"` si ningún webhook coincide.

**Petición** `DELETE /webhooks/{id}`

**Node.js**

```javascript
import { Emailit } from '@emailit/node';
const emailit = new Emailit('your_api_key');

await emailit.webhooks.delete('wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e');
```

**Python**

```python
from emailit import EmailitClient
client = EmailitClient("your_api_key")

client.webhooks.delete("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e")
```

**PHP**

```php
$emailit = Emailit::client('your_api_key');

$emailit->webhooks()->delete('wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e');
```

**Ruby**

```ruby
require "emailit"
client = Emailit::EmailitClient.new("your_api_key")

client.webhooks.delete("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e")
```

**Go**

```go
import "github.com/emailit/emailit-go/v2"
client := emailit.NewClient("your_api_key")

err := client.Webhooks.Delete("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e")
```

**Rust**

```rust
use emailit::Emailit;
let emailit = Emailit::new("your_api_key");

emailit.webhooks.delete("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e").await?;
```

**Java**

```java
import com.emailit.*;
EmailitClient emailit = new EmailitClient("your_api_key");

emailit.webhooks().delete("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e");
```

**.NET**

```csharp
using Emailit;
var emailit = new EmailitClient("your_api_key");

emailit.Webhooks.Delete("wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e");
```

**Laravel**

```php
use Emailit\Laravel\Facades\Emailit;

Emailit::webhooks()->delete('wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e');
```

**cURL**

```bash
curl -X DELETE https://api.emailit.com/v2/webhooks/wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e \
  -H "Authorization: Bearer your_api_key"
```

**200**

```json
{
  "object": "webhook",
  "id": "wh_2xLb3Kp9Qr1Vt7Mn5Ws0Yd4Hc8e",
  "name": "Production events",
  "deleted": true
}
```

**404**

```json
{
  "error": "Webhook not found"
}
```

---
Fuente: https://emailit.com/es/docs/api-reference/webhooks/delete/

## Enviar un evento de prueba — POST /webhooks/{id}/test

> Envía un evento de muestra firmado, de cualquier tipo, a un endpoint de webhook y recibe al instante la respuesta del endpoint.

# Enviar un evento de prueba

Envía un evento de muestra del tipo que elijas a la URL del webhook y devuelve la respuesta de tu endpoint. Úsalo para comprobar que tu endpoint es accesible y que verifica correctamente las [firmas](/es/docs/webhooks/request-signature/). Requiere una clave de API con el permiso `full`.

La petición tiene el mismo formato, las mismas cabeceras y la misma firma que una entrega real: un array JSON con un evento cuyo `event_id` empieza por `evt_test_`, firmado con el secreto actual del webhook. Se envía aunque el webhook esté desactivado o no esté suscrito a ese tipo, no se guarda como petición de webhook y no se reintenta. Los datos de muestra son fijos y no hacen referencia a objetos reales.

Puedes enviar 5 eventos de prueba por minuto desde la misma dirección IP; los que superen ese número devuelven `429`.

`POST /webhooks/{id}/test`

## Parámetros de ruta

- `id` (string, obligatorio): El ID del webhook (`wh_…`) o su nombre.

## Parámetros del cuerpo

- `type` (string, obligatorio): El tipo de evento que se envía. Uno de los tipos de la tabla siguiente.

| Recurso | Tipos de eventos |
| --- | --- |
| Email | `email.accepted`, `email.scheduled`, `email.delivered`, `email.bounced`, `email.attempted`, `email.failed`, `email.rejected`, `email.clicked`, `email.loaded`, `email.complained`, `email.received`, `email.suppressed`, `email.canceled`, `email.unsubscribed`, `email.resubscribed` |
| Dominio | `domain.created`, `domain.updated`, `domain.deleted` |
| Lista de contactos | `audience.created`, `audience.updated`, `audience.deleted` |
| Suscriptor | `subscriber.created`, `subscriber.updated`, `subscriber.deleted` |
| Contacto | `contact.created`, `contact.updated`, `contact.deleted` |
| Plantilla | `template.created`, `template.updated`, `template.deleted` |
| Dirección bloqueada | `suppression.created`, `suppression.updated`, `suppression.deleted` |
| Verificación de emails | `email_verification.created`, `email_verification.updated`, `email_verification_list.created`, `email_verification_list.updated` |
| Campaña | `campaign.created`, `campaign.updated`, `campaign.deleted`, `campaign.scheduled`, `campaign.queued`, `campaign.sending`, `campaign.testing`, `campaign.sent`, `campaign.canceled`, `campaign.archived` |

Para saber qué significa cada evento, consulta [Tipos de eventos](/es/docs/webhooks/event-types/).

## Devuelve

- `ok` (boolean): `true` si tu endpoint respondió con un estado 2xx.

- `status_code` (integer): El código de estado HTTP de tu endpoint. `0` si Emailit no pudo conectarse, si se agotó el tiempo de espera de la petición tras 30 segundos, si el endpoint redirigió (las redirecciones no se siguen) o si la URL apunta a una dirección no permitida.

- `body` (string): Los primeros 2000 caracteres de la respuesta de tu endpoint, o el error de conexión.

- `type` (string): El tipo de evento enviado.

- `payload` (object[]): El array JSON exacto que se envió.

Devuelve `400` si falta `type` o es desconocido, `404` si el webhook no existe y `429` si superas el límite de pruebas.

**Petición** `POST /webhooks/{id}/test`

**cURL**

```bash
curl -X POST https://api.emailit.com/v2/webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/test \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "type": "email.delivered" }'
```

**Node.js**

```javascript
const res = await fetch('https://api.emailit.com/v2/webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/test', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.EMAILIT_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ type: 'email.delivered' }),
});
const { ok, status_code, body } = await res.json();
```

**Python**

```python
import os, requests

r = requests.post(
    "https://api.emailit.com/v2/webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/test",
    headers={"Authorization": f"Bearer {os.environ['EMAILIT_API_KEY']}"},
    json={"type": "email.delivered"},
)
result = r.json()
```

**PHP**

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.emailit.com/v2/']);

$response = $client->post('webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/test', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('EMAILIT_API_KEY')],
    'json' => ['type' => 'email.delivered'],
]);
$result = json_decode($response->getBody(), true);
```

**200**

```json
{
  "ok": true,
  "status_code": 200,
  "type": "email.delivered",
  "payload": [
    {
      "event_id": "evt_test_3G0pUekgBm1uIxi9m4C380H70Zq",
      "type": "email.delivered",
      "object": {
        "id": "eml_test_001",
        "email_id": 12345,
        "message_id": "<test-token@mydomain.com>",
        "from": "sender@mydomain.com",
        "to": "recipient@example.com",
        "subject": "Test email",
        "status": "delivered",
        "delivered_at": "2026-01-15T10:30:00.000Z"
      },
      "data": {
        "object": {
          "id": "eml_test_001",
          "email_id": 12345,
          "message_id": "<test-token@mydomain.com>",
          "from": "sender@mydomain.com",
          "to": "recipient@example.com",
          "subject": "Test email",
          "status": "delivered",
          "delivered_at": "2026-01-15T10:30:00.000Z"
        }
      }
    }
  ],
  "body": "{\"received\":true}"
}
```

**400**

```json
{
  "error": "Unknown event type"
}
```

**429**

```json
{
  "statusCode": 429,
  "error": "Too Many Requests",
  "message": "Rate limit exceeded, retry in 1 minute"
}
```

---
Fuente: https://emailit.com/es/docs/api-reference/webhooks/test/

## Rotar el secreto de firma — POST /webhooks/{id}/reset-secret

> Sustituye el secreto de firma de un webhook. Todas las entregas posteriores a la rotación, incluidos los reintentos, se firman con el nuevo secreto.

# Rotar el secreto de firma

Genera un nuevo secreto de firma para el webhook y lo devuelve. Requiere una clave de API con el permiso `full`.

El secreto anterior deja de usarse de inmediato: todas las peticiones enviadas después de la rotación, incluidos los reintentos de eventos anteriores, se firman con el nuevo secreto. No hay periodo de solapamiento, así que actualiza el secreto en tu endpoint justo después de rotarlo, o acepta ambos secretos durante un breve periodo mientras haces el cambio. Consulta [Verificar las firmas de los webhooks](/es/docs/webhooks/request-signature/).

`POST /webhooks/{id}/reset-secret`

## Parámetros de ruta

- `id` (string, obligatorio): El ID del webhook (`wh_…`) o su nombre.

## Devuelve

Devuelve el objeto de webhook con el nuevo `secret` (`whsec_` seguido de 64 caracteres hexadecimales). Devuelve `404` si el webhook no existe.

**Petición** `POST /webhooks/{id}/reset-secret`

**cURL**

```bash
curl -X POST https://api.emailit.com/v2/webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/reset-secret \
  -H "Authorization: Bearer $EMAILIT_API_KEY"
```

**Node.js**

```javascript
const res = await fetch('https://api.emailit.com/v2/webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/reset-secret', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.EMAILIT_API_KEY}` },
});
const { secret } = await res.json();
```

**Python**

```python
import os, requests

r = requests.post(
    "https://api.emailit.com/v2/webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/reset-secret",
    headers={"Authorization": f"Bearer {os.environ['EMAILIT_API_KEY']}"},
)
secret = r.json()["secret"]
```

**PHP**

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.emailit.com/v2/']);

$response = $client->post('webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/reset-secret', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('EMAILIT_API_KEY')],
]);
$secret = json_decode($response->getBody(), true)['secret'];
```

**200**

```json
{
  "object": "webhook",
  "id": "wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ",
  "name": "Order notifications",
  "url": "https://acme.com/webhooks/emailit",
  "all_events": false,
  "enabled": true,
  "events": ["email.delivered", "email.bounced", "email.complained"],
  "filter": null,
  "last_used_at": "2026-10-01T12:58:40.000000+00:00",
  "created_at": "2026-08-14T09:12:03.000000+00:00",
  "updated_at": "2026-10-01T13:20:11.000000+00:00",
  "secret": "whsec_a0a593d006bdec5aff2f21e88afd543ba239431acbe7d8dc7a9723d76e0a64e2"
}
```

**404**

```json
{
  "error": "Webhook not found"
}
```

---
Fuente: https://emailit.com/es/docs/api-reference/webhooks/reset-secret/

## Reintentar peticiones fallidas — POST /webhooks/{id}/retry-failed

> Vuelve a poner en cola para su entrega todas las peticiones de webhook que fallaron de forma definitiva en los últimos 7 días y reactiva el webhook.

# Reintentar peticiones fallidas

Vuelve a poner en cola para su entrega todas las peticiones de este webhook que fallaron de forma definitiva en los últimos 7 días. Requiere una clave de API con el permiso `full`.

Una petición falla de forma definitiva tras su último reintento automático (11 intentos a lo largo de varios días; consulta [Reintentos y fallos](/es/docs/webhooks/retries-and-failures/)). Las peticiones reintentadas empiezan de nuevo con un calendario de reintentos completo y se entregan en cuestión de segundos. Si se pone en cola al menos una petición y el webhook estaba desactivado, por ejemplo tras 3 días de fallos continuos, se vuelve a activar.

Corrige primero tu endpoint o las peticiones volverán a fallar. Para reintentar una sola petición, usa [Reintentar una petición](/es/docs/api-reference/webhooks/retry-request/).

`POST /webhooks/{id}/retry-failed`

## Parámetros de ruta

- `id` (string, obligatorio): El ID del webhook (`wh_…`) o su nombre.

## Devuelve

- `retried` (integer): El número de peticiones que se han vuelto a poner en cola. `0` si no había nada que reintentar; en ese caso, el estado de activación del webhook no cambia.

Devuelve `404` si el webhook no existe.

**Petición** `POST /webhooks/{id}/retry-failed`

**cURL**

```bash
curl -X POST https://api.emailit.com/v2/webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/retry-failed \
  -H "Authorization: Bearer $EMAILIT_API_KEY"
```

**Node.js**

```javascript
const res = await fetch('https://api.emailit.com/v2/webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/retry-failed', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.EMAILIT_API_KEY}` },
});
const { retried } = await res.json();
```

**Python**

```python
import os, requests

r = requests.post(
    "https://api.emailit.com/v2/webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/retry-failed",
    headers={"Authorization": f"Bearer {os.environ['EMAILIT_API_KEY']}"},
)
retried = r.json()["retried"]
```

**PHP**

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.emailit.com/v2/']);

$response = $client->post('webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/retry-failed', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('EMAILIT_API_KEY')],
]);
$retried = json_decode($response->getBody(), true)['retried'];
```

**200**

```json
{
  "retried": 37
}
```

**404**

```json
{
  "error": "Webhook not found"
}
```

---
Fuente: https://emailit.com/es/docs/api-reference/webhooks/retry-failed/

## Reintentar una petición — POST /webhooks/{id}/requests/{request_id}/retry

> Vuelve a poner en cola para su entrega una sola petición de webhook que falló de forma definitiva y reactiva el webhook si estaba desactivado.

# Reintentar una petición

Vuelve a poner en cola para su entrega una petición de webhook que falló de forma definitiva, con un nuevo calendario de reintentos. Si el webhook estaba desactivado, se vuelve a activar. Requiere una clave de API con el permiso `full`.

Solo se pueden reintentar así las peticiones que han agotado sus reintentos automáticos; las que siguen pendientes o en reintento devuelven `400`. Encontrarás los ID de las peticiones (`whr_…`) en la pestaña **Requests** del webhook, en **Email API → Webhooks**. Para reintentar a la vez todo lo de los últimos 7 días, usa [Reintentar peticiones fallidas](/es/docs/api-reference/webhooks/retry-failed/).

`POST /webhooks/{id}/requests/{request_id}/retry`

## Parámetros de ruta

- `id` (string, obligatorio): El ID del webhook (`wh_…`) o su nombre.

- `request_id` (string, obligatorio): El ID de la petición de webhook (`whr_…`).

## Devuelve

- `retried` (integer): Siempre `1`.

- `id` (string): El ID de la petición que se ha puesto en cola.

| Código | Cuándo |
| --- | --- |
| `400` | La petición no ha fallado de forma definitiva o no tiene ningún evento que volver a enviar. |
| `404` | El webhook no existe o la petición no le pertenece. |

**Petición** `POST /webhooks/{id}/requests/{request_id}/retry`

**cURL**

```bash
curl -X POST https://api.emailit.com/v2/webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/requests/whr_3tWVVMd2eHv3R9B5DWTLtwwU05X/retry \
  -H "Authorization: Bearer $EMAILIT_API_KEY"
```

**Node.js**

```javascript
const res = await fetch(
  'https://api.emailit.com/v2/webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/requests/whr_3tWVVMd2eHv3R9B5DWTLtwwU05X/retry',
  { method: 'POST', headers: { Authorization: `Bearer ${process.env.EMAILIT_API_KEY}` } },
);
const result = await res.json();
```

**Python**

```python
import os, requests

r = requests.post(
    "https://api.emailit.com/v2/webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/requests/whr_3tWVVMd2eHv3R9B5DWTLtwwU05X/retry",
    headers={"Authorization": f"Bearer {os.environ['EMAILIT_API_KEY']}"},
)
result = r.json()
```

**PHP**

```php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.emailit.com/v2/']);

$response = $client->post('webhooks/wh_3NGa6raJ3s1VJ75lO9km6Dqg4cQ/requests/whr_3tWVVMd2eHv3R9B5DWTLtwwU05X/retry', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('EMAILIT_API_KEY')],
]);
$result = json_decode($response->getBody(), true);
```

**200**

```json
{
  "retried": 1,
  "id": "whr_3tWVVMd2eHv3R9B5DWTLtwwU05X"
}
```

**400**

```json
{
  "error": "Only permanently failed requests can be retried"
}
```

**404**

```json
{
  "error": "Webhook request not found"
}
```

---
Fuente: https://emailit.com/es/docs/api-reference/webhooks/retry-request/
