Referência da API

Base URL https://api.broski.pt · Autenticação Authorization: Bearer sk_live_… · Valores em cêntimos · Importe o openapi.yaml no Postman ou Insomnia.

POST/v1/orders — Criar pedido

Cria uma cobrança MB WAY ou Multibanco. Header Idempotency-Key obrigatório (1–128 caracteres): reenvio com a mesma chave e o mesmo corpo devolve a resposta original com Idempotent-Replay: true; corpo diferente → 409. Retenção garantida ≥ 24 h.

CampoTipoRegras
amountintObrigatório, em cêntimos. MB WAY: 50–500000 (€0,50–€5.000). Multibanco: 1–100000000.
methodstringObrigatório: mbway | multibanco.
phonestringObrigatório p/ MB WAY. Telemóvel PT: +3519XXXXXXXX.
external_referencestringObrigatório, único por conta: A–Z a–z 0–9 _ - . (1–128).
currencystringOpcional; apenas EUR.
descriptionstringOpcional (≤140). Nome do produto — aparece no seu painel; não é devolvido pela API.
customerobjetoOpcional: name, email, phone, nif (9 dígitos, validado se presente). Armazenado cifrado; nunca devolvido.

Campo desconhecido no JSON → 400 invalid_json (validação estrita).

Exemplo — MB WAY (201)
curl https://api.broski.pt/v1/orders \
  -H "Authorization: Bearer sk_live_..." \
  -H "Idempotency-Key: pedido-1042-v1" \
  -H "Content-Type: application/json" \
  -d '{"amount":1990,"method":"mbway","phone":"+351912345678",
       "external_reference":"pedido-1042","description":"Curso de tráfego"}'

{"id":"ord_9f2c1ab34d","status":"pending","amount":1990,"currency":"EUR",
 "method":"mbway","external_reference":"pedido-1042","livemode":true,
 "created_at":"2026-07-16T14:03:07Z"}

O cliente confirma no app MB WAY; a confirmação chega em segundos via webhook order.paid.

Exemplo — Multibanco (201, com voucher)
{"id":"ord_4c77e0b1aa","status":"awaiting_payment","amount":4990,"currency":"EUR",
 "method":"multibanco","external_reference":"pedido-1043","livemode":true,
 "created_at":"2026-07-16T14:05:11Z",
 "multibanco":{"entity":"11249","reference":"123 456 789","amount":4990,
               "expires_at":"2026-07-19T14:05:11Z"}}

Exiba entidade, referência e valor ao cliente — ele paga no homebanking ou numa caixa Multibanco, em geral em até alguns dias. awaiting_payment é um estado normal e duradouro.

Erros específicos: 402 payment_failed (não iniciou; o pedido é desfeito e a external_reference pode ser reutilizada), 409 external_reference_taken, 400 amount_below_fee, 400 currency_not_supported.

GET/v1/orders/{id} — Consultar pedido

Devolve o pedido completo (mesmo shape do POST; paid_at presente quando pago). Pedido inexistente ou de outra conta404 resource_not_found.

GET/v1/orders — Listar pedidos

Página de até 25, do mais novo ao mais antigo. Filtros: status (enum de status), method. Paginação por cursor: passe starting_after=<id do último>. Cursor desconhecido é ignorado (devolve a primeira página). Filtro fora do enum → 400.

{"data":[{"id":"ord_…","status":"paid","amount":1990,"method":"mbway",
  "external_reference":"pedido-1042","livemode":true,
  "created_at":"…","paid_at":"…"}], "has_more":true}

O item da listagem é um resumo (sem currency nem multibanco). Para o objeto completo, consulte o pedido individual.

POST/v1/orders/{id}/refunds — Estornar

Corpo JSON obrigatório — envie {} para estorno total do restante, ou {"amount": 500, "reason": "…"} para parcial (amount 0 ou ausente = total). Parciais são repetíveis até o total (o pedido vira refunded só no total acumulado). Estornos não aceitam Idempotency-Key: após um timeout, confira o pedido antes de repetir — repetir um parcial estorna duas vezes.

201 → {"id":"ref_5ba01cd922","amount":500,"status":"succeeded"}

Erros: 409 order_not_paid, 400 refund_exceeds_amount, 404 resource_not_found.

Webhooks

Cadastre a URL HTTPS no painel (Configurações → Webhooks) — o segredo whbroski_… é exibido uma única vez. Eventos: order.awaiting_payment, order.paid, order.failed, order.expired, order.refunded (lista vazia no cadastro = todos). O endpoint pode receber tipos além destes — responda 2xx e ignore type desconhecido.

POST (sua URL)
Content-Type: application/json
Broski-Signature: t=1750000000,v1=5fb448226598b14dea45ff94ee317c2c…

{"id":"evt_ab12cd34ef","type":"order.paid","created":1750000000,
 "data":{"object":{"id":"ord_9f2c1ab34d","status":"paid","amount":1990,
   "currency":"EUR","method":"mbway","external_reference":"pedido-1042",
   "livemode":true,"created_at":"…","paid_at":"…"}}}

Códigos de erro

Toda resposta de erro usa o envelope {"error":{"type","code","message","param?"}} com mensagem em PT-BR.

HTTPcodeQuando
400validation_failedCampo inválido (veja param quando presente).
400invalid_jsonJSON malformado ou campo desconhecido.
400currency_not_supportedMoeda diferente de EUR.
400amount_below_feeValor menor que a tarifa aplicável.
400refund_exceeds_amountEstorno maior que o restante.
401unauthorizedChave ausente, inválida ou revogada.
402payment_failedO pagamento não pôde ser iniciado.
404resource_not_foundRecurso inexistente (ou de outra conta).
409external_reference_takenReferência já usada.
409idempotency_key_reusedMesma Idempotency-Key com corpo diferente.
409order_not_paidEstorno de pedido não pago.
413body_too_largeCorpo acima de 64 KB.
429rate_limitedAcima de 120 req/min por chave.
500internal_errorErro nosso — tente novamente; persiste? fale com o suporte.