Skip to content

Bubble Dev — Passo a passo

Você é o dev Bubble, vai conectar Blueprintt ao backend Blu × Omie. Aqui está o caminho mais curto: setup → trigger automático → botões de ops → writeback → testar local.

  1. Base URL.

    • Staging: https://staging-blu-omie.devmagic.com.br
    • Local dev (com ngrok): https://<your-tunnel>.ngrok-free.app
  2. Headers obrigatórios em toda chamada Bubble → Backend.

    Authorization: Bearer <BUBBLE_API_KEY>
    Idempotency-Key: <uuid>
    X-Request-Timestamp: <epoch ms>
    Content-Type: application/json
    • BUBBLE_API_KEY vive em Bubble Plugin Settings → API Connector (NÃO commitar, NÃO colar em workflow visível).
    • Idempotency-Key — gerar via expression Bubble (Current date/time:formatted as + suffix) ou plugin uuid. Garante que retry não duplica OS na Omie.
    • X-Request-TimestampCurrent date/time:extract UNIX × 1000. Backend tolera ±5min de drift.
  3. Instalar API Connector. Plugin oficial “API Connector”. Add a new API com nome Blueprintt × Omie Backend. Auth: Private key in header, Key name Authorization, Key value Bearer [API_KEY] ([API_KEY] vira parâmetro do plugin).

  4. Importar endpoints. Bubble não importa OpenAPI nativo — cada endpoint vira 1 API Call configurada manualmente. Abra docs/openapi.yaml da staging como referência (1 path × method = 1 API Call). Detalhe completo do mapping está em docs/bubble-api-connector.md.

  5. Testar conectividade. Configure uma call GET /healthz. Clique Initialize call — deve retornar 200. Se der 401, Bearer está errado. Se der CORS / timeout, base URL está errada.

Trigger automático — workflow “Pedido criado”

Section titled “Trigger automático — workflow “Pedido criado””

O único webhook automático que o Bubble dispara. Chamado quando o type order é criado.

  1. Workflow trigger. Database Trigger Event → When a new order is created.

  2. Action: API Call → sync-omie. Use a API call POST /v1/orders/{bubble_order_id}/sync-omie. Path param bubble_order_id = Current order's unique id.

  3. Body (JSON). Payload mínimo:

    {
    "company": "aabc",
    "trigger_source": "auto"
    }

    company sempre "aabc" na Versão Atual. LNG está fora de escopo — não enviar.

  4. Headers. Adicionar:

    Idempotency-Key: <Current order's unique id>:sync

    Key fixa por pedido (sem timestamp). Se o workflow Bubble retentar, backend reconhece a key e retorna o resultado anterior sem reabrir OS na Omie.

  5. Sucesso esperado. HTTP 202 ou 200. Backend já escreveu status_pedido e status_faturamento via Data API (ver próxima seção). Não precisa ler o response — Current order já reflete o novo estado em ~1s.

Cada botão de ação backoffice chama um endpoint dedicado. Bubble não tem lógica fiscal — só dispara a call e mostra o resultado quando status_faturamento mudar.

Quando usar. NFS-e falhou (rate-limit Omie, REDUNDANT, erro Prefeitura). Botão “Tentar emitir NF novamente” na tela do pedido.

Endpoint. POST /v1/orders/{bubble_order_id}/retry

Body.

{
"reason": "manual retry by <Current User's email>"
}

Headers. Idempotency-Key: <order_id>:retry:<Current date/time:formatted as UNIX> — cada clique tem key única; sem o timestamp, backend bloqueia segundo clique.

Sucesso. 202 — backend re-enfileira job de emissão. status_faturamento volta a agendado ou faturando. Falha. 409 se já está sendo processado. 4xx se estado inválido (ex.: NF já emitida).

Writeback — campos escritos pelo backend

Section titled “Writeback — campos escritos pelo backend”

Backend faz PATCH no Bubble Data API atualizando estes campos. Você não escreve nestes — backend é dono. Bubble só lê pra exibir.

