Documentacao da API v1

Integre seu sistema com a API do Bridge Link para criar pedidos, consultar rastreamento e baixar etiquetas.

Inicio Rapido

Siga estes passos para comecar a usar a API do Bridge Link em poucos minutos.

Obtenha suas credenciais

Entre em contato com a equipe Bridge Link para receber seu client_id e client_secret.

Obtenha o token de acesso

Use o endpoint POST /api/v1/oauth/token para obter seu idToken (valido por 24h).

Faca sua primeira requisicao

Use o endpoint POST /api/v1/orders com o header Authorization: Bearer {token}.

Acompanhe o pedido

Consulte o status e baixe as etiquetas usando os endpoints de consulta.

Ambiente de Producao: A URL base da API e https://bridgelink.com.br/api/v1

Autenticacao (OAuth2)

A API utiliza autenticacao OAuth2 com Bearer Token. Primeiro obtenha um token de acesso, depois use-o em todas as requisicoes.

Passo 1: Obter Token de Acesso

POST /api/v1/oauth/token Obter token de acesso

Request

cURL
curl -X POST "https://bridgelink.com.br/api/v1/oauth/token" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "bl_seu_client_id",
    "client_secret": "seu_client_secret"
  }'

Response

JSON Response
{
  "idToken": "eyJhbGciOiJIUzI1NiJ9.eyJjbGllbnRfaWQi...",
  "expiresIn": "86400"
}

Passo 2: Usar o Token nas Requisicoes

Headers Obrigatorios

Authorization: Bearer {seu_idToken}
Content-Type: application/json

Token TTL: O token e valido por 24 horas (86400 segundos). Apos expirar, solicite um novo token.

Importante: Mantenha suas credenciais em seguranca. Nunca compartilhe ou exponha seu client_secret em codigo publico.

Exemplo de Requisicao Autenticada

cURL
curl -X GET "https://bridgelink.com.br/api/v1/orders/ATN12345" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
  -H "Content-Type: application/json"

Parceiro / Agregador (Multi-Cliente)

Esta secao descreve a superficie de consumo multi-cliente usada por um parceiro/agregador. Clientes single-customer (um token = um cliente) nao precisam dela — seu token continua escopado ao seu unico cliente, exatamente como antes. Nada aqui altera o comportamento dos endpoints ja documentados.

Um token de parceiro le atraves de uma allowlist explicita de clientes (configurada pelo administrador). Com ele voce pode:

Escopo e isolamento: o escopo parte sempre da allowlist do token — nunca de um id arbitrario que voce envie. Um customer_id (ou um :id de cliente) fora da allowlist (ou um UUID fabricado) retorna o mesmo 404 / codigo 5 que um recurso inexistente, sem qualquer sinal de enumeracao (nao existe um 403 "existe-mas-proibido" que revele a existencia de outro cliente).

A emissao de credenciais (criar o token de parceiro e definir a allowlist) e uma acao administrativa — nao e uma chamada de API. Voce consome sua credencial; nao a emite.

Exemplo cURL

cURL
# Listar os clientes que o seu token de parceiro pode ler
curl -X GET "https://bridgelink.com.br/api/v1/customers?per_page=50" \
  -H "Authorization: Bearer SEU_TOKEN"

# Puxar os pedidos de um cliente especifico da allowlist
curl -X GET "https://bridgelink.com.br/api/v1/orders?customer_id=550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer SEU_TOKEN"

Os endpoints GET /customers, GET /customers/:id e o filtro customer_id estao detalhados nas secoes "Listar Clientes", "Consultar Cliente" e "Listar Pedidos" abaixo.

Criar Pedido

Crie um novo pedido/HAWB no sistema. O pedido sera processado e enviado para a transportadora automaticamente.

POST /api/v1/orders Cria um novo pedido

Parametros do Request

Parametro Tipo Descricao
shipTo* object Dados do destinatario (name, phone, federalTaxId, address)
shipTo.address.correios* object Endereco no formato Correios (logradouro, numero, bairro, cep, cidade, uf)
packages* array Lista de pacotes com peso e nota fiscal
packages[].weightG(opcional) number Peso do pacote em gramas
packages[].documentTypes.invoice(opcional) object Dados da nota fiscal (key, number, totalValue)
contractId(opcional) UUID UUID de um contrato (loja/remetente) do seu proprio cliente (nivel raiz do payload). Carimba o pedido criado com aquele contrato. Aditivo: se ausente, a criacao e byte-identica a atual (ORDER-05) — nenhuma chave nova entra no payload nem na resposta. Um contractId malformado ou de outro tenant retorna 404 / codigo 5 byte-identico ao recurso inexistente (sem sinal de enumeracao, nunca um 403), antes da criacao. O id aceito e o UUID do contrato Bridge Link — nunca o client_id/contract_id nativo da Flash.

Exemplo de Request

JSON
{
  "shipTo": {
    "name": "Joao da Silva",
    "phone": "21988887777",
    "federalTaxId": "12345678901",
    "address": {
      "correios": {
        "logradouro": "Av. Atlantica",
        "numero": "500",
        "complemento": "Apto 1001",
        "bairro": "Copacabana",
        "cep": "22010000",
        "cidade": "Rio de Janeiro",
        "uf": "RJ"
      }
    }
  },
  "packages": [
    {
      "weightG": 1500,
      "documentTypes": {
        "invoice": {
          "key": "35240612345678000195550010000001011234567890",
          "number": "12345",
          "totalValue": 299.90
        }
      }
    }
  ]
}

Resposta de Sucesso

201 Created
JSON Response
{
  "packages": [
    {
      "trackingCode": "ATN123456789",
      "loggiKey": "bf7a1c2d-3e4f-5678-9abc-def012345678",
      "status": {
        "code": 2,
        "highLevelStatus": "IMPORTADO",
        "description": "Pedido importado na transportadora",
        "updatedTime": "2025-01-16T10:30:00Z"
      },
      "labelUrl": "https://bridgelink.com.br/api/v1/labels/ATN123456789",
      "flashLabelUrl": "https://webservice.flashpegasus.com.br/..."
    }
  ]
}

Exemplo cURL Completo

cURL
curl -X POST "https://bridgelink.com.br/api/v1/orders" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "shipTo": {
      "name": "Joao da Silva",
      "phone": "21988887777",
      "federalTaxId": "12345678901",
      "address": {
        "correios": {
          "logradouro": "Av. Atlantica",
          "numero": "500",
          "bairro": "Copacabana",
          "cep": "22010000",
          "cidade": "Rio de Janeiro",
          "uf": "RJ"
        }
      }
    },
    "packages": [
      {
        "weightG": 1500,
        "documentTypes": {
          "invoice": {
            "key": "35240612345678000195550010000001011234567890",
            "number": "12345",
            "totalValue": 299.90
          }
        }
      }
    ]
  }'

Respostas de Erro

O POST /orders retorna dois formatos distintos de erro 422, ambos com codigo Loggi 9. Um cliente/SDK deve tratar os dois casos.

(a) Falha de credenciais/configuracao — o cliente nao tem credenciais da transportadora (Jall/Flash Courier) configuradas. O campo details vem vazio:

422 Unprocessable Entity
JSON Response
{
  "code": 9,
  "message": "Customer does not have Jall/Flash Courier credentials configured",
  "details": []
}

(b) Falha de validacao do payload — o payload esta malformado ou faltam campos obrigatorios. A message e "Invalid payload" e details traz a lista de campos invalidos no formato fieldViolations (mesmo formato descrito na secao Formato de Resposta de Erro): details.fieldViolations[].field nomeia o campo ausente/invalido e description e a mensagem legivel:

422 Unprocessable Entity
JSON Response
{
  "code": 9,
  "message": "Invalid payload",
  "details": [
    {
      "@type": "type.googleapis.com/google.rpc.BadRequest",
      "fieldViolations": [
        { "field": "shipTo", "description": "shipTo is required" }
      ]
    }
  ]
}

Listar Pedidos

Retorna uma lista paginada e filtravel dos pedidos do proprio cliente, no envelope data + meta. A listagem e sempre escopada ao cliente do token — nunca expoe pedidos de outro cliente.

