Iniciar sesión Crear cuenta
Audiencia

Temas

Temas que el contacto elige recibir o no, con valor predeterminado opt-in u opt-out.

Los temas son los asuntos que el contacto elige recibir o no, como "Novedades" o "Encuestas". Aparecen en la página de preferencias que el contacto abre desde el enlace de baja. Para cada tema, cada contacto tiene su propia elección (opt_in u opt_out) o, si no eligió, el valor predeterminado del tema (default_subscription).

CampoValores
default_subscriptionopt_in: quien no eligió, recibe. opt_out: solo recibe quien eligió recibir. No cambia después de crearlo.
visibilitypublic: aparece en la página de preferencias. private (predeterminado): solo tú lo gestionas, por la API o desde el panel.

#Listar temas

GET/topics

Clave de acceso total

paused_by_plan es true cuando el plan dejó de admitir el tema (por ejemplo, tras un downgrade): sigue en la lista y se puede leer o eliminar, pero no se puede modificar (403 paused_by_plan).

Parámetros de consulta

  • limitinteger
    De 1 a 100. Predeterminado: 20.
  • afterstring
    Cursor de la página siguiente.
  • beforestring
    Cursor de la página anterior.
GET /topics

cURL

curl https://api.postal.so/topics \
  -H "Authorization: Bearer $POSTAL_API_KEY"

Node.js

const response = await fetch('https://api.postal.so/topics', {
  headers: {
    Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
  },
});

const data = await response.json();

Python

import os
import requests

response = requests.get(
    "https://api.postal.so/topics",
    headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
    timeout=10,
)

data = response.json()

PHP

$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);

$response = $client->get('topics', [
    'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
]);

$data = json_decode($response->getBody(), true);
200Respuesta
{
  "object": "list",
  "has_more": false,
  "data": [
    {
      "object": "topic",
      "id": "019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b",
      "paused_by_plan": false,
      "name": "Novidades",
      "description": "Lançamentos e promoções, uma vez por semana.",
      "default_subscription": "opt_in",
      "visibility": "public",
      "created_at": "2026-10-20T10:05:00.000000Z",
      "updated_at": "2026-10-20T10:05:00.000000Z"
    }
  ]
}

#Crear un tema

POST/topics

Clave de acceso total

Cuerpo de la solicitud

  • namestringobligatorio
    Nombre, hasta 255 caracteres.
  • default_subscriptionstringobligatorio
    opt_in u opt_out.
  • descriptionstring | null
    Descripción para el contacto, hasta 500 caracteres.
  • visibilitystring
    public o private (predeterminado).

Errores

  • 422validation_error
    Algún campo no es válido. El mensaje indica cuál.
  • 403plan_limit_reached
    El plan no permite más temas.
POST /topics

cURL

curl -X POST https://api.postal.so/topics \
  -H "Authorization: Bearer $POSTAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Novidades",
    "description": "Lançamentos e promoções, uma vez por semana.",
    "default_subscription": "opt_in",
    "visibility": "public"
  }'

Node.js

const response = await fetch('https://api.postal.so/topics', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Novidades',
    description: 'Lançamentos e promoções, uma vez por semana.',
    default_subscription: 'opt_in',
    visibility: 'public',
  }),
});

const data = await response.json();

Python

import os
import requests

response = requests.post(
    "https://api.postal.so/topics",
    headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
    json={
        "name": "Novidades",
        "description": "Lançamentos e promoções, uma vez por semana.",
        "default_subscription": "opt_in",
        "visibility": "public",
    },
    timeout=10,
)

data = response.json()

PHP

$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);

$response = $client->post('topics', [
    'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
    'json' => [
        'name' => 'Novidades',
        'description' => 'Lançamentos e promoções, uma vez por semana.',
        'default_subscription' => 'opt_in',
        'visibility' => 'public',
    ],
]);

$data = json_decode($response->getBody(), true);
201Respuesta
{
  "object": "topic",
  "id": "019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b"
}

#Obtener un tema

GET/topics/{id}

Clave de acceso total

Parámetros de ruta

  • idstringobligatorio
    ID del tema.

Errores

  • 404not_found
    El recurso no existe o es de otro equipo.
GET /topics/{id}

cURL

curl https://api.postal.so/topics/019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b \
  -H "Authorization: Bearer $POSTAL_API_KEY"

Node.js

const response = await fetch('https://api.postal.so/topics/019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b', {
  headers: {
    Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
  },
});

const data = await response.json();

Python

import os
import requests

response = requests.get(
    "https://api.postal.so/topics/019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b",
    headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
    timeout=10,
)

data = response.json()

PHP

$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);

$response = $client->get('topics/019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b', [
    'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
]);

$data = json_decode($response->getBody(), true);
200Respuesta
{
  "object": "topic",
  "id": "019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b",
  "paused_by_plan": false,
  "name": "Novidades",
  "description": "Lançamentos e promoções, uma vez por semana.",
  "default_subscription": "opt_in",
  "visibility": "public",
  "created_at": "2026-10-20T10:05:00.000000Z",
  "updated_at": "2026-10-20T10:05:00.000000Z"
}

#Actualizar un tema

PATCH/topics/{id}

Clave de acceso total

Cambia el nombre, la descripción o la visibilidad. default_subscription no se puede cambiar, porque los contactos sin elección ya siguen el valor actual.

Parámetros de ruta

  • idstringobligatorio
    ID del tema.

Cuerpo de la solicitud

  • namestring
    Nombre nuevo.
  • descriptionstring | null
    Nueva descripción.
  • visibilitystring
    public o private.

Errores

  • 422validation_error
    Campo no válido o intento de cambiar default_subscription.
  • 403paused_by_plan
    El tema está pausado porque supera el límite del plan.
  • 404not_found
    El recurso no existe o es de otro equipo.
PATCH /topics/{id}

cURL

curl -X PATCH https://api.postal.so/topics/019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b \
  -H "Authorization: Bearer $POSTAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "visibility": "private"
  }'

Node.js

const response = await fetch('https://api.postal.so/topics/019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    visibility: 'private',
  }),
});

const data = await response.json();

Python

import os
import requests

response = requests.patch(
    "https://api.postal.so/topics/019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b",
    headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
    json={
        "visibility": "private",
    },
    timeout=10,
)

data = response.json()

PHP

$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);

$response = $client->patch('topics/019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b', [
    'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
    'json' => [
        'visibility' => 'private',
    ],
]);

$data = json_decode($response->getBody(), true);
200Respuesta
{
  "object": "topic",
  "id": "019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b"
}

#Eliminar un tema

DELETE/topics/{id}

Clave de acceso total

Elimina el tema y las elecciones de los contactos sobre él.

Parámetros de ruta

  • idstringobligatorio
    ID del tema.

Errores

  • 404not_found
    El recurso no existe o es de otro equipo.
DELETE /topics/{id}

cURL

curl -X DELETE https://api.postal.so/topics/019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b \
  -H "Authorization: Bearer $POSTAL_API_KEY"

Node.js

const response = await fetch('https://api.postal.so/topics/019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
  },
});

const data = await response.json();

Python

import os
import requests

response = requests.delete(
    "https://api.postal.so/topics/019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b",
    headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
    timeout=10,
)

data = response.json()

PHP

$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);

$response = $client->delete('topics/019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b', [
    'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
]);

$data = json_decode($response->getBody(), true);
200Respuesta
{
  "object": "topic",
  "id": "019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b",
  "deleted": true
}