Subscription Blueprint

SaaS (Subscrições)

Facturação recorrente com Factura-Recibo (FR) - emitida automaticamente em cada ciclo de renovação, com idempotência para retries seguros.

Gatilho de renovação

Cron job ou webhook do teu sistema de pagamentos dispara no dia de renovação.

Emissão da FR

customers.ensure → products.create → invoices.create - 3 chamadas, factura certificada.

Entrega ao assinante

invoices.send() envia o PDF por email. Ou recebe o evento invoice.issued via webhook.

Idempotência · O campo idempotencyKey garante que retries no mesmo ciclo (ex: falha de rede, timeout) não criam facturas duplicadas. Usa sempre um identificador ligado ao ciclo: renewal_2026-05.
TypeScript
import { createVeroClient } from '@veroao/node'

const vero = createVeroClient() // lê VERO_API_KEY do ambiente
const ORG_ID = process.env.VERO_ORG_ID!

// Chamado no dia de renovação do plano
async function billRenewal(user: { id: string; name: string; nif: string; phone: string; email: string; address: string; city: string }, plan: { code: string; name: string; description: string; price: number }, cycleId: string) {
  // 1. Garantir cliente
  const customer = await vero.customers.ensure(ORG_ID, {
    externalId: user.id,
    name: user.name,
    taxId: user.nif,
    phone: user.phone,
    email: user.email,
    addressLine1: user.address,
    city: user.city,
  })

  // 2. Garantir produto (plano de subscrição)
  const product = await vero.products.create(ORG_ID, {
    code: plan.code,
    name: plan.name,
    description: plan.description,
    unitPrice: plan.price, // kwanzas × 100
    taxRate: 14,
    unitOfMeasure: 'UN',
  })

  // 3. Emitir FR (Factura-Recibo = pagamento imediato)
  //    idempotencyKey garante que retries no mesmo ciclo não criam facturas duplicadas
  const invoice = await vero.invoices.create(ORG_ID, {
    customerId: customer.id,
    documentType: 'FR',
    items: [{
      description: product.name,
      quantity: 1,
      unitPrice: product.unitPrice,
      taxRate: product.taxRate,
      productId: product.id,
    }],
    idempotencyKey: `renewal_${cycleId}`,
  })

  // 4. Enviar PDF por email (opcional - pode usar webhook invoice.issued)
  await vero.invoices.send(ORG_ID, invoice.id)

  return invoice
}

Resposta (201 Created)

JSON
{
  "id": "b2c3d4e5-...",
  "number": "FR FR6326S47071N/1",
  "documentType": "FR",
  "status": "paid",
  "subtotal": 2192982,
  "taxAmount": 307018,
  "total": 2500000,
  "currency": "AOA",
  "atcud": "ABCD1234-7",
  "pdfUrl": "https://storage.vero.ao/invoices/b2c3d4e5.pdf",
  "issuedAt": "2026-05-19T00:00:00.000Z"
}