GET /api/v1/orders Lista pedidos (paginada + filtros)

Parametros de Query (todos opcionais)

Parametro Tipo Descricao
page(opcional) inteiro Pagina desejada (default: 1)
per_page(opcional) inteiro Itens por pagina (default: 50, maximo: 100 — valores acima sao limitados a 100)
status(opcional) string Chave do enum de status: erro, integrado, importado, rastreado, aguardando_nf, aguardando_centro_custo
source(opcional) string Chave do enum de origem do pedido
order_number(opcional) string Filtro exato pelo numero do pedido
invoice_number(opcional) string Filtro exato pelo numero da nota fiscal
tracking(opcional) string Filtro exato pelo codigo de rastreio
customer_id(opcional) UUID (Parceiro) Estreita a busca a um unico cliente dentro da allowlist do token. Um valor fora da allowlist (ou fabricado) retorna 404 / codigo 5 — nunca e silenciosamente ignorado nem amplia o escopo.
contract_id(opcional) UUID Estreita a busca aos pedidos de um contrato (loja/remetente) dentro do escopo do token. Aditivo: ausente nao altera a lista. Um valor fora do escopo (ou um UUID fabricado) retorna 404 / codigo 5 — byte-identico ao recurso inexistente, sem sinal de enumeracao. Um valor malformado (nao-UUID) falha alto em 400 / codigo 9 (campo contract_id).
created_from(opcional) ISO-8601 Data/hora inicial (inclusiva, fuso America/Sao_Paulo)
created_to(opcional) ISO-8601 Data/hora final (inclusiva, fuso America/Sao_Paulo)
created_after(opcional) ISO-8601 Alias de created_from (limite inferior inclusivo). Quando ambos sao enviados, o nome novo prevalece; a coluna e filtrada uma unica vez.
created_before(opcional) ISO-8601 Alias de created_to (limite superior inclusivo). Quando ambos sao enviados, o nome novo prevalece; a coluna e filtrada uma unica vez.
include_consumed(opcional) booleano Quando true, inclui na lista os pedidos ja consumidos (acknowledged). Por padrao a lista exclui os consumidos (pull-dedup).

Um valor de enum invalido ou uma data malformada retorna 400 / codigo 9 (fail-loud), com o campo ofensor em details.fieldViolations. Parametros desconhecidos sao ignorados.

Resposta de Sucesso

200 OK
JSON Response
{
  "data": [
    {
      "trackingCode": "ATN12345",
      "status": {
        "code": 2,
        "highLevelStatus": "IMPORTADO",
        "description": "Pedido importado na transportadora",
        "updatedTime": "2024-12-17T10:30:00Z"
      },
      "orderNumber": "PED-001",
      "invoiceNumber": "NF-001",
      "source": "api",
      "createdAt": "2024-12-17T10:30:00Z",
      "customer": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "ATN Contact",
        "cnpj": "12345678000190"
      },
      "contract": {
        "id": "9c8b7a65-4d3e-2f1a-0b9c-8d7e6f5a4b3c",
        "code": "LOJA-SP",
        "name": "Loja Sao Paulo LTDA"
      }
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 50,
    "total": 137,
    "total_pages": 3
  }
}

O bloco customer ({ id, name, cnpj }) e sempre presente na linha de lista e no detalhe — e apenas a identidade do cliente dono do pedido (nunca transportadora, plataforma ou credenciais). O id e o UUID do cliente e faz round-trip no filtro customer_id; o cnpj e apenas digitos. Os campos weight/value/itemsQuantity/obs/consumedAt ficam apenas no detalhe (GET /orders/:id).

O bloco contract ({ id, code, name }) e aditivo e condicional: aparece na linha de lista e no detalhe apenas quando o pedido tem contrato (omitido caso contrario — um pedido sem contrato fica byte-identico). O id e o UUID do contrato — a chave de enderecamento publica que faz round-trip no filtro contract_id e no contractId de criacao (os identificadores Flash nativos clientId/contractId da jallConnection seguem internos da transportadora). Fronteira de nao-vazamento: o bloco nunca carrega carrier_token, flash_client_id nem flash_contract_id.

Sobre o objeto status: aplica-se a mesma limitacao conhecida documentada na secao "Consultar Pedido" (o code: 0 de fallback vale igualmente aqui). Use o highLevelStatus como fonte de verdade.

Exemplo cURL

cURL
curl -X GET "https://bridgelink.com.br/api/v1/orders?status=integrado&page=1&per_page=50" \
  -H "Authorization: Bearer SEU_TOKEN"

Consultar Pedido

Consulte os detalhes de um pedido existente. O segmento :id aceita o UUID do pedido OU o codigo de rastreio — um valor no formato UUID estrito (8-4-4-4-12) resolve por id; qualquer outro valor cai na busca por codigo de rastreio.

GET /api/v1/orders/:id Consulta detalhes do pedido (UUID ou rastreio)

Parametros da URL

Parametro Tipo Descricao
id* string UUID do pedido OU codigo de rastreamento (ex: ATN123456789). Um valor no formato UUID estrito resolve por id; qualquer outro valor resolve por codigo de rastreio.

Resposta de Sucesso

200 OK
JSON Response
{
  "packages": [
    {
      "trackingCode": "ATN12345",
      "loggiKey": "550e8400-e29b-41d4-a716-446655440000",
      "status": {
        "code": 2,
        "highLevelStatus": "IMPORTADO",
        "description": "Pedido importado na transportadora",
        "updatedTime": "2024-12-17T10:30:00Z"
      },
      "destination": {
        "recipient": {
          "name": "Joao da Silva",
          "phone": "11999998888",
          "federalTaxId": "12345678901"
        },
        "postalAddress": {
          "postalCode": "01234567",
          "administrativeArea": "SP",
          "addressLines": [
            "Rua das Flores, 123",
            "Apto 101",
            "Centro",
            "Sao Paulo"
          ]
        }
      },
      "invoice": {
        "number": "NF-001",
        "key": "35240612345678901234550010000000011000000001",
        "series": "1",
        "date": "2024-12-15"
      },
      "labelUrl": "https://bridgelink.com.br/api/v1/labels/ATN12345",
      "flashLabelUrl": "https://webservice.flashpegasus.com.br/FlashPegasus/rest/padrao/etiqueta/HAWB12345.pdf",
      "costCenter": {
        "code": "CC01",
        "name": "Centro de Custo SP"
      },
      "contract": {
        "id": "9c8b7a65-4d3e-2f1a-0b9c-8d7e6f5a4b3c",
        "code": "LOJA-SP",
        "name": "Loja Sao Paulo LTDA"
      },
      "receiptUrl": "https://bridgelink.com.br/api/v1/delivery_receipts/ATN12345",
      "createdAt": "2024-12-17T10:30:00Z",
      "updatedAt": "2024-12-17T10:30:00Z",
      "weight": 0.5,
      "value": 150.0,
      "itemsQuantity": 3,
      "obs": "Entregar no periodo da manha",
      "consumedAt": "2024-12-17T10:35:00Z",
      "customer": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "ATN Contact",
        "cnpj": "12345678000190"
      }
    }
  ]
}

Campos adicionais (opcionais)

Campo Tipo Descricao
costCenter object Centro de custo resolvido para o pedido, exposto apenas como { code, name }. Omitido quando o pedido nao possui centro de custo. Os campos sensiveis (token/produto) nunca sao expostos.
contract object Contrato (loja/remetente) do pedido, bloco aditivo de identidade exposto apenas como { id, code, name } (name = razao_social, com fallback para nome_fantasia). Omitido quando o pedido nao tem contrato. O id e o UUID do contrato — a chave de enderecamento publica (round-trip no filtro contract_id e no contractId de criacao); os identificadores Flash nativos seguem internos da transportadora. Nunca carrega carrier_token, flash_client_id nem flash_contract_id.
receiptUrl string Link absoluto para o comprovante de entrega (GET /api/v1/delivery_receipts/:tracking), presente apenas quando ja existe um comprovante para este pedido. Omitido caso contrario.
invoice.date ISO-8601 Data de emissao da nota fiscal (YYYY-MM-DD), dentro do bloco invoice. null quando a data nao esta preenchida.
weight number Peso do pedido como armazenado. Omitido quando nao informado.
value number Valor do pedido como armazenado. Omitido quando nao informado.
itemsQuantity inteiro Quantidade de itens. Omitido quando nao informado.
obs string Observacoes livres do pedido. Omitido quando nao informado.
consumedAt ISO-8601 Instante em que o pedido foi marcado como consumido (acknowledged). Apenas no detalhe (nao aparece na linha de lista); omitido para pedidos ainda nao consumidos. Veja a secao "Acknowledge".
customer object Bloco de identidade do cliente dono do pedido, sempre presente, exposto apenas como { id, name, cnpj }. O id e o UUID do cliente (round-trip no filtro customer_id); o cnpj e apenas digitos. Nunca carrega transportadora, plataforma ou credenciais.

