Eventos
Publique eventos e entregue-os aos assinantes por webhook, consulta ou transmissão ao vivo, com mensagens mortas e reenvio.
Visão geral
Eventos permite que uma parte do seu sistema anuncie que algo aconteceu, e que cada parte interessada fique sabendo, sem que as duas se conheçam. Um publicador envia um evento como order.paid para https://events.inovacc.dev; toda assinatura cujo padrão corresponda ao tipo do evento o recebe, por webhook no seu endpoint HTTPS, por pull a partir do seu worker, ou por transmissão ao vivo por um WebSocket. Os eventos que não podem ser entregues são mantidos como mensagens mortas, que você pode inspecionar e reenviar.
O problema que ele resolve é a distribuição confiável. Chamar cada serviço interessado diretamente os acopla, perde mensagens quando um deles está fora do ar e faz novas tentativas de forma ruim. Eventos aceita a publicação uma vez, a entrega pelo menos uma vez a cada assinatura, repete as entregas que falharam com espera crescente, deduplica publicações repetidas e guarda o que não conseguiu entregar.
Use Eventos para reagir a mudanças: enviar um e-mail quando um pedido é pago, atualizar um cache quando um registro muda, enviar uma notificação a uma página. Mantenha o próprio estado em Dados e os bytes em Arquivos: um evento deve dizer o que aconteceu, não carregar o objeto. Para a história completa do receptor de webhooks, veja o guia de Webhooks.
Conceitos
Espaço de trabalho. Toda rota fica sob /v1/workspaces/{workspace}. O espaço de trabalho no caminho é uma declaração conferida contra a sua credencial: uma chave de aplicação só pode nomear o seu próprio espaço de trabalho, e qualquer outro responde 403 forbidden, igual a um que não existe.
Eventos e o envelope. Você publica type (palavras minúsculas separadas por pontos, como invoice.created, até 128 bytes), data (qualquer valor JSON) e uma idempotency_key opcional. Os assinantes recebem um envelope com event_id (evt_ e 26 caracteres, atribuído pela Inovacc), type, source (a sua aplicação, definida a partir da credencial), time, tenant, idempotency_key e data.
Níveis. Uma publicação pode nomear um tier: basic (o padrão), reliable ou advanced. O nível define o maior data que um evento pode carregar: 16 KiB para basic e reliable, 32 KiB para advanced.
Assinaturas e padrões. Uma assinatura lista de 1 a 20 padrões em types, cada um sendo * (tudo), um tipo exato ou um prefixo terminado em .* (order.* corresponde a order.paid e order.item.added), e um modo de entrega.
Modos de entrega. webhook envia cada evento por POST à sua URL HTTPS, assinado com o segredo da assinatura. pull mantém uma caixa de entrada que o seu código lê e confirma. websocket mantém a mesma caixa de entrada e também a transmite ao vivo; o pull continua funcionando ao lado da transmissão.
Pelo menos uma vez. Cada evento chega a cada assinatura correspondente uma vez em operação normal, mas uma nova tentativa ou uma confirmação perdida pode entregá-lo de novo. Os receptores deduplicam por event_id.
Mensagens mortas. Uma entrega por webhook que continua falhando é movida para as mensagens mortas do seu espaço de trabalho, com o último erro e o número de tentativas, e mantida por 30 dias.
Como funciona
Toda chamada leva Authorization: Bearer <credential>. A credencial é o tenant: organização, conta e aplicação vêm dela, e nada em um corpo pode nomear outra. Uma chave secreta é para servidores e pode usar todas as rotas. Uma chave publicável (apb_...) só pode abrir uma transmissão, a partir de uma origem que a sua aplicação lista. O token de um usuário final não pode usar nada. Cada rota exige a sua própria permissão, como events:event.publish, events:subscription.write ou events:dead.replay.
Publicar. POST /events com {"event": {...}} ou {"events": [...]} (de 1 a 100). A resposta é 202 com accepted (cada um com o seu event_id e duplicate) e rejected (cada um com um índice e um código); um evento inválido nunca bloqueia os outros. Enviar uma idempotency_key já usada no espaço de trabalho nas últimas 168 horas devolve o event_id original com duplicate: true e não entrega nada de novo.
Entrega por webhook. A Inovacc envia o envelope por POST à sua URL com x-event-id, x-event-type, x-event-timestamp e x-event-signature: v1=<hex>, um HMAC-SHA256 do carimbo de data e hora e do corpo bruto. Qualquer 2xx em até 10 segundos é uma entrega; qualquer outra coisa é repetida após 10 segundos, com o atraso dobrando até 10 minutos, até que o limite de 5 tentativas seja atingido e o evento se torne uma mensagem morta. Redirecionamentos nunca são seguidos, e a sua URL deve ser HTTPS pública na porta 443.
Pull. POST /subscriptions/{id}/pull com max (de 1 a 100, padrão 10) e lease_seconds (de 5 a 300, padrão 30) devolve as mensagens mais antigas, cada uma com o seu delivery_count. Uma mensagem obtida fica oculta durante o seu período de reserva; confirme-a com POST .../ack e os ids, ou ela volta quando a reserva termina.
Transmissão. GET /subscriptions/{id}/stream faz o upgrade para um WebSocket com o subprotocolo inovacc.v1; um navegador passa a sua chave como um segundo subprotocolo, bearer.<key>. Cada quadro é um envelope; responda {"ack": [...]} para confirmar. Um quadro não confirmado é enviado de novo após a sua reserva.
Monitoramento. GET /stats devolve published, completed, depth, oldest_pending_age_seconds, retries, retry_rate e dlq_inflow do espaço de trabalho. Toda chamada é registrada no Registro de atividade. O que é medido é o evento entregue.
Primeiros passos
Você precisa de uma chave secreta vinculada ao seu espaço de trabalho com as permissões de eventos (Autenticação).
- Crie uma assinatura pull.
POST /v1/workspaces/{workspace}/subscriptionscom{"types":["demo.*"],"delivery":{"mode":"pull"}}(veja os exemplos). A resposta é 201 com umsubscription_id. - Publique.
POST .../eventscom{"event":{"type":"demo.hello","data":{"n":1}}}. A resposta é 202 com uma entrada emacceptede o seuevent_id. - Faça o pull.
POST .../subscriptions/{id}/pullcom{}. O seu evento está emmessages, comdelivery_count1. - Confirme.
POST .../subscriptions/{id}/ackcom{"ids":["<event_id>"]}responde{"acked":1}; um segundo pull vem vazio. - Adicione um webhook. Crie uma segunda assinatura com
{"mode":"webhook","url":"https://<your endpoint>"}, guarde osigning_secretque a resposta mostra uma única vez e siga o guia de Webhooks para verificar as entregas.
Casos de uso
Atendimento de pedidos. O checkout publica order.paid com o id do pedido em data e o id do pagamento como idempotency_key. Uma assinatura por webhook para order.* chega ao sistema do depósito; uma assinatura pull alimenta a tarefa de faturamento. Um checkout repetido pelo cliente publica uma única vez.
Atualizações ao vivo em uma página. Um painel abre uma transmissão em uma assinatura websocket para ticket.* com uma chave publicável a partir da sua própria origem, mostra cada novo chamado à medida que o quadro chega e o confirma.
Recuperação após uma queda. O endpoint de um parceiro ficou fora do ar por uma hora. Suas entregas terminaram em mensagens mortas com last_error webhook_timeout. Quando ele volta, a sua equipe lista GET /dead e reenvia cada evento; ele vai apenas para as assinaturas que nunca o receberam.
Limites e preços
| Limite | Valor |
|---|---|
| Eventos por publicação | 100 |
| Corpo da requisição | 5 MiB |
data por evento | 16 KiB (basic, reliable), 32 KiB (advanced) |
Janela de deduplicação de idempotency_key | 168 horas |
| Assinaturas por espaço de trabalho; padrões por assinatura | 50; 20 |
| Mensagens por pull; reserva | 100; 5 a 300 segundos |
| Tempo de resposta do webhook | 10 segundos |
| Novas tentativas | a partir de 10 segundos, dobrando até 10 minutos; limite 5, depois mensagem morta |
| Mensagens mortas mantidas | 30 dias |
| Quadro de transmissão vindo do cliente | 49.152 bytes |
| Taxa | 600 chamadas por minuto por credencial, por localização |
Preços: sob consulta. A unidade de preço é o evento entregue.
Erros
| Status | Código | O que significa e o que fazer |
|---|---|---|
| 400 | invalid_body | O corpo está malformado, ou nomeia source (ele vem da sua credencial). |
| 400 | invalid_query | Apenas GET /dead aceita uma consulta (limit). |
| 400 | invalid_subscription, invalid_delivery, invalid_limit, invalid_id | Corrija a assinatura, a entrega ou o parâmetro. |
| 400 | invalid_url, url_not_https, url_has_credentials, url_port_not_allowed, url_destination_blocked | A URL do webhook deve ser HTTPS pública na porta 443, sem credenciais. |
| 401 | invalid_credentials | Envie uma credencial válida. |
| 403 | forbidden, account_required | Falta permissão ou o espaço de trabalho está errado; use uma chave de aplicação. |
| 403 | publishable_key_not_allowed, origin_not_allowed, secret_key_in_browser | Uma chave publicável só pode transmitir, a partir de uma origem listada; mantenha as chaves secretas em servidores. |
| 404 | subscription_not_found, dead_event_not_found | Não existe no seu espaço de trabalho. |
| 409 | wrong_delivery_mode, too_many_subscriptions, secret_not_managed | A operação não se encaixa no modo de entrega, ou você está em 50 assinaturas. |
| 413 | payload_too_large | O corpo excede 5 MiB. |
| 426 | upgrade_required | A rota de transmissão exige um upgrade para WebSocket. |
| 429 | rate_limited, too_many_streams | Diminua o ritmo; feche os sockets de que não precisa. |
| 503 | service_unavailable, events_disabled, signing_unavailable | Tente novamente mais tarde; uma publicação repetida com as mesmas chaves reutiliza seus ids. |
Um evento rejeitado dentro de um 202 traz o seu próprio código: invalid_event, unknown_field, invalid_type, invalid_idempotency_key, payload_too_large ou data_required.
Boas práticas
- Envie uma
idempotency_keyderivada do que aconteceu (o id do pagamento, a versão do registro), para que uma publicação repetida não seja um segundo evento. - Deduplique por
event_idem todo receptor: a entrega é de pelo menos uma vez. - Coloque ids em
data, não objetos: busque o estado atual em Dados quando tratar o evento. - Responda aos webhooks rapidamente com um
2xxe faça o trabalho depois; 10 segundos é o limite. - Verifique a assinatura de todo webhook antes de interpretar o corpo (guia de Webhooks).
- Confirme as mensagens obtidas por pull depois de processá-las, e escolha uma reserva maior que o seu tempo de processamento.
- Acompanhe
depthedlq_inflowem/stats, e reenvie as mensagens mortas depois que a causa for corrigida.
Relacionados
- Guia de Webhooks: receba, verifique e reenvie entregas
- Dados, Registro de atividade
- Autenticação, Erros, Limites
Autenticação
Toda chamada leva a sua chave; a sua organização vem dela. Veja o guia de autenticação.
AuthorizationEndpoints
POST /v1/workspaces/{workspace_id}/events
GET /v1/workspaces/{workspace_id}/subscriptions
POST /v1/workspaces/{workspace_id}/subscriptions
DELETE /v1/workspaces/{workspace_id}/subscriptions/{subscription_id}
POST /v1/workspaces/{workspace_id}/subscriptions/{subscription_id}/rotate-secret
POST /v1/workspaces/{workspace_id}/subscriptions/{subscription_id}/pull
POST /v1/workspaces/{workspace_id}/subscriptions/{subscription_id}/ack
GET /v1/workspaces/{workspace_id}/subscriptions/{subscription_id}/stream
GET /v1/workspaces/{workspace_id}/dead
POST /v1/workspaces/{workspace_id}/dead/{event_id}/replay
GET /v1/workspaces/{workspace_id}/stats
Exemplo
Linguagem
⋮
cURL
curl -X POST "https://events.inovacc.dev/v1/workspaces/{workspace_id}/events" \
-H "Authorization: Bearer $INOVACC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
}'curl -X POST "https://events.inovacc.dev/v1/workspaces/{workspace_id}/events" \
-H "Authorization: Bearer $INOVACC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
}'
TypeScript
const body: Record<string, unknown> = {
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
};
const url = "https://events.inovacc.dev/v1/workspaces/{workspace_id}/events";
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
console.log(response.status, await response.text());const body: Record<string, unknown> = {
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
};
const url = "https://events.inovacc.dev/v1/workspaces/{workspace_id}/events";
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
console.log(response.status, await response.text());
Python
import json
import os
import urllib.request
body = {
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42",
},
},
}
request = urllib.request.Request(
"https://events.inovacc.dev/v1/workspaces/{workspace_id}/events",
data=json.dumps(body).encode(),
method="POST",
headers={
"User-Agent": "inovacc-python-sample",
"Authorization": "Bearer " + os.environ["INOVACC_API_KEY"],
"Content-Type": "application/json",
},
)
with urllib.request.urlopen(request) as response:
print(response.status, response.read().decode())import json
import os
import urllib.request
body = {
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42",
},
},
}
request = urllib.request.Request(
"https://events.inovacc.dev/v1/workspaces/{workspace_id}/events",
data=json.dumps(body).encode(),
method="POST",
headers={
"User-Agent": "inovacc-python-sample",
"Authorization": "Bearer " + os.environ["INOVACC_API_KEY"],
"Content-Type": "application/json",
},
)
with urllib.request.urlopen(request) as response:
print(response.status, response.read().decode())
Go
package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
)
const url = "https://events.inovacc.dev/v1/workspaces/{workspace_id}/events"
const body = `{
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
}`
func main() {
req, err := http.NewRequest("POST", url, strings.NewReader(body))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("INOVACC_API_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
fmt.Println(res.Status, string(out))
}package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
)
const url = "https://events.inovacc.dev/v1/workspaces/{workspace_id}/events"
const body = `{
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
}`
func main() {
req, err := http.NewRequest("POST", url, strings.NewReader(body))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("INOVACC_API_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
fmt.Println(res.Status, string(out))
}
Rust
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }
// Cargo.toml: serde_json = "1"
fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = std::env::var("INOVACC_API_KEY")?;
let body = serde_json::json!({
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
});
let response = reqwest::blocking::Client::new()
.post("https://events.inovacc.dev/v1/workspaces/{workspace_id}/events")
.bearer_auth(api_key)
.json(&body)
.send()?;
println!("{} {}", response.status(), response.text()?);
Ok(())
}// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }
// Cargo.toml: serde_json = "1"
fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = std::env::var("INOVACC_API_KEY")?;
let body = serde_json::json!({
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
});
let response = reqwest::blocking::Client::new()
.post("https://events.inovacc.dev/v1/workspaces/{workspace_id}/events")
.bearer_auth(api_key)
.json(&body)
.send()?;
println!("{} {}", response.status(), response.text()?);
Ok(())
}
JavaScript
const body = {
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
};
const url = "https://events.inovacc.dev/v1/workspaces/{workspace_id}/events";
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
console.log(response.status, await response.text());const body = {
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
};
const url = "https://events.inovacc.dev/v1/workspaces/{workspace_id}/events";
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.INOVACC_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
console.log(response.status, await response.text());
PHP
<?php
$body = <<<'JSON'
{
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
}
JSON;
$curl = curl_init('https://events.inovacc.dev/v1/workspaces/{workspace_id}/events');
curl_setopt_array($curl, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('INOVACC_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($curl);
echo curl_getinfo($curl, CURLINFO_HTTP_CODE), ' ', $response, "\n";
curl_close($curl);<?php
$body = <<<'JSON'
{
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
}
JSON;
$curl = curl_init('https://events.inovacc.dev/v1/workspaces/{workspace_id}/events');
curl_setopt_array($curl, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('INOVACC_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($curl);
echo curl_getinfo($curl, CURLINFO_HTTP_CODE), ' ', $response, "\n";
curl_close($curl);
Ruby
require "net/http"
require "uri"
uri = URI('https://events.inovacc.dev/v1/workspaces/{workspace_id}/events')
body = <<~'JSON'
{
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
}
JSON
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch('INOVACC_API_KEY')}"
request["Content-Type"] = "application/json"
request.body = body
response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
http.request(request)
end
puts "#{response.code} #{response.body}"require "net/http"
require "uri"
uri = URI('https://events.inovacc.dev/v1/workspaces/{workspace_id}/events')
body = <<~'JSON'
{
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
}
JSON
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch('INOVACC_API_KEY')}"
request["Content-Type"] = "application/json"
request.body = body
response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
http.request(request)
end
puts "#{response.code} #{response.body}"
Java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("INOVACC_API_KEY");
String body = "{" +
"\"event\": {" +
"\"type\": \"order.paid\"," +
"\"idempotency_key\": \"pay_123\"," +
"\"data\": {" +
"\"order_id\": \"ord_42\"" +
"}" +
"}" +
"}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://events.inovacc.dev/v1/workspaces/{workspace_id}/events"))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
}
}import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("INOVACC_API_KEY");
String body = "{" +
"\"event\": {" +
"\"type\": \"order.paid\"," +
"\"idempotency_key\": \"pay_123\"," +
"\"data\": {" +
"\"order_id\": \"ord_42\"" +
"}" +
"}" +
"}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://events.inovacc.dev/v1/workspaces/{workspace_id}/events"))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
}
}
C#
using System.Text;
var body = "{" +
"\"event\": {" +
"\"type\": \"order.paid\"," +
"\"idempotency_key\": \"pay_123\"," +
"\"data\": {" +
"\"order_id\": \"ord_42\"" +
"}" +
"}" +
"}";
var url = "https://events.inovacc.dev/v1/workspaces/{workspace_id}/events";
var apiKey = Environment.GetEnvironmentVariable("INOVACC_API_KEY");
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.Add("Authorization", $"Bearer {apiKey}");
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
using var response = await client.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");using System.Text;
var body = "{" +
"\"event\": {" +
"\"type\": \"order.paid\"," +
"\"idempotency_key\": \"pay_123\"," +
"\"data\": {" +
"\"order_id\": \"ord_42\"" +
"}" +
"}" +
"}";
var url = "https://events.inovacc.dev/v1/workspaces/{workspace_id}/events";
var apiKey = Environment.GetEnvironmentVariable("INOVACC_API_KEY");
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.Add("Authorization", $"Bearer {apiKey}");
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
using var response = await client.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");
Kotlin
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
fun main() {
val apiKey = System.getenv("INOVACC_API_KEY")
val body = "{" +
"\"event\": {" +
"\"type\": \"order.paid\"," +
"\"idempotency_key\": \"pay_123\"," +
"\"data\": {" +
"\"order_id\": \"ord_42\"" +
"}" +
"}" +
"}"
val request = HttpRequest.newBuilder()
.uri(URI.create("https://events.inovacc.dev/v1/workspaces/{workspace_id}/events"))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(body))
.build()
val response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString())
println("${response.statusCode()} ${response.body()}")
}import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
fun main() {
val apiKey = System.getenv("INOVACC_API_KEY")
val body = "{" +
"\"event\": {" +
"\"type\": \"order.paid\"," +
"\"idempotency_key\": \"pay_123\"," +
"\"data\": {" +
"\"order_id\": \"ord_42\"" +
"}" +
"}" +
"}"
val request = HttpRequest.newBuilder()
.uri(URI.create("https://events.inovacc.dev/v1/workspaces/{workspace_id}/events"))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(body))
.build()
val response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString())
println("${response.statusCode()} ${response.body()}")
}
Swift
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
let body = #"""
{
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
}
"""#
let apiKey = ProcessInfo.processInfo.environment["INOVACC_API_KEY"] ?? ""
let url = URL(string: "https://events.inovacc.dev/v1/workspaces/{workspace_id}/events")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = Data(body.utf8)
let (data, response) = try await URLSession.shared.data(for: request)
let status = (response as? HTTPURLResponse)?.statusCode ?? 0
print(status, String(decoding: data, as: UTF8.self))import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
let body = #"""
{
"event": {
"type": "order.paid",
"idempotency_key": "pay_123",
"data": {
"order_id": "ord_42"
}
}
}
"""#
let apiKey = ProcessInfo.processInfo.environment["INOVACC_API_KEY"] ?? ""
let url = URL(string: "https://events.inovacc.dev/v1/workspaces/{workspace_id}/events")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = Data(body.utf8)
let (data, response) = try await URLSession.shared.data(for: request)
let status = (response as? HTTPURLResponse)?.statusCode ?? 0
print(status, String(decoding: data, as: UTF8.self))
Detalhes da fonte
- Id
- identity/component-taxonomy/capabilities#events
- Repositório
- identity
- Caminho
- contracts/component-taxonomy/catalog/capabilities.json
- Commit
- 08ef3cd75d82
- Id
- identity/component-taxonomy/quickstart#events
- Repositório
- identity
- Caminho
- contracts/component-taxonomy/catalog/capabilities.json
- Commit
- 08ef3cd75d82