Idempotency
Retry a write without duplicating the record.
The rules
- Send a unique value per operation (a UUID works) in the Idempotency-Key header of every POST.
- Repeating the same key with the same body does not run again: the original response comes back, flagged by the replay header.
- The same key with a different body gets 409. Generate a new key for each new operation.
- The same key while the first call is still running gets 409 with Retry-After: 5.
- A 5xx response does not freeze the key: retrying runs again.
In a batch the key covers the whole call, not each item: to resend only the failed items, use a new key.
Headers involved
| Header | Description |
|---|---|
Idempotency-Key | You send: one unique value per operation. |
Idempotency-Replayed | Tenka returns true when the response is the stored replay. |
Warning · X-Api-Aviso | Tenka returns it while the key is not mandatory and you did not send one. |
Mandatory on writes from 2026-12-01
Until then, writes without the key are accepted and the response carries the Warning and X-Api-Aviso headers. After that date, they are refused with 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 generated from the contract — download at 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);