O objeto status (limitacao conhecida)

O objeto status e emitido na forma { code, highLevelStatus, description, updatedTime }. O highLevelStatus e a chave do enum de status em maiusculas (ex.: INTEGRADO, IMPORTADO, ERRO); o code e o codigo numerico Loggi correspondente.

code highLevelStatus Descricao
1 INTEGRADO Pedido integrado, aguardando importacao
2 IMPORTADO Pedido importado na transportadora
99 ERRO Erro no processamento
0 RASTREADO / AGUARDANDO_NF / AGUARDANDO_CENTRO_CUSTO Status desconhecido (ver nota abaixo)

Limitacao conhecida (status): os status rastreado, aguardando_nf e aguardando_centro_custo ainda nao possuem codigo numerico proprio e sao emitidos com code: 0 e description: "Status desconhecido" — embora o highLevelStatus (chave do enum em maiusculas) seja preenchido corretamente. Use o highLevelStatus como fonte de verdade do status do pedido; o code: 0 e um valor de fallback, nao um erro. Esse comportamento e pre-existente e mantido por compatibilidade. Nao confie em codigos numericos para esses tres status.

Exemplo cURL

cURL
curl -X GET "https://bridgelink.com.br/api/v1/orders/ATN12345" \
  -H "Authorization: Bearer SEU_TOKEN"

Acknowledge (Marcar Pedido como Consumido)

Marca um pedido como consumido pelo agregador (pull-dedup). Apos o acknowledge, o pedido sai da listagem padrao GET /orders (volta apenas com include_consumed=true). E a peca central do ciclo pull → acknowledge → re-poll.

POST /api/v1/orders/:id/acknowledge Marca o pedido como consumido (UUID ou rastreio)

Parametros da URL

Parametro Tipo Descricao
id* string UUID do pedido OU codigo de rastreamento. Resolucao dupla, sempre dentro do escopo do token.

Resposta de Sucesso

200 OK
JSON Response
{
  "trackingCode": "ATN12345",
  "consumedAt": "2024-12-17T10:35:00Z"
}

Idempotente (first-write-wins): a primeira chamada carimba consumedAt; as chamadas seguintes no mesmo pedido ecoam o mesmo instante, sem rebaixar nem rebatizar. Re-fazer o acknowledge e um no-op de sucesso. Resolve o pedido independentemente de ja estar consumido (nao depende de include_consumed).

Um :id fora do escopo (ou um UUID fabricado) retorna 404 / codigo 5 byte-identico ao Loggi (sem sinal de enumeracao). Token ausente/expirado retorna 401 / codigo 16.

Exemplo cURL

cURL
curl -X POST "https://bridgelink.com.br/api/v1/orders/ATN12345/acknowledge" \
  -H "Authorization: Bearer SEU_TOKEN"

Rastreamento Detalhado

Obtenha o historico completo de rastreamento de um pedido, incluindo todos os eventos e movimentacoes.

GET /api/v1/tracking/:tracking Consulta rastreamento detalhado

Parametros da URL

Parametro Tipo Descricao
tracking* string Codigo de rastreamento do pacote

Resposta de Sucesso

200 OK
JSON Response
{
  "packages": [
    {
      "trackingCode": "ATN12345",
      "loggiKey": "123456",
      "status": {
        "code": 10,
        "highLevelStatus": "in_transit",
        "description": "HAWB em transito para o destino",
        "updatedTime": "2024-12-17T14:00:00Z"
      },
      "trackingHistory": [
        {
          "status": {
            "code": 10,
            "highLevelStatus": "in_transit",
            "description": "HAWB em transito para o destino",
            "updatedTime": "2024-12-17T14:00:00Z"
          },
          "location": {
            "description": "CD Sao Paulo"
          }
        },
        {
          "status": {
            "code": 5,
            "highLevelStatus": "registered",
            "description": "HAWB registrado no sistema",
            "updatedTime": "2024-12-17T10:00:00Z"
          },
          "location": {
            "description": "CD Rio de Janeiro"
          }
        }
      ],
      "promisedDate": "2024-12-20T18:00:00Z",
      "deliveryInformation": null
    }
  ]
}

Resposta de Sucesso — transportadora Interlog

200 OK
JSON Response (Interlog)
{
  "packages": [
    {
      "trackingCode": "INT-EXEMPLO-0001",
      "status": {
        "code": 15,
        "highLevelStatus": "out_for_delivery",
        "description": "EM ROTA DE ENTREGA AO DESTINATARIO",
        "updatedTime": "2024-12-17T13:45:00Z"
      },
      "trackingHistory": [
        {
          "status": {
            "code": 15,
            "highLevelStatus": "out_for_delivery",
            "description": "EM ROTA DE ENTREGA AO DESTINATARIO",
            "updatedTime": "2024-12-17T13:45:00Z"
          },
          "location": {
            "description": "Base de Entrega - Sao Paulo/SP"
          }
        },
        {
          "status": {
            "code": 5,
            "highLevelStatus": "registered",
            "description": "IMPORTACAO/CADASTRO DE ENTREGA",
            "updatedTime": "2024-12-17T09:10:00Z"
          },
          "location": {
            "description": "CD Origem - Guarulhos/SP"
          }
        }
      ],
      "proofOfDeliveryUrl": "https://bridgelink.com.br/api/v1/comprovantes/INT-EXEMPLO-0001"
    }
  ]
}

Quando entregue, deliveryInformation contem { receiverName, receiverDocument }. Codigos de status do rastreamento (carrier): 0 pending, 5 registered, 10 in_transit, 15 out_for_delivery, 20 delivered, 25 returned, 30 failed_delivery, 35 cancelled, 40 loss.

Interlog (v2.12): para pedidos de transportadora Interlog, o objeto status (e cada trackingHistory[].status) tem code/highLevelStatus/description derivados do StatusMapping (DE/PARA do codlog) e nunca sao null — cobrindo o conjunto completo de transportadora (incl. 30 failed_delivery, 35 cancelled, 40 loss). A resposta Interlog nao inclui loggiKey, promisedDate nem deliveryInformation (campos exclusivos da Flash).

proofOfDeliveryUrl (v2.16 — exclusivo Interlog): presente somente na resposta de pedidos Interlog — nunca nas respostas Flash ou Logan, e o envelope { "packages": [...] } permanece inalterado (o campo vive apenas dentro do ramo Interlog). Quando presente, e uma URL absoluta para GET /api/v1/comprovantes/:tracking (o proxy autenticado que devolve a imagem JPG do comprovante). O campo e incluido apenas quando ha um comprovante anexado ao pedido; caso contrario e omitido por completo (ausente — nunca null).

Exemplo cURL

cURL
curl -X GET "https://bridgelink.com.br/api/v1/tracking/ATN12345" \
  -H "Authorization: Bearer SEU_TOKEN"

Etiquetas (Labels)

Baixe as etiquetas de envio em formato PDF codificadas em Base64.

GET /api/v1/labels/:tracking Baixa etiqueta em PDF

Parametros da URL

Parametro Tipo Descricao
tracking* string Codigo de rastreamento do pacote

Resposta de Sucesso

200 OK
JSON Response
{
  "packages": [
    {
      "trackingCode": "ATN12345",
      "loggiKey": "550e8400-e29b-41d4-a716-446655440000",
      "label": {
        "content": "JVBERi0xLjQKJeLjz9MKNCAwIG9iago8PC9...",
        "format": "PDF",
        "encoding": "base64"
      },
      "createdTime": "2024-12-17T10:30:00Z"
    }
  ]
}

