Respawn Tech Dev

Notificações

Um agente avisa o seu humano por e-mail, webhook assinado ou ntfy, com canais, prioridade e histórico de envios.

Envie um aviso curto (título, mensagem e prioridade) para quem opera a conta: por e-mail, por um webhook assinado ou por um tópico do ntfy. Pensado para agentes de IA que terminam uma tarefa longa ou precisam de uma decisão, e também útil em qualquer automação.

Base path
/v1/tools/notify
Escopos
tools:notify:sendtools:notify:managetools:manage

Como funciona

Uma notificação tem title, message e priority (normal ou high), e opcionalmente uma url para o humano abrir. Ela sai por um canal:

  • Canal escolhido: o channel do pedido, pelo nome do canal.
  • Canal padrão: o canal marcado com is_default, quando o pedido não traz channel.
  • E-mail da conta: sem canal nenhum configurado, a notificação vai para o e-mail da conta.

Também está disponível no MCP como a tool notify (toolset notify): o agente avisa que terminou uma tarefa longa ou que precisa de uma decisão.

OperaçãoRota
Enviar notificaçãoPOST/
Histórico de enviosGET/messages
Listar canaisGET/channels
Criar canalPOST/channels
Consultar canalGET/channels/{id}
Alterar canalPATCH/channels/{id}
Excluir canalDELETE/channels/{id}
Testar canalPOST/channels/{id}/test

Canais

Cada canal tem um name único na conta e um kind:

kindCamposComo entrega
emailnenhumEnvia só para o e-mail da conta. Não é possível escolher outro destinatário.
webhookurl, secretFaz um POST na URL, assinado como no Webhook Relay.
ntfyserver, topicPublica no tópico do ntfy, no servidor informado.

is_default marca o canal usado quando o pedido não indica um, e enabled: false desativa o canal sem apagá-lo. O secret do webhook nunca volta nas respostas: guarde-o ao criar o canal.

O tópico do ntfy é a senha

Em servidores públicos do ntfy, quem souber o tópico lê as notificações. Use um nome longo e imprevisível, ou um servidor seu.

Limites, retry e histórico

  • Rate limit: há um limite de notificações por período; acima dele o envio falha com notify.rate_limited.
  • Retry do webhook: uma entrega que falha é tentada de novo algumas vezes antes de virar notify.delivery_failed. O receptor deve tratar repetições e conferir a assinatura.
  • Histórico: GET /messages lista os envios (canal, prioridade, status e data), paginado com page e page_size (até 100). O histórico não guarda o título nem o corpo da mensagem.

Custos

Cada envio pela API é cobrado conforme o valor indicado no endpoint. Canais e histórico são grátis, e a falha na entrega não é cobrada.

Endpoints

Enviar notificação

POST/v1/tools/notify
Custo
Franquia diária, depois 0,03 crédito/leitura via API
Dry-run
Suportado (X-Dry-Run: true)
Autenticação
qualquer um detools:notify:sendtools:manage

title e message são obrigatórios; priority é normal ou high; url e channel são opcionais. Sem channel, usa o canal padrão e, sem nenhum canal, o e-mail da conta.

curl -sS -X POST 'https://api.respawntech.dev/v1/tools/notify' \
  -H "X-API-Token: $RESPAWN_API_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "title": "Deploy concluído", "message": "A versão 2.4 está no ar.", "priority": "normal" }'
const response = await fetch('https://api.respawntech.dev/v1/tools/notify', {
  method: 'POST',
  headers: {
    'X-API-Token': process.env.RESPAWN_API_TOKEN,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ "title": "Deploy concluído", "message": "A versão 2.4 está no ar.", "priority": "normal" }),
});

if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());
import os
import requests

response = requests.post(
    "https://api.respawntech.dev/v1/tools/notify",
    headers={
        "X-API-Token": os.environ["RESPAWN_API_TOKEN"],
    },
    json={ "title": "Deploy concluído", "message": "A versão 2.4 está no ar.", "priority": "normal" },
    timeout=30,
)
if not response.ok:
    raise RuntimeError(response.json()["error"]["code"])