Campo BubbleTipoValores possíveisQuando atualiza
status_pedidotext (Option Set ns_status_pedido)aguardando_pagamento, confirmado, canceladoPagar.me webhook + ordem cancelada
status_faturamentotext (Option Set ns_status_faturamento)aguardando_pagamento, aguardando_confirmacao, bloqueado_dia25, agendado, faturando, nf_emitida, nf_cancelada, erro_faturamento, faturamento_manualCada transição do billing state machine
omie_os_idtextUUID Omie OSApós CreateOS
omie_nfse_idtextUUID Omie NFS-eApós EmitirNFSe
numero_nfsetextNúmero NFS-e PrefeituraApós callback Omie
link_nfsetext (URL)PDF NFS-eApós callback Omie

Crie estes dois Option Sets exatamente com estes valores antes de configurar os campos:

ns_status_pedido (3 valores):

aguardando_pagamentoconfirmadocancelado

ns_status_faturamento (9 valores):

aguardando_pagamentoaguardando_confirmacaobloqueado_dia25agendadofaturandonf_emitidanf_canceladaerro_faturamentofaturamento_manual

Strings devem casar exatamente (lowercase, underscore) — backend escreve essa forma literal.

Pagar.me webhook — backend recebe direto

Section titled “Pagar.me webhook — backend recebe direto”

Pagar.me charge.* events NÃO vão pro Bubble. Vão pro backend (POST /webhooks/pagarme) com validação HMAC. Backend escreve status_pedido no Bubble após confirmar pagamento.

Do ponto de vista Bubble, o webhook foi processado quando você observa:

  • status_pedido muda pra confirmado (backend escreveu via PATCH Data API).
  • status_faturamento evolui (aguardando_pagamentoagendado ou bloqueado_dia25).
  • payment record atualizado com payment_method + paid_at (backend escreve).

Testar local — apontar Bubble staging pro seu backend

Section titled “Testar local — apontar Bubble staging pro seu backend”
  1. Rodar backend local. cd backend && make dev (uvicorn em :8000).

  2. Expor via ngrok. ngrok http 8000. Copy URL https://abc123.ngrok-free.app.

  3. Trocar base URL no API Connector. Substituir https://staging-blu-omie.devmagic.com.br pela sua URL ngrok. Re-initialize as calls que mudaram path.

  4. Disparar pedido de teste no Bubble staging. Use um backoffice pessoal pra não poluir tickets reais.

  5. Observar logs. Terminal do uvicorn mostra request entrando + structlog estruturado por correlation id. DB local é sqlite tmp (auto-criado).

  6. Voltar pra staging. Após terminar, trocar base URL de volta. Não esqueça — clientes reais ficarão tentando hit no seu laptop.

EndpointQuandoIdempotency-Key sugerida
POST /v1/orders/{id}/sync-omieTrigger automático ao criar pedido<order_id>:sync
POST /v1/orders/{id}/retryBotão “Tentar emitir NF”<order_id>:retry:<timestamp>
POST /v1/orders/{id}/cancel-nfBotão “Cancelar NF”<order_id>:cancel-nf
POST /v1/orders/{id}/mark-nf-manualBotão “Marcar manual”<order_id>:mark-manual
POST /v1/orders/{id}/approve-billing-holdAprovar hold backoffice<order_id>:approve-hold
POST /v1/orders/{id}/override-day25Override dia 25<order_id>:override-day25
POST /v1/orders/{id}/transfer-ccTransferir carta de crédito<order_id>:transfer-cc:<destination_id>
POST /v1/orders/{id}/use-ccAplicar carta de crédito<order_id>:use-cc:<cc_id>
GET /v1/orders/{id}/statusPolling status (opcional)n/a
GET /healthzLivenessn/a
  • 401 Unauthorized — Bearer token errado ou expirado. Confirmar Authorization header no API Connector + key no plugin settings.
  • 409 ConflictIdempotency-Key já foi processada. Use timestamp ou UUID nova por clique em endpoints que aceitam re-execução (retry, transfer-cc, use-cc).
  • 425 Too Early — Omie rate-limit ban (31min). Backend retry automático. Não tratar como erro. UI mostra spinner / “Sincronizando…” até status_faturamento evoluir.
  • 5xx — backend down ou conexão DB perdeu. Retry com backoff exponencial (1s, 2s, 4s, 8s); se persistir, alertar ops.
  • Timeout 30ssync-omie síncrono normal leva ~3s; >10s indica problema. Cancela a call e mude pra polling em GET /v1/orders/{id}/status.
  • Webhook Pagar.me chega no Bubble — bug — está roteado errado. Reportar (pendência BUBBLE-1); workflow no Bubble deve ser removido ou desabilitado.