Dica: O campo content contem o PDF codificado em Base64. Para visualizar ou salvar, decodifique o conteudo Base64.

Exemplo cURL (baixar e decodificar o PDF)

cURL
curl -s -X GET "https://bridgelink.com.br/api/v1/labels/ATN12345" \
  -H "Authorization: Bearer SEU_TOKEN" \
  | jq -r '.packages[0].label.content' \
  | base64 -d > etiqueta.pdf

Exemplo: Salvar PDF (Ruby)

Ruby
# Ruby
pdf_content = Base64.decode64(response['packages'][0]['label']['content'])
File.write('etiqueta.pdf', pdf_content)

Exemplo: Salvar PDF (Python)

Python
# Python
import base64
pdf_content = base64.b64decode(response['packages'][0]['label']['content'])
with open('etiqueta.pdf', 'wb') as f:
    f.write(pdf_content)

Consultar Meu Cliente

Retorna o perfil do proprio cliente autenticado (configuracao espelhada) e um resumo das integracoes. E um recurso singular auto-escopado: nao ha :id e nenhum parametro de cliente e consultado — a resposta e sempre o cliente dono do token.

GET /api/v1/customer Consulta o proprio perfil do cliente

Resposta de Sucesso

200 OK
JSON Response
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "ATN Contact",
    "cnpj": "12345678000190",
    "active": true,
    "city": "Sao Paulo",
    "uf": "SP",
    "address": "Rua das Flores, 123",
    "zipcode": "01234-567",
    "whatsappPhone": "11999998888",
    "traceable": true,
    "deliveryReceipt": true,
    "invoiceEmitter": false,
    "carrier": "flash_courier",
    "platform": "api",
    "interlog": {
      "ambiente": "producao",
      "active": true,
      "costCenters": [
        { "code": "CC01", "name": "Centro de Custo SP", "default": true },
        { "code": "CC02", "name": "Centro de Custo RJ", "default": false }
      ]
    },
    "contracts": [
      { "id": "9c8b7a65-4d3e-2f1a-0b9c-8d7e6f5a4b3c", "code": "LOJA-SP", "name": "Loja Sao Paulo LTDA", "cnpj": "12345678000190", "trackingPrefix": "SP" }
    ]
  }
}

O campo id e o UUID do cliente (string), nunca um inteiro. O campo cnpj e retornado somente com digitos (normalizado pelo modelo, ex.: "12345678000190"), sem mascara. O bloco interlog aparece apenas para clientes com integracao Interlog configurada (omitido inteiramente para clientes Flash/Logan). Os centros de custo expoem somente { code, name, default }. Fronteira de nao-vazamento: este recurso (e o GET /customers/:id de parceiro) nunca expoem login, password, authorization, token, codproduto nem codgrupoproduto. Campos fixos com valor nulo sao serializados como null (nao omitidos).

O array contracts (lojas/remetentes do cliente) esta sempre presente[] quando o cliente nao tem contrato. Cada item expoe apenas { id, code, name, cnpj, trackingPrefix } (name = razao_social, com fallback para nome_fantasia; trackingPrefix = prefix_tracking). O id e o UUID do contrato — a chave de enderecamento publica usada no filtro contract_id e no contractId de criacao. Fronteira de nao-vazamento: o item nunca carrega carrier_token, flash_client_id, flash_contract_id nem qualquer credencial.

Exemplo cURL

cURL
curl -X GET "https://bridgelink.com.br/api/v1/customer" \
  -H "Authorization: Bearer SEU_TOKEN"

Listar Clientes (Parceiro / Agregador)

(Endpoint de parceiro) Retorna a lista paginada dos clientes que o token de parceiro pode ler — a sua allowlist, ordenada por nome. Um token single-customer le apenas o seu proprio cliente. O escopo parte sempre de authorized_customer_idsnunca de um id enviado pelo cliente.

GET /api/v1/customers Lista os clientes da allowlist (paginada)

Parametros de Query (todos opcionais)

Parametro Tipo Descricao
page(opcional) inteiro Pagina desejada (default: 1)
per_page(opcional) inteiro Itens por pagina (default: 50, maximo: 100)

Resposta de Sucesso

200 OK
JSON Response
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "ATN Contact",
      "cnpj": "12345678000190",
      "carrier": "flash_courier",
      "platform": "api",
      "active": true
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 50,
    "total": 4,
    "total_pages": 1
  }
}

A linha de resumo traz exatamente { id, name, cnpj, carrier, platform, active }. O id e o UUID do cliente (round-trip no filtro customer_id dos pedidos); carrier e platform sao as chaves de enum em string; active e a negacao de disabled. A lista e sempre escopada a allowlist do token.

Exemplo cURL

cURL
curl -X GET "https://bridgelink.com.br/api/v1/customers?per_page=50" \
  -H "Authorization: Bearer SEU_TOKEN"

Consultar Cliente (Parceiro / Agregador)

(Endpoint de parceiro) Retorna o detalhe de um cliente dentro da allowlist do token, incluindo o remetente padrao (sender), o remetente estruturado da transportadora (carrierSender, apenas Logan) e a conexao de contrato Flash (jallConnection, apenas Flash). Um :id fora da allowlist (ou um UUID fabricado) retorna o mesmo 404 / codigo 5 que um recurso inexistente, sem qualquer sinal de enumeracao.

GET /api/v1/customers/:id Detalha um cliente da allowlist

Parametros da URL

Parametro Tipo Descricao
id* UUID UUID do cliente dentro da allowlist do token.

Resposta de Sucesso

200 OK
JSON Response
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "ATN Contact",
    "cnpj": "12345678000190",
    "active": true,
    "city": "Sao Paulo",
    "uf": "SP",
    "address": "Rua das Flores, 123",
    "zipcode": "01234-567",
    "whatsappPhone": "11999998888",
    "traceable": true,
    "deliveryReceipt": true,
    "invoiceEmitter": false,
    "carrier": "flash_courier",
    "platform": "api",
    "sender": {
      "name": "Centro de Distribuicao SP",
      "cnpj": "12345678000190",
      "address": "Av. Logistica, 1000",
      "city": "Sao Paulo",
      "uf": "SP",
      "zipcode": "04001-000"
    },
    "carrierSender": {
      "name": "Remetente Logan",
      "cnpj": "98765432000110",
      "address": "Rua do Galpao",
      "number": "500",
      "neighborhood": "Distrito Industrial",
      "city": "Cajamar",
      "state": "SP",
      "zipcode": "07750-000",
      "ie": "111222333444"
    },
    "jallConnection": {
      "senderLocationId": "1001",
      "clientId": "FLASH-CLI-42",
      "contractId": "CTR-2024",
      "subsidiaryId": "FIL-01"
    },
    "contracts": [
      { "id": "9c8b7a65-4d3e-2f1a-0b9c-8d7e6f5a4b3c", "code": "LOJA-SP", "name": "Loja Sao Paulo LTDA", "cnpj": "12345678000190", "trackingPrefix": "SP" }
    ]
  }
}

O bloco sender (6 chaves: name, cnpj, address, city, uf, zipcode) esta sempre presente. carrierSender (9 chaves, incluindo ie) aparece apenas para clientes Logan; jallConnection aparece apenas para clientes Flash e expoe exatamente as 4 chaves de contrato { senderLocationId, clientId, contractId, subsidiaryId }. Atencao: o contractId/clientId aqui sao os identificadores nativos da Flash (internos da transportadora) — nao sao a chave de enderecamento publica. A chave publica de contrato e o UUID do array contracts abaixo.

O array contracts (igual ao de GET /customer) esta sempre presente[] quando o cliente nao tem contrato. Cada item expoe apenas { id, code, name, cnpj, trackingPrefix }; o id e o UUID do contrato (round-trip no filtro contract_id e no contractId de criacao). Nunca carrega carrier_token, flash_client_id nem flash_contract_id.

Fronteira de nao-vazamento: o detalhe nunca expoe login, password, authorization, token, codproduto nem codgrupoproduto — a whitelist enumerada de campos e a fronteira.