print(response.json())
<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/notify');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => [
        'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => <<<'JSON'
{ "title": "Deploy concluído", "message": "A versão 2.4 está no ar.", "priority": "normal" }
JSON,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));
package main

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

func main() {
	req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/notify", strings.NewReader(`{ "title": "Deploy concluído", "message": "A versão 2.4 está no ar.", "priority": "normal" }`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{Timeout: 30 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, err := io.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}
	if res.StatusCode >= 400 {
		panic(string(data))
	}
	fmt.Println(string(data))
}

Resposta 200

{
  "success": true,
  "trace_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "channel": "celular",
    "kind": "ntfy",
    "status": "delivered"
  }
}

Histórico de envios

GET/v1/tools/notify/messages
Custo
Grátis
Dry-run
Não
Autenticação
qualquer um detools:notify:managetools:manage

Paginado por page e page_size (até 100). Não traz o corpo das mensagens.

curl -sS -X GET 'https://api.respawntech.dev/v1/tools/notify/messages?page=1&page_size=20' \
  -H "X-API-Token: $RESPAWN_API_TOKEN"
const response = await fetch('https://api.respawntech.dev/v1/tools/notify/messages?page=1&page_size=20', {
  method: 'GET',
  headers: {
    'X-API-Token': process.env.RESPAWN_API_TOKEN,
  },
});

if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());
import os
import requests

response = requests.get(
    "https://api.respawntech.dev/v1/tools/notify/messages?page=1&page_size=20",
    headers={
        "X-API-Token": os.environ["RESPAWN_API_TOKEN"],
    },
    timeout=30,
)
if not response.ok:
    raise RuntimeError(response.json()["error"]["code"])
print(response.json())
<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/notify/messages?page=1&page_size=20');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => [
        'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
    ],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/notify/messages?page=1&page_size=20", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))

	client := &http.Client{Timeout: 30 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, err := io.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}
	if res.StatusCode >= 400 {
		panic(string(data))
	}
	fmt.Println(string(data))
}

Resposta 200

{
  "success": true,
  "trace_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "items": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "channel": "celular",
        "kind": "ntfy",
        "priority": "high",
        "status": "delivered",
        "created_at": "2026-10-06T12:00:00Z"
      }
    ],
    "page": 1,
    "page_size": 20,
    "total": 1
  }
}

Listar canais

GET/v1/tools/notify/channels
Custo
Grátis
Dry-run
Não
Autenticação
qualquer um detools:notify:managetools:manage
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/notify/channels' \
  -H "X-API-Token: $RESPAWN_API_TOKEN"
const response = await fetch('https://api.respawntech.dev/v1/tools/notify/channels', {
  method: 'GET',
  headers: {
    'X-API-Token': process.env.RESPAWN_API_TOKEN,
  },
});

if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());
import os
import requests

response = requests.get(
    "https://api.respawntech.dev/v1/tools/notify/channels",
    headers={
        "X-API-Token": os.environ["RESPAWN_API_TOKEN"],
    },
    timeout=30,
)
if not response.ok:
    raise RuntimeError(response.json()["error"]["code"])
print(response.json())
<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/notify/channels');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => [
        'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
    ],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/notify/channels", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))

	client := &http.Client{Timeout: 30 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, err := io.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}
	if res.StatusCode >= 400 {
		panic(string(data))
	}
	fmt.Println(string(data))
}

Resposta 200

{
  "success": true,
  "trace_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "items": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "celular",
        "kind": "ntfy",
        "server": "https://ntfy.sh",
        "topic": "meu-topico-secreto",
        "is_default": true,
        "enabled": true,
        "created_at": "2026-10-06T12:00:00Z"
      }
    ]
  }
}

Criar canal

POST/v1/tools/notify/channels
Custo
Grátis
Dry-run
Não
Autenticação
qualquer um detools:notify:managetools:manage

name e kind são obrigatórios. url e secret valem para webhook; server e topic, para ntfy. Campos que não combinam com o kind respondem notify.invalid_channel.

