Idempotência
Repetir uma escrita sem duplicar o registro.
As regras
- Mande um valor único por operação (um UUID serve) no cabeçalho Idempotency-Key de todo POST.
- Repetir a mesma chave com o mesmo corpo não executa de novo: volta a resposta original, marcada com o cabeçalho de repetição.
- A mesma chave com corpo diferente recebe 409. Gere chave nova para cada operação nova.
- A mesma chave enquanto a primeira chamada ainda roda recebe 409 com Retry-After: 5.
- Resposta 5xx não congela a chave: repetir executa de novo.
No lote, a chave vale para a chamada inteira, não por item: para reenviar só os itens que falharam, use chave nova.
Cabeçalhos envolvidos
| Cabeçalho | Descrição |
|---|---|
Idempotency-Key | Você manda: um valor único por operação. |
Idempotency-Replayed | O Tenka devolve true quando a resposta é a repetição gravada. |
Warning · X-Api-Aviso | O Tenka devolve enquanto a chave não é obrigatória e você não a mandou. |
Obrigatória em escrita a partir de 2026-12-01
Até lá, a escrita sem a chave é aceita e a resposta traz os cabeçalhos Warning e X-Api-Aviso. Depois da data, é recusada com 400.
cURL
curl -X POST "https://tenka.app.br/api/v1/clientes" \
-H "Authorization: Bearer $TENKA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"nome": "Comercial Aurora Ltda",
"email": "contato@exemplo.com",
"cpfCnpj": "12.345.678/0001-00",
"telefone": "+55 11 99999-0000"
}'JavaScript
const response = await fetch("https://tenka.app.br/api/v1/clientes", {
method: "POST",
headers: {
"Authorization": "Bearer " + TENKA_API_KEY,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID()
},
body: JSON.stringify({
"nome": "Comercial Aurora Ltda",
"email": "contato@exemplo.com",
"cpfCnpj": "12.345.678/0001-00",
"telefone": "+55 11 99999-0000"
})
});
const data = await response.json();
if (!response.ok || data.erro) throw new Error(response.status + " " + data.erro);
console.log(data);Python
import os
import uuid
import requests
response = requests.post(
"https://tenka.app.br/api/v1/clientes",
headers={
"Authorization": f"Bearer {os.environ['TENKA_API_KEY']}",
"Content-Type": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"nome": "Comercial Aurora Ltda",
"email": "contato@exemplo.com",
"cpfCnpj": "12.345.678/0001-00",
"telefone": "+55 11 99999-0000"
},
timeout=30,
)
data = response.json()
if not response.ok or "erro" in data:
raise RuntimeError(f"{response.status_code} {data.get('erro')}")
print(data)Java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(URI.create("https://tenka.app.br/api/v1/clientes"))
.header("Authorization", "Bearer " + System.getenv("TENKA_API_KEY"))
.header("Content-Type", "application/json")
.header("Idempotency-Key", java.util.UUID.randomUUID().toString())
.POST(HttpRequest.BodyPublishers.ofString("""
{
"nome": "Comercial Aurora Ltda",
"email": "contato@exemplo.com",
"cpfCnpj": "12.345.678/0001-00",
"telefone": "+55 11 99999-0000"
}
"""))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());C#
using System.Net.Http.Headers;
using System.Text;
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("TENKA_API_KEY"));
var request = new HttpRequestMessage(HttpMethod.Post, "https://tenka.app.br/api/v1/clientes");
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent(@"{
""nome"": ""Comercial Aurora Ltda"",
""email"": ""contato@exemplo.com"",
""cpfCnpj"": ""12.345.678/0001-00"",
""telefone"": ""+55 11 99999-0000""
}", Encoding.UTF8, "application/json");
var response = await http.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");PHP
<?php
$ch = curl_init("https://tenka.app.br/api/v1/clientes");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("TENKA_API_KEY"),
"Content-Type: application/json",
"Idempotency-Key: " . bin2hex(random_bytes(16)),
],
CURLOPT_POSTFIELDS => '{
"nome": "Comercial Aurora Ltda",
"email": "contato@exemplo.com",
"cpfCnpj": "12.345.678/0001-00",
"telefone": "+55 11 99999-0000"
}',
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($body, true);
echo $status . " " . $body;Node (SDK)
// SDK gerado do contrato — baixe em https://tenka.app.br/api/v1/sdk/tenka.js
import { Tenka } from "./tenka.js";
const tenka = new Tenka(process.env.TENKA_API_KEY, "https://tenka.app.br/api/v1");
const data = await tenka.postClientes({}, {
"nome": "Comercial Aurora Ltda",
"email": "contato@exemplo.com",
"cpfCnpj": "12.345.678/0001-00",
"telefone": "+55 11 99999-0000"
}, crypto.randomUUID());
console.log(data);