Exemplo cURL

cURL
curl -X GET "https://bridgelink.com.br/api/v1/customers/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer SEU_TOKEN"

Comprovantes de Entrega

Liste os comprovantes de entrega do proprio cliente (paginado + filtros) e consulte o detalhe curado de um comprovante pela chave de rastreio.

Listar Comprovantes

GET /api/v1/delivery_receipts Lista comprovantes (paginada + filtros)

Parametros de Query (todos opcionais)

Parametro Tipo Descricao
page(opcional) inteiro Pagina desejada (default: 1)
per_page(opcional) inteiro Itens por pagina (default: 50, maximo: 100)
status(opcional) string Chave do enum de status do comprovante (ex.: processando, aguardando_envio, entregue, concluido)
tracking(opcional) string Filtro exato pelo codigo de rastreio
created_from(opcional) ISO-8601 Data/hora inicial (inclusiva)
created_to(opcional) ISO-8601 Data/hora final (inclusiva)

Resposta de Sucesso

200 OK
JSON Response
{
  "data": [
    {
      "trackingCode": "ATN12345",
      "status": "concluido",
      "statusDescription": "Documento de entrega enviado ao servidor do cliente",
      "invoiceNumber": "NF-001",
      "createdAt": "2024-12-17T10:30:00Z"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 50,
    "total": 12,
    "total_pages": 1
  }
}

Aqui o status e a chave bruta do enum do comprovante (string), acompanhada de statusDescription em pt-BR — diferente do objeto status { code, ... } dos pedidos.

Exemplo cURL

cURL
curl -X GET "https://bridgelink.com.br/api/v1/delivery_receipts?status=concluido" \
  -H "Authorization: Bearer SEU_TOKEN"

Consultar Comprovante

GET /api/v1/delivery_receipts/:tracking Detalhe curado de um comprovante

Parametros da URL

Parametro Tipo Descricao
tracking* string Codigo de rastreamento do comprovante

Resposta de Sucesso

200 OK
JSON Response
{
  "data": {
    "trackingCode": "ATN12345",
    "status": "concluido",
    "statusDescription": "Documento de entrega enviado ao servidor do cliente",
    "invoiceNumber": "NF-001",
    "createdAt": "2024-12-17T10:30:00Z",
    "invoice": {
      "number": "NF-001",
      "series": "1",
      "issueDate": "2024-12-15",
      "volumeCount": "1",
      "totalWeight": "0.5",
      "invoiceValue": "150.00"
    },
    "recipient": {
      "razaoSocial": "Cliente Final LTDA",
      "city": "Sao Paulo",
      "uf": "SP"
    }
  }
}

Os blocos invoice e recipient sao opcionais e omitidos quando nao ha dados. Nao ha campo de imagem/URL do comprovante — o status carrega o sinal do ciclo de vida da entrega. Um tracking de outro cliente ou inexistente retorna o mesmo 404 / codigo 5.

Exemplo cURL

cURL
curl -X GET "https://bridgelink.com.br/api/v1/delivery_receipts/ATN12345" \
  -H "Authorization: Bearer SEU_TOKEN"

Baixar Imagem do Comprovante (JPG)

GET /api/v1/comprovantes/:tracking Imagem JPG do comprovante de entrega Interlog

Devolve a imagem JPG original do comprovante de entrega (foto/assinatura do recebimento) de um pedido Interlog, pela chave de rastreio. E o destino do campo proofOfDeliveryUrl da resposta de GET /api/v1/tracking — diferente de GET /api/v1/delivery_receipts/:tracking, que devolve o JSON curado do ciclo de vida (sem imagem). Requisicao autenticada via OAuth2 Bearer e escopada ao proprio cliente (tenant).

Parametros da URL

Parametro Tipo Descricao
tracking* string Codigo de rastreamento do pedido

Headers

Authorization: Bearer <idToken>

Resposta de Sucesso

200 OK

O corpo e a imagem binaria image/jpeg servida inline (Content-Type: image/jpeg, Content-Disposition: inline) — o JPG original completo do comprovante. Nao e um envelope JSON e nao e base64.

Respostas de Erro

404 · code 5{ "code": 5, "message": "Comprovante not found", "details": [] }: uma unica resposta indistinguivel para rastreio inexistente, rastreio de outro cliente, OU pedido que existe mas nao tem comprovante anexado (sem pista de enumeracao entre os tres casos).

500 · code 13{ "code": 13, "message": "Comprovante retrieval failed", "details": [] }: falha ao ler o blob da imagem.

PII / seguranca: o comprovante e a imagem do recebimento do destinatario (dado pessoal). Por isso e servido apenas atraves deste endpoint autenticado e escopado por tenantnunca como uma URL de blob direta /rails/active_storage/... (as rotas globais de blob do Active Storage nao sao escopadas por tenant). O campo proofOfDeliveryUrl aponta sempre para este proxy, nunca para um blob direto.

Exemplo cURL

cURL
curl -X GET "https://bridgelink.com.br/api/v1/comprovantes/INT-EXEMPLO-0001" \
  -H "Authorization: Bearer SEU_TOKEN" \
  --output comprovante.jpg

Codigos de Erro

A API utiliza codigos HTTP padrao para indicar o sucesso ou falha de uma requisicao. Todas as respostas de erro seguem o padrao Loggi { code, message, details }.

404 · code 5
Recurso nao encontrado (ou de outro cliente)
429 · code 8
Limite de taxa excedido (ver Retry-After)
400/422 · code 9
Requisicao invalida / erro de validacao
500 · code 13
Erro interno do servidor
401 · code 16
Nao autorizado (credenciais invalidas/ausentes)

Esta API nao emite codigo 7 / PERMISSION_DENIED. Um recurso de outro cliente (ou inexistente) retorna sempre o mesmo 404 / codigo 5, sem revelar se o recurso existe em outro tenant.

Formato de Resposta de Erro (Loggi)

JSON Error Response
{
  "code": 5,
  "message": "Resource not found",
  "details": []
}

Detalhamento de Erros de Validacao (details)

Para os erros 400 / 422 (codigo 9), o campo details traz a lista de campos invalidos no formato fieldViolations:

JSON Error Response
{
  "code": 9,
  "message": "Invalid filter",
  "details": [
    {
      "@type": "type.googleapis.com/google.rpc.BadRequest",
      "fieldViolations": [
        { "field": "status", "description": "Unrecognized status value" }
      ]
    }
  ]
}

Limites de Taxa (Rate Limiting)

A API e protegida por rate limiting. Ao exceder o limite, a resposta e 429 com codigo Loggi 8 e o cabecalho Retry-After (segundos ate liberar).

Superficie Limite Chave
/api/v1/* (endpoints autenticados) 120 requisicoes/minuto por cliente da API (JWT)
POST /api/v1/oauth/token 10 requisicoes/minuto por IP
HTTP 429 + Retry-After
HTTP/1.1 429 Too Many Requests
Retry-After: 42

{
  "code": 8,
  "message": "Rate limit exceeded",
  "details": []
}

Dica: Respeite o Retry-After antes de repetir a requisicao. Como o token dura 24 horas, solicite-o uma vez e reutilize-o — o limite por cliente (120/min) e mais generoso que o limite anonimo de oauth/token (10/min por IP). Sempre verifique o campo details para obter informacoes especificas sobre erros de validacao.

Contrato legivel por maquina: o contrato OpenAPI 3.0 desta API esta disponivel publicamente (sem token) em GET /api/v1/openapi.yaml — use-o para gerar um cliente/SDK automaticamente no seu ERP/WMS.

Webhooks (Push)

Alem de consultar a API por polling, voce pode receber os eventos por push: o Bridge Link envia uma requisicao POST assinada para uma URL sua (o endpoint receptor) assim que algo relevante acontece. Assim um parceiro/agregador (ex.: Engloba) recebe pedidos e atualizacoes de clientes sem precisar fazer polling.

O canal de webhooks e estritamente aditivo — ele entrega exatamente os mesmos recursos que a pull API ja expoe, com o mesmo escopo de allowlist. Voce pode usar webhooks, polling, ou os dois ao mesmo tempo.

A assinatura (cadastrar a URL receptora, os eventos desejados e gerar o segredo) e uma acao administrativa — nao e uma chamada de API. Fale com a equipe Bridge Link para habilitar o push e receber o segredo de assinatura (secret), revelado uma unica vez no cadastro.

Eventos

Sao tres tipos de evento. Cada assinatura escolhe quais deseja receber.

Evento Quando dispara
order.created Quando um pedido fica pronto pela primeira vez (integrado/importado), em qualquer uma das tres origens de criacao — pedido vindo da Tiny, pedido criado via API (POST /orders) ou importacao por SFTP — para um cliente dentro da allowlist do seu token.
order.status_changed A cada transicao de status do pedido (incluindo as atualizacoes geradas no registro de rastreamento).
customer.updated Quando um cliente (ou a sua configuracao de remetente / contrato CT-e) e criado ou atualizado.

Envelope

Todo webhook chega com o mesmo envelope versionado, com exatamente estas quatro chaves em camelCase: { event, eventId, occurredAt, data }.

Corpo do webhook

JSON
{
  "event": "order.status_changed",
  "eventId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "occurredAt": "2026-06-20T19:12:27Z",
  "data": { }
}
Chave Descricao
event O tipo do evento — um de order.created, order.status_changed, customer.updated.
eventId Chave de idempotencia (UUID). Definida uma vez por evento logico e reaproveitada em todas as retentativas — e tambem no reenvio (replay) feito pelo admin. Deduplique por eventId.
occurredAt Instante do evento, em ISO8601 UTC.
data O mesmo payload que a pull API retorna para aquele recurso (ver abaixo).

O bloco data nao e um formato novo: e identico ao que voce ja recebe pela pull API — para order.created/order.status_changed e o detalhe de Consultar Pedido (GET /orders/:id); para customer.updated e o de Consultar Cliente (GET /customers/:id). Abaixo documentamos cada chave de cada payload, em todos os cenarios.

Payload do pedido — data de order.created e order.status_changed

Para os dois eventos de pedido, data e o objeto abaixo. Modelo de presenca: as chaves de topo cujo valor seria nulo sao removidas (a chave nao aparece — nao vem como null): isso vale para invoice, weight, value, itemsQuantity, obs, flashLabelUrl, costCenter, contract, receiptUrl e consumedAt. Ja as chaves aninhadas (dentro de status, destination, recipient, etc.) podem vir como null.

CampoTipoPresencaDescricao
trackingCodestringSempre*Codigo de rastreio (HAWB). *Ausente se o pedido ainda nao tiver tracking.
loggiKeystring (UUID)SempreID interno do pedido no Bridge Link.
statusobjetoSempreBloco de status (4 chaves abaixo).
status.codeinteiroSempreCodigo numerico legado (Loggi). Varios status mapeiam para 0 — ver tabela de status. Use highLevelStatus como fonte de verdade.
status.highLevelStatusstringSempreStatus canonico em MAIUSCULAS (ex.: INTEGRADO). E o nome do status interno em caixa alta.
status.descriptionstringSempreDescricao em pt-BR (ver tabela de status).
status.updatedTimestring (ISO8601)SempreQuando o status mudou.
destinationobjetoSempreDestinatario + endereco.
destination.recipient.namestring | nullSempreNome do destinatario.
destination.recipient.phonestring | nullSempreTelefone do destinatario.
destination.recipient.federalTaxIdstring | nullSempreCPF ou CNPJ do destinatario (CPF tem precedencia quando ambos existem).
destination.postalAddress.postalCodestring | nullSempreCEP do destinatario.
destination.postalAddress.administrativeAreastring | nullSempreUF do destinatario.
destination.postalAddress.addressLinesarray de stringSempreLinhas do endereco: ["Rua, numero", complemento, bairro, cidade]. Partes em branco sao removidas — pode ser [].
destination.postalAddress.streetstring | nullSempreAditivo (v2.11) — logradouro do destinatario, ao lado de addressLines (que continua). null quando em branco.
destination.postalAddress.numberstring | nullSempreNumero do endereco do destinatario.
destination.postalAddress.complementstring | nullSempreComplemento do endereco do destinatario.
destination.postalAddress.districtstring | nullSempreBairro do destinatario.
destination.postalAddress.citystring | nullSempreCidade do destinatario.
destination.postalAddress.statestring | nullSempreUF do destinatario (espelha administrativeArea).
invoiceobjetoCondicionalBloco fiscal. Presente somente quando ha NF (number preenchido); ausente (a chave some) quando o pedido nao tem NF.
invoice.numberstringCom invoiceNumero da nota fiscal.
invoice.keystring | nullCom invoiceChave de acesso (44 digitos).
invoice.seriesstring | nullCom invoiceSerie da NF.
invoice.datestring (ISO8601) | nullCom invoiceData de emissao.
customerobjetoSempreCliente dono do pedido (identidade apenas).
customer.idstring (UUID)SempreID do cliente no Bridge Link.
customer.namestringSempreRazao social / nome do cliente.
customer.cnpjstringSempreCNPJ do cliente (somente digitos).
senderobjetoSempreAditivo (v2.11) — remetente do pedido, por transportadora; irmao do bloco identitario customer (que nao muda). Conjunto de 11 chaves uniforme independente da transportadora: Logan vem de logan_senders (inclui ie); Flash/interlog vem das colunas planas do cliente, com ie/number/complement/district/phone = null. Um campo sem fonte serializa null (sem dado fabricado).
sender.namestring | nullSempreRazao social / nome do remetente.
sender.cnpjstring | nullSempreCNPJ do remetente.
sender.iestring | nullSempreInscricao estadual do remetente (apenas Logan; null no Flash/interlog).
sender.streetstring | nullSempreLogradouro do remetente.
sender.numberstring | nullSempreNumero do endereco do remetente (null no Flash/interlog).
sender.complementstring | nullSempreComplemento do endereco do remetente (null no Flash/interlog).
sender.districtstring | nullSempreBairro do remetente (null no Flash/interlog).
sender.citystring | nullSempreCidade do remetente.
sender.statestring | nullSempreUF do remetente.
sender.postalCodestring | nullSempreCEP do remetente.
sender.phonestring | nullSempreTelefone do remetente (null no Flash/interlog).
weightnumeroCondicionalPeso. Ausente (chave some) quando nulo.
valuenumeroCondicionalValor declarado. Ausente quando nulo.
itemsQuantityinteiroCondicionalQuantidade de volumes/itens. Ausente quando nulo.
obsstringCondicionalObservacoes. Ausente quando nulo.
labelUrlstring (URL)SempreURL da etiqueta no Bridge Link (GET /api/v1/labels/:tracking).
flashLabelUrlstring (URL)CondicionalURL da etiqueta na Flash Pegasus. Presente somente quando o pedido tem etiqueta Flash gerada; ausente caso contrario.
costCenterobjetoCondicionalCentro de custo. Presente somente quando o pedido tem centro de custo (codigo e/ou nome); ausente caso contrario.
costCenter.codestringCom costCenterCodigo do centro de custo (snapshot do pedido).
costCenter.namestring | nullCom costCenterNome do centro de custo.
contractobjetoCondicionalContrato (loja/remetente) do pedido — bloco aditivo de identidade. Presente somente quando o pedido tem contrato; ausente caso contrario. Nunca carrega carrier_token / flash_client_id / flash_contract_id.
contract.idstring (UUID)Com contractUUID do contrato (round-trip no filtro contract_id).
contract.codestring | nullCom contractCodigo do contrato.
contract.namestring | nullCom contractrazao_social, com fallback para nome_fantasia.
receiptUrlstring (URL)CondicionalURL do comprovante de entrega (GET /api/v1/delivery_receipts/:tracking). Presente somente quando existe comprovante para o tracking; ausente caso contrario.
createdAtstring (ISO8601)SempreCriacao do pedido.
updatedAtstring (ISO8601)SempreUltima atualizacao do pedido.
consumedAtstring (ISO8601)CondicionalQuando o pedido foi marcado como consumido (acknowledge da pull-dedup). Ausente ate ser consumido.

Tabela de status (status.code / status.highLevelStatus / status.description)

highLevelStatuscodedescription
INTEGRADO1Pedido integrado, aguardando importacao
IMPORTADO2Pedido importado na transportadora
RASTREADO0Status desconhecido
AGUARDANDO_NF0Status desconhecido
AGUARDANDO_CENTRO_CUSTO0Status desconhecido
ERRO99Erro no processamento

Use highLevelStatus como a fonte de verdade do status, nao code. O code e um numero legado (Loggi): varios status atuais (RASTREADO, AGUARDANDO_NF, AGUARDANDO_CENTRO_CUSTO) caem em 0, e os codigos 10 (em transito) e 20 (entregue) sao reservados/legados e nao sao emitidos pelos status atuais.

Exemplo — pedido COMPLETO (todas as chaves opcionais presentes)
{
  "event": "order.status_changed",
  "eventId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "occurredAt": "2026-06-20T19:12:27Z",
  "data": {
    "trackingCode": "BL123456789BR",
    "loggiKey": "0ae47987-0db1-4811-b131-06db580a25ab",
    "status": {
      "code": 2,
      "highLevelStatus": "IMPORTADO",
      "description": "Pedido importado na transportadora",
      "updatedTime": "2026-06-20T16:12:27-03:00"
    },
    "destination": {
      "recipient": { "name": "Maria Silva", "phone": "21999990000", "federalTaxId": "12345678900" },
      "postalAddress": {
        "postalCode": "20000000",
        "administrativeArea": "RJ",
        "addressLines": ["Rua Exemplo, 100", "Apto 201", "Centro", "Rio de Janeiro"],
        "street": "Rua Exemplo",
        "number": "100",
        "complement": "Apto 201",
        "district": "Centro",
        "city": "Rio de Janeiro",
        "state": "RJ"
      }
    },
    "invoice": { "number": "12345", "key": "35250611222333000181550010000123451000123456", "series": "1", "date": "2026-06-20" },
    "customer": { "id": "4ea8861a-cbe0-48be-b4b5-9def637603ef", "name": "CLIENTE EXEMPLO LTDA", "cnpj": "11222333000181" },
    "sender": {
      "name": "REMETENTE EXEMPLO LTDA",
      "cnpj": "99888777000166",
      "ie": "123456789",
      "street": "Av Remetente",
      "number": "500",
      "complement": "Galpao 2",
      "district": "Industrial",
      "city": "Sao Paulo",
      "state": "SP",
      "postalCode": "01310100",
      "phone": "1133334444"
    },
    "weight": 1.5,
    "value": 199.9,
    "itemsQuantity": 3,
    "obs": "Entregar em horario comercial",
    "labelUrl": "https://bridgelink.com.br/api/v1/labels/BL123456789BR",
    "flashLabelUrl": "https://webservice.flashpegasus.com.br/FlashPegasus/rest/padrao/etiqueta/9988776655",
    "costCenter": { "code": "CC-RJ-01", "name": "Filial Rio" },
    "contract": { "id": "9c8b7a65-4d3e-2f1a-0b9c-8d7e6f5a4b3c", "code": "LOJA-RJ", "name": "Filial Rio LTDA" },
    "receiptUrl": "https://bridgelink.com.br/api/v1/delivery_receipts/BL123456789BR",
    "createdAt": "2026-06-20T15:40:00-03:00",
    "updatedAt": "2026-06-20T16:12:27-03:00",
    "consumedAt": "2026-06-20T16:15:00-03:00"
  }
}
Exemplo — pedido MINIMO (sem NF e sem extras: chaves condicionais ausentes)
{
  "event": "order.created",
  "eventId": "7b2c9a14-3e6f-4d21-9c0a-1f8e7d6c5b4a",
  "occurredAt": "2026-06-20T19:38:45Z",
  "data": {
    "trackingCode": "BL987654321BR",
    "loggiKey": "1c2d3e4f-aaaa-bbbb-cccc-0123456789ab",
    "status": {
      "code": 1,
      "highLevelStatus": "INTEGRADO",
      "description": "Pedido integrado, aguardando importacao",
      "updatedTime": "2026-06-20T16:38:44-03:00"
    },
    "destination": {
      "recipient": { "name": "Joao Souza", "phone": null, "federalTaxId": null },
      "postalAddress": {
        "postalCode": "01310100",
        "administrativeArea": "SP",
        "addressLines": ["Av Paulista, 1000", "Bela Vista", "Sao Paulo"],
        "street": "Av Paulista",
        "number": "1000",
        "complement": null,
        "district": "Bela Vista",
        "city": "Sao Paulo",
        "state": "SP"
      }
    },
    "customer": { "id": "4ea8861a-cbe0-48be-b4b5-9def637603ef", "name": "CLIENTE EXEMPLO LTDA", "cnpj": "11222333000181" },
    "sender": {
      "name": "CLIENTE EXEMPLO LTDA",
      "cnpj": "11222333000181",
      "ie": null,
      "street": "Rua do Cliente",
      "number": null,
      "complement": null,
      "district": null,
      "city": "Sao Paulo",
      "state": "SP",
      "postalCode": "04567000",
      "phone": null
    },
    "weight": 0.8,
    "value": 50.0,
    "itemsQuantity": 1,
    "labelUrl": "https://bridgelink.com.br/api/v1/labels/BL987654321BR",
    "createdAt": "2026-06-20T16:38:44-03:00",
    "updatedAt": "2026-06-20T16:38:44-03:00"
  }
}

No exemplo minimo, repare que invoice, obs, flashLabelUrl, costCenter, contract, receiptUrl e consumedAt nao aparecem (foram removidos por serem nulos), e os campos aninhados nulos (recipient.phone, recipient.federalTaxId, postalAddress.complement) vem como null. O bloco sender e um exemplo Flash: ie/number/complement/district/phone vem como null (sem coluna de origem), enquanto num cliente Logan esses campos viriam preenchidos a partir de logan_senders.

Payload do cliente — data de customer.updated

Para customer.updated, data e o objeto abaixo. Modelo de presenca (diferente do pedido): os campos fixos nunca somem — um valor nulo vem como null. Ja os blocos por transportadora (interlog, carrierSender, jallConnection) usam merge-when-present: a chave fica ausente quando nao se aplica (nunca null nem []). Qual bloco aparece depende do carrier. O array contracts nao e um bloco por transportadora: esta sempre presente ([] quando nao ha contrato), independente do carrier.

CampoTipoPresencaDescricao
idstring (UUID)SempreID do cliente.
namestringSempreRazao social / nome.
cnpjstringSempreCNPJ (somente digitos).
activebooleanSempreCliente ativo (!disabled).
citystring | nullSempreCidade.
ufstring | nullSempreUF.
addressstring | nullSempreEndereco.
zipcodestring | nullSempreCEP.
whatsappPhonestring | nullSempreWhatsApp de contato.
traceableboolean | nullSempreHabilita pagina de rastreio.
deliveryReceiptboolean | nullSempreTrata comprovantes de entrega.
invoiceEmitterboolean | nullSempreEmite NF.
carrierstring (enum)SempreTransportadora: flash_courier | logan | interlog. Define qual bloco condicional aparece.
platformstring (enum)SemprePlataforma de origem: tiny | server_info | vtex | bling | api.
senderobjetoSempreRemetente base (colunas do cliente). Chaves: name, cnpj, address, city, uf, zipcode (cada uma string | null).
contractsarraySempreContratos (lojas/remetentes) do cliente — sempre presente ([] quando nao ha). Cada item: { id, code, name, cnpj, trackingPrefix } (id = UUID do contrato; name = razao_socialnome_fantasia). Nunca expoe carrier_token / flash_client_id / flash_contract_id.
interlogobjetoSo quando carrier=interlogConfig Interlog. Chaves: ambiente (enum homologacao|producao), active (boolean), costCenters (array de {code, name, default}). Credenciais nunca expostas.
carrierSenderobjetoSo quando carrier=loganRemetente Logan (CT-e). Chaves: name, cnpj, address, number, neighborhood, city, state, zipcode, ie.
jallConnectionobjetoSo quando carrier=flash_courierConfig de contrato CT-e da Flash. Apenas os 4 campos de contrato: senderLocationId, clientId, contractId, subsidiaryId (inteiros/string). Login/senha/token nunca expostos.
Exemplo — cliente FLASH (bloco jallConnection)
{
  "event": "customer.updated",
  "eventId": "9f3b974c-649c-48ae-9af8-27cfdf4eb951",
  "occurredAt": "2026-06-20T19:38:45Z",
  "data": {
    "id": "4ea8861a-cbe0-48be-b4b5-9def637603ef",
    "name": "CLIENTE FLASH LTDA",
    "cnpj": "11222333000181",
    "active": true,
    "city": "Rio de Janeiro",
    "uf": "RJ",
    "address": "Rua do Remetente, 50",
    "zipcode": "20000000",
    "whatsappPhone": null,
    "traceable": true,
    "deliveryReceipt": false,
    "invoiceEmitter": true,
    "carrier": "flash_courier",
    "platform": "tiny",
    "sender": { "name": "CLIENTE FLASH LTDA", "cnpj": "11222333000181", "address": "Rua do Remetente, 50", "city": "Rio de Janeiro", "uf": "RJ", "zipcode": "20000000" },
    "contracts": [ { "id": "9c8b7a65-4d3e-2f1a-0b9c-8d7e6f5a4b3c", "code": "LOJA-RJ", "name": "Filial Rio LTDA", "cnpj": "11222333000181", "trackingPrefix": "RJ" } ],
    "jallConnection": { "senderLocationId": 1234, "clientId": 5678, "contractId": 9012, "subsidiaryId": "SP01" }
  }
}
Exemplo — cliente LOGAN (bloco carrierSender)
{
  "event": "customer.updated",
  "eventId": "a1b2c3d4-e5f6-47a8-9b0c-1d2e3f4a5b6c",
  "occurredAt": "2026-06-20T19:40:00Z",
  "data": {
    "id": "7c1f0e44-2b9a-4c33-8e77-aa11bb22cc33",
    "name": "CLIENTE LOGAN SA",
    "cnpj": "99888777000166",
    "active": true,
    "city": "Sao Paulo",
    "uf": "SP",
    "address": "Av Industrial, 2000",
    "zipcode": "04001000",
    "whatsappPhone": "11988887777",
    "traceable": true,
    "deliveryReceipt": true,
    "invoiceEmitter": false,
    "carrier": "logan",
    "platform": "vtex",
    "sender": { "name": "CLIENTE LOGAN SA", "cnpj": "99888777000166", "address": "Av Industrial, 2000", "city": "Sao Paulo", "uf": "SP", "zipcode": "04001000" },
    "contracts": [ { "id": "1a2b3c4d-5e6f-4708-8a9b-0c1d2e3f4a5b", "code": "LOJA-SP", "name": "CLIENTE LOGAN SA", "cnpj": "99888777000166", "trackingPrefix": "SP" } ],
    "carrierSender": { "name": "CLIENTE LOGAN SA", "cnpj": "99888777000166", "address": "Av Industrial", "number": "2000", "neighborhood": "Vila Industrial", "city": "Sao Paulo", "state": "SP", "zipcode": "04001000", "ie": "123456789012" }
  }
}
Exemplo — cliente INTERLOG (bloco interlog)
{
  "event": "customer.updated",
  "eventId": "b0c1d2e3-f4a5-4607-8819-2a3b4c5d6e7f",
  "occurredAt": "2026-06-20T19:42:00Z",
  "data": {
    "id": "33aa44bb-55cc-66dd-77ee-88ff99001122",
    "name": "CLIENTE INTERLOG ME",
    "cnpj": "55444333000122",
    "active": true,
    "city": "Niteroi",
    "uf": "RJ",
    "address": "Rua Central, 10",
    "zipcode": "24000000",
    "whatsappPhone": null,
    "traceable": true,
    "deliveryReceipt": false,
    "invoiceEmitter": true,
    "carrier": "interlog",
    "platform": "bling",
    "sender": { "name": "CLIENTE INTERLOG ME", "cnpj": "55444333000122", "address": "Rua Central, 10", "city": "Niteroi", "uf": "RJ", "zipcode": "24000000" },
    "contracts": [ { "id": "2b3c4d5e-6f70-4819-9a0b-1c2d3e4f5a6b", "code": "PADRAO", "name": "CLIENTE INTERLOG ME", "cnpj": "55444333000122", "trackingPrefix": null } ],
    "interlog": { "ambiente": "producao", "active": true, "costCenters": [ { "code": "PADRAO", "name": "Padrao", "default": true }, { "code": "SP", "name": "Sao Paulo", "default": false } ] }
  }
}

Os tres blocos por transportadora sao mutuamente exclusivos na pratica: um cliente flash_courier traz jallConnection, um logan traz carrierSender, e um interlog traz interlog. O bloco sender (remetente base) vem sempre, para qualquer transportadora.

Cabecalhos de entrega

Cada POST de webhook traz Content-Type: application/json mais os quatro cabecalhos X-BridgeLink-*:

Cabecalho Conteudo
X-BridgeLink-Signature A assinatura HMAC no formato sha256=<hex> (ver "Verificacao da assinatura").
X-BridgeLink-Timestamp O instante da assinatura em segundos Unix (string). Faz parte da string assinada (defesa contra replay).
X-BridgeLink-Event O tipo do evento (ex.: order.created).
X-BridgeLink-Delivery-Id O eventId desta entrega (igual ao eventId do envelope) — use-o para deduplicar.

Verificacao da assinatura (HMAC-SHA256)

A assinatura e calculada sobre a string "#{timestamp}.#{raw_body}" — ou seja, o X-BridgeLink-Timestamp recebido, um ponto literal (.) e o corpo bruto exato da requisicao (os bytes recebidos, sem reserializar o JSON). O timestamp fica dentro da string assinada: ele nao pode ser alterado sem quebrar o HMAC.

Use sempre o corpo bruto (request.raw_post no Rails), nunca um JSON reparseado/reserializado, ou a assinatura nao vai bater.

Exemplo em Ruby

Copie e cole — troque o SECRET pelo segredo do seu cadastro. O segredo abaixo e ficticio.

Ruby
require 'openssl'
require 'active_support'           # ActiveSupport::SecurityUtils.secure_compare

# PLACEHOLDER — substitua pelo segredo revelado no cadastro da sua assinatura.
SECRET    = 'whsec_exemplo_NAO_REAL'
TOLERANCE = 300                    # segundos (5 min)

def webhook_valido?(raw_body, signature_header, timestamp_header, secret = SECRET)
  # 1) Rejeita timestamp velho (replay).
  age = Time.now.to_i - Integer(timestamp_header, 10)
  return false if age.abs > TOLERANCE

  # 2) Recompute a assinatura sobre "#{timestamp}.#{raw_body}".
  signed_string = "#{timestamp_header}.#{raw_body}"
  expected      = 'sha256=' + OpenSSL::HMAC.hexdigest('SHA256', secret, signed_string)

  # 3) Comparacao de tempo constante (evita timing attack).
  ActiveSupport::SecurityUtils.secure_compare(signature_header.to_s, expected)
rescue ArgumentError, TypeError
  false                            # timestamp nao numerico => trate como invalido
end

# No seu controller (Rails): use request.raw_post (o corpo BRUTO, nao params).
# raw = request.raw_post
# sig = request.headers['X-BridgeLink-Signature']
# ts  = request.headers['X-BridgeLink-Timestamp']
# head(:unauthorized) and return unless webhook_valido?(raw, sig, ts)

Pseudocodigo (qualquer linguagem)

Pseudocodigo
signed_string = timestamp_header + "." + raw_request_body
expected      = "sha256=" + hmac_sha256_hexdigest(secret, signed_string)
valido        = constant_time_equals(x_bridgelink_signature, expected)
                AND abs(now_unix - timestamp_header) <= TOLERANCE

Atencao: os exemplos usam um segredo ficticio (whsec_exemplo_NAO_REAL). Nunca publique nem versione o seu segredo real — trate-o como uma senha.

Semantica de entrega

Boas praticas do receptor: responda 2xx rapido (idealmente enfileire e processe de forma assincrona), valide a assinatura antes de processar e deduplique por eventId antes de aplicar qualquer efeito colateral.