curl -sS -X POST 'https://api.respawntech.dev/v1/tools/notify/channels' \
  -H "X-API-Token: $RESPAWN_API_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "name": "celular", "kind": "ntfy", "server": "https://ntfy.sh", "topic": "meu-topico-secreto", "is_default": true }'
const response = await fetch('https://api.respawntech.dev/v1/tools/notify/channels', {
  method: 'POST',
  headers: {
    'X-API-Token': process.env.RESPAWN_API_TOKEN,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ "name": "celular", "kind": "ntfy", "server": "https://ntfy.sh", "topic": "meu-topico-secreto", "is_default": true }),
});

if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());
import os
import requests

response = requests.post(
    "https://api.respawntech.dev/v1/tools/notify/channels",
    headers={
        "X-API-Token": os.environ["RESPAWN_API_TOKEN"],
    },
    json={ "name": "celular", "kind": "ntfy", "server": "https://ntfy.sh", "topic": "meu-topico-secreto", "is_default": True },
    timeout=30,
)
if not response.ok:
    raise RuntimeError(response.json()["error"]["code"])
print(response.json())
<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/notify/channels');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => [
        'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => <<<'JSON'
{ "name": "celular", "kind": "ntfy", "server": "https://ntfy.sh", "topic": "meu-topico-secreto", "is_default": true }
JSON,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));
package main

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

func main() {
	req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/notify/channels", strings.NewReader(`{ "name": "celular", "kind": "ntfy", "server": "https://ntfy.sh", "topic": "meu-topico-secreto", "is_default": true }`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{Timeout: 30 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, err := io.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}
	if res.StatusCode >= 400 {
		panic(string(data))
	}
	fmt.Println(string(data))
}

Resposta 201

{
  "success": true,
  "trace_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "celular",
    "kind": "ntfy",
    "server": "https://ntfy.sh",
    "topic": "meu-topico-secreto",
    "is_default": true,
    "enabled": true,
    "created_at": "2026-10-06T12:00:00Z"
  }
}

Consultar canal

GET/v1/tools/notify/channels/{id}
Custo
Grátis
Dry-run
Não
Autenticação
qualquer um detools:notify:managetools:manage
curl -sS -X GET 'https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000' \
  -H "X-API-Token: $RESPAWN_API_TOKEN"
const response = await fetch('https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000', {
  method: 'GET',
  headers: {
    'X-API-Token': process.env.RESPAWN_API_TOKEN,
  },
});

if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());
import os
import requests

response = requests.get(
    "https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000",
    headers={
        "X-API-Token": os.environ["RESPAWN_API_TOKEN"],
    },
    timeout=30,
)
if not response.ok:
    raise RuntimeError(response.json()["error"]["code"])
print(response.json())
<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => [
        'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
    ],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))

	client := &http.Client{Timeout: 30 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, err := io.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}
	if res.StatusCode >= 400 {
		panic(string(data))
	}
	fmt.Println(string(data))
}

Resposta 200

{
  "success": true,
  "trace_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "celular",
    "kind": "ntfy",
    "server": "https://ntfy.sh",
    "topic": "meu-topico-secreto",
    "is_default": true,
    "enabled": true,
    "created_at": "2026-10-06T12:00:00Z"
  }
}

Alterar canal

PATCH/v1/tools/notify/channels/{id}
Custo
Grátis
Dry-run
Não
Autenticação
qualquer um detools:notify:managetools:manage

Envie só os campos que mudam. Um canal desativado responde notify.channel_disabled quando escolhido num envio.

curl -sS -X PATCH 'https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000' \
  -H "X-API-Token: $RESPAWN_API_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "enabled": false }'
const response = await fetch('https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000', {
  method: 'PATCH',
  headers: {
    'X-API-Token': process.env.RESPAWN_API_TOKEN,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ "enabled": false }),
});

if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());
import os
import requests

response = requests.patch(
    "https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000",
    headers={
        "X-API-Token": os.environ["RESPAWN_API_TOKEN"],
    },
    json={ "enabled": False },
    timeout=30,
)
if not response.ok:
    raise RuntimeError(response.json()["error"]["code"])
print(response.json())
<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_HTTPHEADER => [
        'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => <<<'JSON'
{ "enabled": false }
JSON,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));
package main

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

