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).
| Campo | Valores |
|---|---|
default_subscription | opt_in: quien no eligió, recibe. opt_out: solo recibe quien eligió recibir. No cambia después de crearlo. |
visibility | public: aparece en la página de preferencias. private (predeterminado): solo tú lo gestionas, por la API o desde el panel. |
#Listar temas
GET/topics
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
limitintegerDe 1 a 100. Predeterminado: 20.afterstringCursor de la página siguiente.beforestringCursor de la página anterior.
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);
{
"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
Cuerpo de la solicitud
namestringobligatorioNombre, hasta 255 caracteres.default_subscriptionstringobligatorioopt_inuopt_out.descriptionstring | nullDescripción para el contacto, hasta 500 caracteres.visibilitystringpublicoprivate(predeterminado).
Errores
- 422
validation_errorAlgún campo no es válido. El mensaje indica cuál. - 403
plan_limit_reachedEl plan no permite más temas.
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);
{
"object": "topic",
"id": "019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b"
}
#Obtener un tema
GET/topics/{id}
Parámetros de ruta
idstringobligatorioID del tema.
Errores
- 404
not_foundEl recurso no existe o es de otro equipo.
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);
{
"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}
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
idstringobligatorioID del tema.
Cuerpo de la solicitud
namestringNombre nuevo.descriptionstring | nullNueva descripción.visibilitystringpublicoprivate.
Errores
- 422
validation_errorCampo no válido o intento de cambiardefault_subscription. - 403
paused_by_planEl tema está pausado porque supera el límite del plan. - 404
not_foundEl recurso no existe o es de otro equipo.
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);
{
"object": "topic",
"id": "019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b"
}
#Eliminar un tema
DELETE/topics/{id}
Elimina el tema y las elecciones de los contactos sobre él.
Parámetros de ruta
idstringobligatorioID del tema.
Errores
- 404
not_foundEl recurso no existe o es de otro equipo.
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);
{
"object": "topic",
"id": "019a1d95-4c5d-7e6f-8a7b-8c9d0e1f2a3b",
"deleted": true
}