v1.3.0 · atualizado 2026-05-18 · acesso público · JSON ⇩
Documentação técnica do padrão Partner Integrations do Rally de Vendas. Use esse spec pra construir integrações bidirecionais com o Rally: transportadoras, fulfillment, ERP, BI, atendimento, AI, etc.
Referência viva em produção: Frete.Center auto-despacho Flex Mercado Livre.
O padrão Partner Integrations conecta um serviço externo ao Rally com:
Todos os webhooks Rally ↔ parceiro usam HMAC SHA-256 sobre o body raw. O secret de 64 chars é compartilhado nos dois lados via .env.
X-Rally-Signature: sha256=<hex_digest>
X-Rally-Timestamp: <unix_seconds>
Content-Type: application/json
signature = "sha256=" + hex(hmac_sha256(SHARED_SECRET, RAW_BODY))
Toda request precisa de timestamp dentro de ±300s do time() do receptor. Fora disso = 401 stale_timestamp.
Esses três endpoints estão prontos no Rally e esperam HMAC + timestamp:
| Endpoint | Body | Quando enviar |
|---|---|---|
POST /webhooks/{partner-name}/status |
{
"rally_user_id": "...",
"dispatch_id": "your_external_id",
"status": "accepted|picked_up|in_transit|delivered|refused|cancelled",
"note": "..."
} |
Job mudou de status |
POST /webhooks/{partner-name}/invite-code |
{
"code": "ABC12345",
"carrier_id": "...",
"carrier_name": "...",
"expires_at": "2026-05-21T13:00:00-03:00"
} |
Você gerou novo código (push) |
POST /webhooks/{partner-name}/payment-confirmed |
{
"rally_user_id": "...",
"rally_dispatch_id": "..."
} |
Você confirmou PIX recebido |
Substitua {partner-name} pelo identificador do seu sistema (ex: frete-center, shopee-flash). Combine com a equipe Rally na hora do onboarding.
O Rally vai consumir esses endpoints com a mesma autenticação HMAC (você verifica do mesmo jeito que o Rally verifica os seus webhooks).
| Método + Path (sugestão) | Body / Query | Retorno esperado |
|---|---|---|
GET /api/v1/carriers/by-invite-code?code=XXX |
code (8 chars) |
{
"carrier_id": "...",
"carrier_name": "...",
"pix_key": "...",
"pix_key_type": "cnpj|email|phone|random",
"logo_url": "https://...",
"expires_at": "..."
} |
GET /api/v1/quote?carrier_id&cep_o&cep_d&peso_g&pacotes |
parâmetros query | {
"price": 12.50,
"currency": "BRL",
"eta_hours": 2
} |
POST /api/v1/dispatch |
{
"external_order_id": "...",
"ml_shipment_id": "...",
"carrier_id": "...",
"pickup_point_id": "...",
"buyer_address": {...},
"package": {"weight_g": 500, "dimensions_cm": [20,15,5]},
"callback_url": "https://rallydevendas.com.br/webhooks/{name}/status",
"meta": {"rally_user_id": "...", "rally_dispatch_id": "..."}
} |
{
"dispatch_id": "...",
"quoted_price": 12.50,
"eta": "2026-05-18T16:00:00Z"
} |
POST /api/v1/dispatch/{id}/cancel |
— | { "ok": true } |
GET /api/v1/dispatch/{id} |
— | { "dispatch_id": "...", "status": "...", "last_event_at": "..." } |
1. Você gera código no seu painel: POST your-system → "ABC12345"
2. Webhook: POST /webhooks/{name}/invite-code (Rally cacheia)
3. Cliente cola código no Rally: https://painel.rally.com/transportadoras/vincular?code=ABC12345
4. Rally chama: GET /api/v1/carriers/by-invite-code?code=ABC12345
← você retorna metadata (pix, nome, etc.)
5. Vínculo criado.
6. Cliente vende algo no ML (logistic_type=self_service).
7. Webhook ML → Rally → Rally chama: POST /api/v1/dispatch
← você retorna { dispatch_id, quoted_price }
8. Você notifica seu motoboy (WA/push).
9. Motoboy aceita → você manda: POST /webhooks/{name}/status { status: "accepted" }
10. Motoboy coleta → POST /webhooks/{name}/status { status: "picked_up" }
11. ... in_transit → delivered
12. Toda semana o Rally consolida dispatches abertos em fechamento PIX.
13. Cliente paga via PIX direto, anexa comprovante no Rally.
14. Você verifica o PIX recebido no seu banco.
15. Você manda: POST /webhooks/{name}/payment-confirmed { rally_dispatch_id }
→ Rally marca como pago.
| Code | Erro | Causa |
|---|---|---|
| 400 | invalid_json | Body não é JSON parseável |
| 401 | invalid_signature | HMAC não bate. Verificar secret + assinatura sobre body raw exato |
| 401 | stale_timestamp | Timestamp fora da janela ±5min. Sincronizar relógio do servidor (NTP) |
| 422 | missing_required_fields | Body válido mas campo obrigatório ausente. Conferir spec do endpoint |
| 503 | webhook_secret_missing | Rally não está configurado (FRETECENTER_INBOUND_SECRET ausente). Pedir Rally pra setar |
SECRET="seu-secret-64-chars-aqui"
BODY='{"rally_user_id":"user_abc","dispatch_id":"job_xyz","status":"accepted","note":"motoboy a caminho"}'
TS=$(date +%s)
SIG="sha256=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $2}')"
curl -X POST https://rallydevendas.com.br/webhooks/frete-center/status \
-H "Content-Type: application/json" \
-H "X-Rally-Signature: $SIG" \
-H "X-Rally-Timestamp: $TS" \
--data-raw "$BODY"
GET /api/v1/health retorna 200 + versão