Rotas da v1
POSTRegistrar uma vendaPOSTCancelar uma vendaGETConsultar uma vendaGETLer o programa da lojaGETVer a saúde da conexãoRegistrar uma venda
Avisa o GIRO de uma venda do balcão. O GIRO aplica a regra do programa da loja e devolve o crédito e o bloco do GIRO pronto para o cupom, em texto e em imagem.
A API segue o Open Delivery onde o padrão cobre, e as rotas abaixo são extensões do GIRO. Veja o guia Open Delivery.
Envie o token da conexão no cabeçalho Authorization: Bearer. A loja vem do token. Erros voltam em application/problem+json, com o campo codigo.
Idempotency-KeycabeçalhoobrigatórioChave única do pedido, gerada pelo PDV. Repita a mesma chave ao reenviar o mesmo pedido.
external_idstringobrigatórioChave da venda no PDV. De 1 a 64 caracteres: letras, números, ponto, sublinhado, dois-pontos e hífen. É a chave de idempotência.
total_centsinteiroobrigatórioTotal da venda em centavos, maior que zero.
occurred_atdata e horaobrigatórioMomento da venda, com fuso horário (ISO 8601). Aceita até 7 dias para trás e até 5 minutos para a frente.
customer.phonestringopcionalTelefone do cliente em E.164. O selo entra na hora só se o cliente já aceitou o GIRO.
customer.documentstringopcionalCPF ou CNPJ do cliente, só dígitos.
itemslistaopcionalItens da venda.
receipt.formattextoopcionalFormato do bloco do GIRO: "image" (padrão e recomendado) ou "text". A resposta traz o formato pedido.
receipt.widthinteiroopcionalLargura do cupom em colunas: 32 (bobina de 58 mm), 42 ou 48 (80 mm). O padrão é 48. A imagem sai na mesma largura: 384, 512 ou 576 pontos.
receipt.charsettextoopcionalSó para receipt.format = "text". Caracteres que a impressora imprime: "ascii" (padrão) ou "unicode". Com "unicode", a barra de selos usa ● e ○; com "ascii", usa X e _.
Erros desta rota
| HTTP | Código | Mensagem da API | No caixa |
|---|---|---|---|
| 409 | PROGRAMA_NAO_CONFIGURADO | A loja não tem programa de selos configurado. | A loja ainda não configurou o programa de selos. A venda segue normal. |
| 409 | CHAVE_JA_PROCESSADA_COM_RESULTADO_DIFERENTE | Esta chave já foi processada com outro conteúdo. | Não mostrar. Registrar no log. |
| 409 | IDENTIFICADOR_EM_USO | O identificador da venda já está em uso na loja. | Não mostrar. Registrar no log. |
| 415 | TIPO_DE_CONTEUDO_INVALIDO | Envie o corpo como application/json. | Não mostrar. Registrar no log. |
| 422 | DADOS_INVALIDOS | Dados inválidos. | Não deu para registrar o selo desta venda. A venda segue normal. |
| 422 | VALOR_ACIMA_DO_TETO | O valor da venda passa do teto configurado pela loja. | Esta venda passa do limite da fidelidade da loja. A venda segue normal, sem selo. |
| 422 | VENDA_FORA_DA_TOLERANCIA | A data da venda está fora da tolerância de 7 dias. | Não mostrar. Registrar no log. |
| 401 | TOKEN_INVALIDO | Token ausente, inválido ou revogado. | A fidelidade está fora do ar nesta loja. A venda segue normal. |
| 403 | CONEXAO_DESLIGADA | A conexão está desligada para esta operação. | A fidelidade está desligada nesta loja. A venda segue normal. |
| 403 | CAPACIDADE_NAO_HOMOLOGADA | A capacidade não está homologada nesta conexão. | A fidelidade ainda não está liberada nesta loja. A venda segue normal. |
| 429 | LIMITE_EXCEDIDO | Limite de chamadas excedido. Tente de novo em instantes. | Não mostrar. Registrar no log. |
| 503 | CANAL_DESLIGADO | O canal de parceiros está desligado neste ambiente. | A fidelidade está fora do ar. A venda segue normal. |
curl -X POST "$GIRO_API/v1/sales" \
-H "Authorization: Bearer $GIRO_TOKEN" \
-H "Idempotency-Key: 6f1c2a90-3b7e-4d0a-9e51-8c2b4f7d1a33" \
-H "Content-Type: application/json" \
-d '{
"external_id": "venda-1042",
"total_cents": 4590,
"occurred_at": "2026-11-03T14:32:00-03:00",
"customer": { "phone": "+5511987654321" },
"receipt": { "format": "image", "width": 48 }
}'using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new("Bearer", Environment.GetEnvironmentVariable("GIRO_TOKEN"));
http.DefaultRequestHeaders.Add("Idempotency-Key", Guid.NewGuid().ToString());
var r = await http.PostAsJsonAsync(
Environment.GetEnvironmentVariable("GIRO_API") + "/v1/sales",
new {
external_id = "venda-1042",
total_cents = 4590,
occurred_at = "2026-11-03T14:32:00-03:00",
customer = new { phone = "+5511987654321" }
});const r = await fetch(`${process.env.GIRO_API}/v1/sales`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.GIRO_TOKEN}`,
"Idempotency-Key": crypto.randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify({
"external_id": "venda-1042",
"total_cents": 4590,
"occurred_at": "2026-11-03T14:32:00-03:00",
"customer": { "phone": "+5511987654321" }
}),
});
const venda = await r.json();import os, uuid, requests
r = requests.post(
os.environ["GIRO_API"] + "/v1/sales",
headers={
"Authorization": "Bearer " + os.environ["GIRO_TOKEN"],
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"external_id": "venda-1042",
"total_cents": 4590,
"occurred_at": "2026-11-03T14:32:00-03:00",
"customer": { "phone": "+5511987654321" }
},
)
venda = r.json()uses System.SysUtils, System.Classes, System.Net.HttpClient;
var
Http: THTTPClient;
Corpo: TStringStream;
Resp: IHTTPResponse;
begin
Http := THTTPClient.Create;
Corpo := TStringStream.Create('{"external_id":"venda-1042","total_cents":4590,"occurred_at":"2026-11-03T14:32:00-03:00","customer":{"phone":"+5511987654321"}}', TEncoding.UTF8);
try
Http.ContentType := 'application/json';
Http.CustomHeaders['Authorization'] := 'Bearer ' + GetEnvironmentVariable('GIRO_TOKEN');
Http.CustomHeaders['Idempotency-Key'] := TGUID.NewGuid.ToString;
Resp := Http.Post(GetEnvironmentVariable('GIRO_API') + '/v1/sales', Corpo);
Writeln(Resp.StatusCode, ' ', Resp.ContentAsString(TEncoding.UTF8));
finally
Corpo.Free;
Http.Free;
end;
end;var http = HttpClient.newHttpClient();
var req = HttpRequest.newBuilder(
URI.create(System.getenv("GIRO_API") + "/v1/sales"))
.header("Authorization", "Bearer " + System.getenv("GIRO_TOKEN"))
.header("Idempotency-Key", UUID.randomUUID().toString())
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("""
{
"external_id": "venda-1042",
"total_cents": 4590,
"occurred_at": "2026-11-03T14:32:00-03:00",
"customer": { "phone": "+5511987654321" }
}"""))
.build();
var resp = http.send(req, HttpResponse.BodyHandlers.ofString());{
"external_id": "venda-1042",
"status": "registrada",
"credit": {
"kind": "stamps",
"amount": 1,
"state": "efetivado"
},
"card": {
"stamps": 7,
"goal": 10,
"completed_now": false
},
"claim": null,
"receipt": {
"format": "image",
"width": 48,
"snapshot_at": "2026-02-10T17:32:00Z",
"image": "data:image/png;base64,iVBORw0KGgo..."
}
}{
"external_id": "venda-1043",
"status": "registrada",
"credit": {
"kind": "stamps",
"amount": 1,
"state": "pendente"
},
"card": null,
"claim": {
"code": "x7k9m2c3d4p",
"url": "https://giro.app.br/c/x7k9m2c3d4p",
"expires_at": "2026-11-10T17:32:01Z"
},
"receipt": {
"format": "image",
"width": 48,
"snapshot_at": "2026-02-10T17:32:00Z",
"image": "data:image/png;base64,iVBORw0KGgo...",
"qr": "https://giro.app.br/c/x7k9m2c3d4p",
"short_code": "x7k9m2c3d4p"
}
}{
"external_id": "venda-1045",
"status": "registrada",
"credit": {
"kind": "stamps",
"amount": 1,
"state": "efetivado"
},
"card": {
"stamps": 10,
"goal": 10,
"completed_now": true,
"completed_goal": true
},
"claim": null,
"receipt": {
"format": "image",
"width": 48,
"snapshot_at": "2026-02-10T17:32:00Z",
"image": "data:image/png;base64,iVBORw0KGgo..."
}
}{
"external_id": "venda-1042",
"replay": true,
"status": "registrada",
"credit": {
"kind": "stamps",
"amount": 1,
"state": "efetivado"
},
"card": {
"stamps": 7,
"goal": 10,
"completed_now": false
},
"receipt": {
"format": "image",
"width": 48,
"snapshot_at": "2026-02-10T17:32:00Z",
"image": "data:image/png;base64,iVBORw0KGgo..."
}
}{
"external_id": "venda-1044",
"status": "cancelada",
"credit": {
"kind": "stamps",
"amount": 0,
"state": "nenhum"
},
"card": null,
"claim": null,
"receipt": null
}Cancelar uma venda
Desfaz o crédito da venda. Se o cancelamento chega antes da venda, o GIRO guarda o cancelamento, e a venda que chega depois já nasce cancelada.
A API segue o Open Delivery onde o padrão cobre, e as rotas abaixo são extensões do GIRO. Veja o guia Open Delivery.
Envie o token da conexão no cabeçalho Authorization: Bearer. A loja vem do token. Erros voltam em application/problem+json, com o campo codigo.
Idempotency-KeycabeçalhoobrigatórioChave única do pedido, gerada pelo PDV. Repita a mesma chave ao reenviar o mesmo pedido.
external_idcaminhoobrigatórioA mesma chave usada no registro da venda.
Erros desta rota
| HTTP | Código | Mensagem da API | No caixa |
|---|---|---|---|
| 401 | TOKEN_INVALIDO | Token ausente, inválido ou revogado. | A fidelidade está fora do ar nesta loja. A venda segue normal. |
| 403 | CONEXAO_DESLIGADA | A conexão está desligada para esta operação. | A fidelidade está desligada nesta loja. A venda segue normal. |
| 403 | CAPACIDADE_NAO_HOMOLOGADA | A capacidade não está homologada nesta conexão. | A fidelidade ainda não está liberada nesta loja. A venda segue normal. |
| 429 | LIMITE_EXCEDIDO | Limite de chamadas excedido. Tente de novo em instantes. | Não mostrar. Registrar no log. |
| 503 | CANAL_DESLIGADO | O canal de parceiros está desligado neste ambiente. | A fidelidade está fora do ar. A venda segue normal. |
curl -X POST "$GIRO_API/v1/sales/venda-1042/cancel" \
-H "Authorization: Bearer $GIRO_TOKEN" \
-H "Idempotency-Key: 6f1c2a90-3b7e-4d0a-9e51-8c2b4f7d1a33"using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new("Bearer", Environment.GetEnvironmentVariable("GIRO_TOKEN"));
http.DefaultRequestHeaders.Add("Idempotency-Key", Guid.NewGuid().ToString());
var r = await http.PostAsync(
Environment.GetEnvironmentVariable("GIRO_API") + "/v1/sales/venda-1042/cancel", null);const r = await fetch(`${process.env.GIRO_API}/v1/sales/venda-1042/cancel`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.GIRO_TOKEN}`,
"Idempotency-Key": crypto.randomUUID(),
},
});
const dados = await r.json();import os, uuid, requests
r = requests.post(
os.environ["GIRO_API"] + "/v1/sales/venda-1042/cancel",
headers={
"Authorization": "Bearer " + os.environ["GIRO_TOKEN"],
"Idempotency-Key": str(uuid.uuid4()),
},
)
dados = r.json()uses System.SysUtils, System.Classes, System.Net.HttpClient;
var
Http: THTTPClient;
Corpo: TStringStream;
Resp: IHTTPResponse;
begin
Http := THTTPClient.Create;
Corpo := TStringStream.Create('', TEncoding.UTF8);
try
Http.CustomHeaders['Authorization'] := 'Bearer ' + GetEnvironmentVariable('GIRO_TOKEN');
Http.CustomHeaders['Idempotency-Key'] := TGUID.NewGuid.ToString;
Resp := Http.Post(GetEnvironmentVariable('GIRO_API') + '/v1/sales/venda-1042/cancel', Corpo);
Writeln(Resp.StatusCode, ' ', Resp.ContentAsString(TEncoding.UTF8));
finally
Corpo.Free;
Http.Free;
end;
end;var http = HttpClient.newHttpClient();
var req = HttpRequest.newBuilder(
URI.create(System.getenv("GIRO_API") + "/v1/sales/venda-1042/cancel"))
.header("Authorization", "Bearer " + System.getenv("GIRO_TOKEN"))
.header("Idempotency-Key", UUID.randomUUID().toString())
.POST(HttpRequest.BodyPublishers.noBody())
.build();
var resp = http.send(req, HttpResponse.BodyHandlers.ofString());{
"external_id": "venda-1042",
"status": "cancelada"
}Consultar uma venda
Mostra o estado da venda e do crédito. Use quando o PDV não recebeu a resposta do registro.
A API segue o Open Delivery onde o padrão cobre, e as rotas abaixo são extensões do GIRO. Veja o guia Open Delivery.
Envie o token da conexão no cabeçalho Authorization: Bearer. A loja vem do token. Erros voltam em application/problem+json, com o campo codigo.
external_idcaminhoobrigatórioA chave da venda no PDV.
Erros desta rota
| HTTP | Código | Mensagem da API | No caixa |
|---|---|---|---|
| 404 | VENDA_NAO_ENCONTRADA | Venda não encontrada. | Não mostrar. Registrar no log. |
| 401 | TOKEN_INVALIDO | Token ausente, inválido ou revogado. | A fidelidade está fora do ar nesta loja. A venda segue normal. |
| 403 | CONEXAO_DESLIGADA | A conexão está desligada para esta operação. | A fidelidade está desligada nesta loja. A venda segue normal. |
| 403 | CAPACIDADE_NAO_HOMOLOGADA | A capacidade não está homologada nesta conexão. | A fidelidade ainda não está liberada nesta loja. A venda segue normal. |
| 429 | LIMITE_EXCEDIDO | Limite de chamadas excedido. Tente de novo em instantes. | Não mostrar. Registrar no log. |
| 503 | CANAL_DESLIGADO | O canal de parceiros está desligado neste ambiente. | A fidelidade está fora do ar. A venda segue normal. |
curl "$GIRO_API/v1/sales/venda-1042" \
-H "Authorization: Bearer $GIRO_TOKEN"using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new("Bearer", Environment.GetEnvironmentVariable("GIRO_TOKEN"));
var r = await http.GetAsync(
Environment.GetEnvironmentVariable("GIRO_API") + "/v1/sales/venda-1042");const r = await fetch(`${process.env.GIRO_API}/v1/sales/venda-1042`, {
method: "GET",
headers: { Authorization: `Bearer ${process.env.GIRO_TOKEN}` },
});
const dados = await r.json();import os, requests
r = requests.get(
os.environ["GIRO_API"] + "/v1/sales/venda-1042",
headers={"Authorization": "Bearer " + os.environ["GIRO_TOKEN"]},
)
dados = r.json()uses System.SysUtils, System.Classes, System.Net.HttpClient;
var
Http: THTTPClient;
Corpo: TStringStream;
Resp: IHTTPResponse;
begin
Http := THTTPClient.Create;
Corpo := nil;
try
Http.CustomHeaders['Authorization'] := 'Bearer ' + GetEnvironmentVariable('GIRO_TOKEN');
Resp := Http.Get(GetEnvironmentVariable('GIRO_API') + '/v1/sales/venda-1042');
Writeln(Resp.StatusCode, ' ', Resp.ContentAsString(TEncoding.UTF8));
finally
Corpo.Free;
Http.Free;
end;
end;var http = HttpClient.newHttpClient();
var req = HttpRequest.newBuilder(
URI.create(System.getenv("GIRO_API") + "/v1/sales/venda-1042"))
.header("Authorization", "Bearer " + System.getenv("GIRO_TOKEN"))
.GET()
.build();
var resp = http.send(req, HttpResponse.BodyHandlers.ofString());{
"external_id": "venda-1043",
"status": "registrada",
"credit": {
"kind": "stamps",
"amount": 1,
"state": "pendente"
},
"claim_status": "pendente",
"registered_at": "2026-11-03T17:32:01Z"
}Ler o programa da loja
Devolve a regra do programa de selos da loja. Use para mostrar a regra no caixa. Leia de novo de tempos em tempos: a loja pode mudar a regra.
A API segue o Open Delivery onde o padrão cobre, e as rotas abaixo são extensões do GIRO. Veja o guia Open Delivery.
Envie o token da conexão no cabeçalho Authorization: Bearer. A loja vem do token. Erros voltam em application/problem+json, com o campo codigo.
Erros desta rota
| HTTP | Código | Mensagem da API | No caixa |
|---|---|---|---|
| 401 | TOKEN_INVALIDO | Token ausente, inválido ou revogado. | A fidelidade está fora do ar nesta loja. A venda segue normal. |
| 403 | CONEXAO_DESLIGADA | A conexão está desligada para esta operação. | A fidelidade está desligada nesta loja. A venda segue normal. |
| 403 | CAPACIDADE_NAO_HOMOLOGADA | A capacidade não está homologada nesta conexão. | A fidelidade ainda não está liberada nesta loja. A venda segue normal. |
| 429 | LIMITE_EXCEDIDO | Limite de chamadas excedido. Tente de novo em instantes. | Não mostrar. Registrar no log. |
| 503 | CANAL_DESLIGADO | O canal de parceiros está desligado neste ambiente. | A fidelidade está fora do ar. A venda segue normal. |
curl "$GIRO_API/v1/program" \
-H "Authorization: Bearer $GIRO_TOKEN"using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new("Bearer", Environment.GetEnvironmentVariable("GIRO_TOKEN"));
var r = await http.GetAsync(
Environment.GetEnvironmentVariable("GIRO_API") + "/v1/program");const r = await fetch(`${process.env.GIRO_API}/v1/program`, {
method: "GET",
headers: { Authorization: `Bearer ${process.env.GIRO_TOKEN}` },
});
const dados = await r.json();import os, requests
r = requests.get(
os.environ["GIRO_API"] + "/v1/program",
headers={"Authorization": "Bearer " + os.environ["GIRO_TOKEN"]},
)
dados = r.json()uses System.SysUtils, System.Classes, System.Net.HttpClient;
var
Http: THTTPClient;
Corpo: TStringStream;
Resp: IHTTPResponse;
begin
Http := THTTPClient.Create;
Corpo := nil;
try
Http.CustomHeaders['Authorization'] := 'Bearer ' + GetEnvironmentVariable('GIRO_TOKEN');
Resp := Http.Get(GetEnvironmentVariable('GIRO_API') + '/v1/program');
Writeln(Resp.StatusCode, ' ', Resp.ContentAsString(TEncoding.UTF8));
finally
Corpo.Free;
Http.Free;
end;
end;var http = HttpClient.newHttpClient();
var req = HttpRequest.newBuilder(
URI.create(System.getenv("GIRO_API") + "/v1/program"))
.header("Authorization", "Bearer " + System.getenv("GIRO_TOKEN"))
.GET()
.build();
var resp = http.send(req, HttpResponse.BodyHandlers.ofString());{
"public_code": "K3TB7QWX",
"configured": true,
"mode": "stamps",
"stamp_rule": "por_compra",
"min_purchase_cents": 2000,
"value_per_stamp_cents": null,
"goal": 10,
"reward_label": "1 café",
"max_sale_cents": 500000
}Ver a saúde da conexão
Mostra se a conexão está ligada, o ambiente, as capacidades homologadas e a última recusa. Use no diagnóstico do PDV.
A API segue o Open Delivery onde o padrão cobre, e as rotas abaixo são extensões do GIRO. Veja o guia Open Delivery.
Envie o token da conexão no cabeçalho Authorization: Bearer. A loja vem do token. Erros voltam em application/problem+json, com o campo codigo.
Erros desta rota
| HTTP | Código | Mensagem da API | No caixa |
|---|---|---|---|
| 401 | TOKEN_INVALIDO | Token ausente, inválido ou revogado. | A fidelidade está fora do ar nesta loja. A venda segue normal. |
| 403 | CONEXAO_DESLIGADA | A conexão está desligada para esta operação. | A fidelidade está desligada nesta loja. A venda segue normal. |
| 403 | CAPACIDADE_NAO_HOMOLOGADA | A capacidade não está homologada nesta conexão. | A fidelidade ainda não está liberada nesta loja. A venda segue normal. |
| 429 | LIMITE_EXCEDIDO | Limite de chamadas excedido. Tente de novo em instantes. | Não mostrar. Registrar no log. |
| 503 | CANAL_DESLIGADO | O canal de parceiros está desligado neste ambiente. | A fidelidade está fora do ar. A venda segue normal. |
curl "$GIRO_API/v1/connection" \
-H "Authorization: Bearer $GIRO_TOKEN"using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new("Bearer", Environment.GetEnvironmentVariable("GIRO_TOKEN"));
var r = await http.GetAsync(
Environment.GetEnvironmentVariable("GIRO_API") + "/v1/connection");const r = await fetch(`${process.env.GIRO_API}/v1/connection`, {
method: "GET",
headers: { Authorization: `Bearer ${process.env.GIRO_TOKEN}` },
});
const dados = await r.json();import os, requests
r = requests.get(
os.environ["GIRO_API"] + "/v1/connection",
headers={"Authorization": "Bearer " + os.environ["GIRO_TOKEN"]},
)
dados = r.json()uses System.SysUtils, System.Classes, System.Net.HttpClient;
var
Http: THTTPClient;
Corpo: TStringStream;
Resp: IHTTPResponse;
begin
Http := THTTPClient.Create;
Corpo := nil;
try
Http.CustomHeaders['Authorization'] := 'Bearer ' + GetEnvironmentVariable('GIRO_TOKEN');
Resp := Http.Get(GetEnvironmentVariable('GIRO_API') + '/v1/connection');
Writeln(Resp.StatusCode, ' ', Resp.ContentAsString(TEncoding.UTF8));
finally
Corpo.Free;
Http.Free;
end;
end;var http = HttpClient.newHttpClient();
var req = HttpRequest.newBuilder(
URI.create(System.getenv("GIRO_API") + "/v1/connection"))
.header("Authorization", "Bearer " + System.getenv("GIRO_TOKEN"))
.GET()
.build();
var resp = http.send(req, HttpResponse.BodyHandlers.ofString());{
"environment": "sandbox",
"enabled": true,
"capabilities": {
"registrar_venda": "em_homologacao"
},
"last_seen_at": "2026-11-03T17:32:01Z",
"last_rejected_code": null
}