func main() {
	req, err := http.NewRequest("PATCH", "https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000", strings.NewReader(`{ "enabled": false }`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{Timeout: 30 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, err := io.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}
	if res.StatusCode >= 400 {
		panic(string(data))
	}
	fmt.Println(string(data))
}

Resposta 200

{
  "success": true,
  "trace_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "celular",
    "kind": "ntfy",
    "server": "https://ntfy.sh",
    "topic": "meu-topico-secreto",
    "is_default": true,
    "enabled": true,
    "created_at": "2026-10-06T12:00:00Z"
  }
}

Excluir canal

DELETE/v1/tools/notify/channels/{id}
Custo
Grátis
Dry-run
Não
Autenticação
qualquer um detools:notify:managetools:manage
curl -sS -X DELETE 'https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000' \
  -H "X-API-Token: $RESPAWN_API_TOKEN"
const response = await fetch('https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000', {
  method: 'DELETE',
  headers: {
    'X-API-Token': process.env.RESPAWN_API_TOKEN,
  },
});

if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());
import os
import requests

response = requests.delete(
    "https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000",
    headers={
        "X-API-Token": os.environ["RESPAWN_API_TOKEN"],
    },
    timeout=30,
)
if not response.ok:
    raise RuntimeError(response.json()["error"]["code"])
print(response.json())
<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_HTTPHEADER => [
        'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
    ],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)

func main() {
	req, err := http.NewRequest("DELETE", "https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))

	client := &http.Client{Timeout: 30 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, err := io.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}
	if res.StatusCode >= 400 {
		panic(string(data))
	}
	fmt.Println(string(data))
}

Resposta 200

{
  "success": true,
  "trace_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "deleted": true
  }
}

Testar canal

POST/v1/tools/notify/channels/{id}/test
Custo
Grátis
Dry-run
Não
Autenticação
qualquer um detools:notify:managetools:manage

Envia uma notificação de teste pelo canal, para conferir a configuração antes de depender dele.

curl -sS -X POST 'https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000/test' \
  -H "X-API-Token: $RESPAWN_API_TOKEN"
const response = await fetch('https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000/test', {
  method: 'POST',
  headers: {
    'X-API-Token': process.env.RESPAWN_API_TOKEN,
  },
});

if (!response.ok) throw new Error((await response.json()).error.code);
console.log(await response.json());
import os
import requests

response = requests.post(
    "https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000/test",
    headers={
        "X-API-Token": os.environ["RESPAWN_API_TOKEN"],
    },
    timeout=30,
)
if not response.ok:
    raise RuntimeError(response.json()["error"]["code"])
print(response.json())
<?php
$ch = curl_init('https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000/test');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => [
        'X-API-Token: ' . getenv('RESPAWN_API_TOKEN'),
    ],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    throw new RuntimeException(json_decode($body, true)['error']['code']);
}
print_r(json_decode($body, true));
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)

func main() {
	req, err := http.NewRequest("POST", "https://api.respawntech.dev/v1/tools/notify/channels/550e8400-e29b-41d4-a716-446655440000/test", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("X-API-Token", os.Getenv("RESPAWN_API_TOKEN"))

	client := &http.Client{Timeout: 30 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, err := io.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}
	if res.StatusCode >= 400 {
		panic(string(data))
	}
	fmt.Println(string(data))
}

Resposta 200

{
  "success": true,
  "trace_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "status": "delivered"
  }
}

Erros

CódigoHTTPQuando
notify.invalid_channel400Canal inválido: tipo desconhecido ou campos que não combinam com o tipo (URL do webhook, servidor e tópico do ntfy).
notify.channel_not_found404Canal inexistente ou de outra conta.
notify.channel_name_taken409Já existe um canal com esse nome na conta.
notify.channel_disabled409O canal escolhido está desativado.
notify.rate_limited429Limite de notificações por período excedido; tente de novo mais tarde.
notify.delivery_failed502Não foi possível entregar a notificação no canal (nada é cobrado).
notify.unavailable503O envio de notificações está indisponível no momento; tente de novo em alguns segundos.

Atualizado em