Primeiros Passos — PopinaFlow App Marketplace
Audiência: desenvolvedores brasileiros que querem construir aplicações sobre a plataforma PopinaFlow (ERP de restaurantes multi-tenant). Base URL pública:
https://popinaflow.alojaweb.onlineVersão da API:v1(path prefix/public/v1)
O que é o App Marketplace
O PopinaFlow expõe uma API pública e um marketplace de apps para que terceiros possam estender a plataforma — receber pedidos em tempo real, sincronizar cardápios, exportar dados fiscais para sistemas contábeis, automatizar atendimento via WhatsApp e muito mais.
Existem dois lados:
- Publisher (você) — registra uma App, declara escopos, hospeda um endpoint webhook e expõe alguma utilidade ao restaurante.
- Tenant (o restaurante) — instala sua App pelo painel
/t/:slug/admin/marketplace, autoriza escopos, e a partir daí sua App passa a receber webhooks e a chamar a API pública em nome dele.
┌─────────────────┐ install + scopes ┌─────────────────┐
│ Tenant Admin │ ─────────────────────► │ PopinaFlow │
│ (restaurante) │ ◄─── accessToken ───── │ (marketplace) │
└─────────────────┘ └────────┬────────┘
│
webhook signed POST │
▼
┌─────────────────┐
│ Sua App (você) │
│ webhookUrl │
└────────┬────────┘
│
Bearer accessToken
▼
┌─────────────────┐
│ /public/v1/... │
└─────────────────┘Como me tornar publisher
No MVP, o registro de publisher é manual — assinatura de um termo de uso de API e provisionamento de uma App em draft. Para participar:
- Preencha o formulário de inscrição em https://popinaflow.alojaweb.online/devs (formulário externo no Google Forms; será substituído por self-service em release futura).
- Aguarde aprovação (≤ 5 dias úteis). O time de plataforma cria sua App com
status='draft', gera umclientId(UUID v4 público) e umclientSecret(mostrado uma única vez ao publicador). - Você submete o
webhookUrl, ooauthRedirectUri, a lista de escopos solicitados e descreve em português o que sua App faz. - Após revisão (validação de escopo mínimo necessário + segurança básica), a App passa para
status='published'e fica visível emGET /t/:slug/admin/marketplace/apps.
Princípio do menor privilégio: pedir mais escopos do que o necessário causa rejeição na revisão. Veja
scopes.mdantes de submeter.
Fluxo de ponta a ponta
1. PUBLISHER (você) — registra a App com webhookUrl + escopos + redirect.
2. TENANT (restaurante) — visita /t/<slug>/admin/marketplace, abre sua App,
clica em "Instalar", escolhe quais escopos conceder.
3. POPINAFLOW — emite um accessToken (mostrado UMA vez ao tenant) e um
signingSecret interno por instalação. Persiste o hash bcrypt do token.
4. TENANT — copia o accessToken e cola na configuração da sua App.
5. SUA APP — daqui pra frente:
a) recebe HTTP POSTs assinados em webhookUrl quando eventos ocorrem,
b) faz chamadas a /public/v1/* com o accessToken em Authorization.Veja oauth.md para detalhes do install flow e webhooks.md para verificação de assinatura.
Hello World
O exemplo mais curto que comprova que sua integração está respirando: listar pedidos em aberto do restaurante.
1. Tenant instala sua App e te entrega o accessToken
Quando o admin do tenant clica em "Instalar" na sua App, o backend retorna:
{
"installation": {
"_id": "65f1c8a2e4b0a8d1e5c3b9a7",
"tenant": "65a0b1c2d3e4f5a6b7c8d9e0",
"app": "65a0b1c2d3e4f5a6b7c8d9e1",
"scopes": ["orders.read", "webhooks.subscribe"],
"status": "active",
"createdAt": "2026-05-23T14:21:00.000Z"
},
"accessToken": "9b7f6e5d4c3b2a190f8e7d6c5b4a3928...128 hex chars total"
}CRÍTICO: O campo
accessTokené retornado em texto plano uma única vez. O servidor armazena apenas o hash bcrypt. Se o tenant fechar essa tela sem copiar, ele precisa revogar e reinstalar. Comunique isso claramente no seu onboarding.
2. Sua App chama a API pública
Com o accessToken em mãos:
curl -X GET 'https://popinaflow.alojaweb.online/public/v1/orders?status=preparing' \
-H 'Authorization: Bearer 9b7f6e5d4c3b2a190f8e7d6c5b4a3928...'Resposta (truncada):
[
{
"_id": "65f1d0a2e4b0a8d1e5c3b9b1",
"orderNumber": "20260523-A3F9C12E45",
"status": "preparing",
"total": 87.50,
"items": [
{ "name": "Pizza Margherita", "quantity": 1, "price": 52.00 },
{ "name": "Refrigerante 350ml", "quantity": 2, "price": 17.75 }
],
"createdAt": "2026-05-23T14:18:42.000Z"
}
]3. Sua App recebe um webhook quando o status muda
Quando o pedido sai da cozinha, o PopinaFlow faz POST para o webhookUrl registrado:
POST /seu/webhook HTTP/1.1
Host: sua-app.com.br
Content-Type: application/json
X-PopinaFlow-Event: order.statusChanged
X-PopinaFlow-Signature: sha256=4f8b3a...
X-PopinaFlow-Delivery: 65f1d8b2e4b0a8d1e5c3b9c3
{
"orderNumber": "20260523-A3F9C12E45",
"previousStatus": "preparing",
"status": "ready",
"tenantId": "65a0b1c2d3e4f5a6b7c8d9e0",
"timestamp": "2026-05-23T14:31:08.000Z"
}Você deve verificar a assinatura HMAC antes de processar (veja webhooks.md). E deve responder 2xx em menos de 10 segundos — processamento pesado vai para fila assíncrona do seu lado.
Próximos passos
| Tópico | Documento |
|---|---|
| Como o install flow funciona (não é OAuth2 padrão) | oauth.md |
| Como verificar assinaturas HMAC e tratar retries | webhooks.md |
| Lista completa de escopos disponíveis | scopes.md |
| Limites de uso e headers de throttle | rate-limits.md |
Suporte
- Status da plataforma: https://popinaflow.alojaweb.online/status (em breve)
- Tickets de desenvolvedor: abra via
/superadmin/ticketsou pelo email do termo de uso de API. - Quebra de contrato: mudanças incompatíveis na
/public/v1requerem deprecação de 90 dias com aviso emSunset:header. Vejarate-limits.mdpara a política de versionamento.