wallet PayZap

🇦🇴 Pioneiros em Angola

© 2026 PayZap · Primeira Fintech de Pagamentos por WhatsApp em Angola

PayZap API

Documentação REST para links de pagamento com autenticação por API Key

A PayZap API permite criar links de pagamento, partilhá-los com clientes e acompanhar o estado de cada cobrança por polling. A integração é simples, sem webhooks, com foco em operações server-to-server.

REST JSON Bearer API Key Polling 5s Sem webhooks Moeda AOA

Base URL

https://api.payzap.ao/v1

Header obrigatório

Authorization: Bearer sk_live_xxxxxxxxxxxxx

Resposta padrão

Content-Type: application/json

1. Visão Geral

O que é a PayZap API

A PayZap API é uma API REST para geração e gestão de links de pagamento. Ela foi desenhada para equipas técnicas que precisam criar cobranças programaticamente, enviar o link ao cliente e confirmar o pagamento consultando o estado da transação via polling.

O conceito central é o payment link: um recurso único com valor, descrição e data de expiração. A sua aplicação cria o link, entrega ao cliente por qualquer canal e depois consulta o estado até o pagamento ficar concluído ou expirar.

Canal

WhatsApp e SMS

Envie o link diretamente na conversa com o cliente.

Produto

Apps e ERPs

Gere links a partir de pedidos, faturas ou carrinhos.

Operação

Backoffice

Concilie pagamentos e consulte saldo disponível.

Casos de uso comuns

Vendas por WhatsApp, links enviados por e-mail, checkout sem carrinho e integrações com apps internos.

Formato das respostas

Todas as respostas usam JSON e datas em ISO 8601. O campo do link retornado pela API chama-se payment_url.

Escopo atual da v1

A moeda suportada atualmente é AOA e a confirmação é feita por polling, sem webhooks.

2. Base URL

Endpoint base da API

Todas as rotas apresentadas nesta documentação partem da base URL abaixo. Em ambiente de produção, o padrão esperado é:

Produção

https://api.payzap.ao/v1

Base URL configurada neste ambiente

https://api.payzap.ao/v1

3. Autenticação

Como autenticar as requisições

Todas as requisições exigem uma API Key enviada no header Authorization no formato Bearer. Para integrações server-to-server, use preferencialmente uma chave sk_live.

Header

Authorization: Bearer {API_KEY}
curl -X GET https://api.payzap.ao/v1/balance \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxx"

Erros comuns

Token sem o prefixo Bearer, chave inválida, chave desativada ou header ausente.

Resposta típica de erro

A API responde com 401 Unauthorized e o objeto error em JSON.

Recomendação

Nunca envie a API Key diretamente do browser para a PayZap API. Faça isso a partir do seu backend.

4. Fluxo de Pagamento

Fluxo completo da integração

Passo 1

Criar o link

A sua aplicação cria um payment link com valor, descrição e validade.

Passo 2

Enviar ao cliente

Partilhe o campo payment_url por WhatsApp, e-mail, SMS ou no seu frontend.

Passo 3

Cliente paga

O cliente abre o link, executa o pagamento e a PayZap atualiza o estado da cobrança.

Passo 4

Polling de status

O integrador consulta GET /payment-links/:id/status até encontrar um estado terminal.

Como usar polling corretamente

A PayZap API não envia webhooks. Depois de criar o link, use polling no endpoint de status com intervalo de 5 segundos. Se a sua integração não precisa de atualização tão rápida, pode subir para 10 segundos para reduzir carga.

5. Endpoints

Referência completa da API

POST /payment-links 5.1 Criar Link de Pagamento

Cria um novo link de pagamento. O campo description é obrigatório nesta versão. Para definir expiração absoluta no seu sistema, calcule a diferença em minutos e envie em expires_in_minutes.

Campo Tipo Obrigatório Descrição
amount number Sim Valor da cobrança em AOA. Exemplo: 25000 para Kz 25.000.
currency string Não Moeda do pagamento. Padrão: AOA. Outras moedas não são aceites na v1.
description string Sim Descrição legível do pagamento, por exemplo o nome do pedido ou da venda.
customer_name string Não Nome do cliente para referência interna e exibição.
customer_email string Não E-mail do cliente, útil para conciliação e relatórios.
expires_in_minutes number Não Validade relativa do link. Use este campo no lugar de expires_at na v1.
customer_phone string Não Telefone do cliente.
project_id string Não Identificador do projeto, loja ou aplicação de origem.
metadata object Não Objeto livre para correlacionar a cobrança com os dados do seu sistema.

Exemplo de request

{
  "amount": 25000,
  "currency": "AOA",
  "description": "Pedido #1024 - Camisa oficial",
  "customer_name": "Maria Fernandes",
  "customer_email": "maria.fernandes@email.com",
  "customer_phone": "923000111",
  "expires_in_minutes": 60,
  "project_id": "loja_online",
  "metadata": {
    "order_id": "1024",
    "channel": "whatsapp"
  }
}

Exemplo de response

{
  "id": "8ab7f52c-b7e4-4bc6-bf08-0c9fe98d8b9c",
  "amount": 25000,
  "currency": "AOA",
  "description": "Pedido #1024 - Camisa oficial",
  "customer_name": "Maria Fernandes",
  "customer_email": "maria.fernandes@email.com",
  "customer_phone": "923000111",
  "source_channel": "api",
  "status": "pending",
  "payment_url": "https://payzap.ao/customer/checkout/pedido-1024-camisa-oficial-a81f90c2",
  "expires_at": "2026-04-10T15:00:00.000Z",
  "paid_at": null,
  "created_at": "2026-04-10T14:00:00.000Z",
  "project_id": "loja_online",
  "metadata": {
    "order_id": "1024",
    "channel": "whatsapp"
  }
}

Status possíveis

201 Created quando o link é criado com sucesso.

Falha de validação

400 Bad Request quando faltar amount, description ou a moeda for inválida.

GET /payment-links 5.2 Listar Links de Pagamento

Retorna uma lista paginada de links criados pela conta autenticada. A API usa limit e offset. Se o seu frontend trabalhar com page, calcule offset = (page - 1) * limit.

Query param Tipo Obrigatório Descrição
limit number Não Quantidade por página. Mínimo 1, máximo 100. Padrão: 10.
offset number Não Deslocamento para paginação. Padrão: 0.
status string Não Filtra por pending, paid, expired ou failed.
source_channel string Não Filtra por canal de origem. Para esta API, o valor usual é api.
created_after datetime Não Filtra por data ISO 8601 a partir da qual o recurso foi criado.
{
  "data": [
    {
      "id": "8ab7f52c-b7e4-4bc6-bf08-0c9fe98d8b9c",
      "amount": 25000,
      "currency": "AOA",
      "description": "Pedido #1024 - Camisa oficial",
      "customer_name": "Maria Fernandes",
      "customer_email": "maria.fernandes@email.com",
      "customer_phone": "923000111",
      "source_channel": "api",
      "status": "pending",
      "payment_url": "https://payzap.ao/customer/checkout/pedido-1024-camisa-oficial-a81f90c2",
      "expires_at": "2026-04-10T15:00:00.000Z",
      "paid_at": null,
      "created_at": "2026-04-10T14:00:00.000Z",
      "project_id": "loja_online",
      "metadata": {
        "order_id": "1024"
      }
    }
  ],
  "pagination": {
    "total": 42,
    "limit": 10,
    "offset": 0
  }
}
GET /payment-links/:id 5.3 Ver Detalhes do Link

Retorna os detalhes de um link específico. O parâmetro :id aceita tanto o UUID interno como o slug do link. Nesta API pública, o detalhe devolve os dados normalizados da cobrança; para monitorização frequente, prefira o endpoint de status.

{
  "id": "8ab7f52c-b7e4-4bc6-bf08-0c9fe98d8b9c",
  "amount": 25000,
  "currency": "AOA",
  "description": "Pedido #1024 - Camisa oficial",
  "customer_name": "Maria Fernandes",
  "customer_email": "maria.fernandes@email.com",
  "customer_phone": "923000111",
  "source_channel": "api",
  "status": "paid",
  "payment_url": "https://payzap.ao/customer/checkout/pedido-1024-camisa-oficial-a81f90c2",
  "expires_at": "2026-04-10T15:00:00.000Z",
  "paid_at": "2026-04-10T14:12:48.000Z",
  "created_at": "2026-04-10T14:00:00.000Z",
  "project_id": "loja_online",
  "metadata": {
    "order_id": "1024"
  }
}

Se precisa consultar apenas o estado atual, use GET /payment-links/:id/status. Ele é mais apropriado para polling e devolve instruções úteis em polling.recommended_interval_seconds.

GET /payment-links/:id/status 5.4 Ver Status do Link (Polling)

Endpoint otimizado para polling. Pode ser chamado com ?sync=true para pedir sincronização com o gateway antes da resposta.

{
  "id": "8ab7f52c-b7e4-4bc6-bf08-0c9fe98d8b9c",
  "status": "pending",
  "paid_at": null,
  "expires_at": "2026-04-10T15:00:00.000Z",
  "last_checked_at": "2026-04-10T14:00:05.000Z",
  "polling": {
    "mode": "polling",
    "terminal": false,
    "recommended_interval_seconds": 5,
    "synced_with_gateway": true,
    "sync_message": "Gateway status synchronized"
  }
}

Status esperados

pending, paid, expired e, em casos de falha no gateway, failed.

Quando parar o polling

Pare quando polling.terminal for true ou quando o estado for terminal no seu backend.

POST /payment-links/:id/expire 5.5 Expirar Link

Expira manualmente um link ainda não pago. Links pagos não podem ser expirados.

{
  "id": "8ab7f52c-b7e4-4bc6-bf08-0c9fe98d8b9c",
  "status": "expired",
  "message": "Link expirado com sucesso"
}
GET /balance 5.6 Ver Saldo

Consulta o saldo agregado da conta autenticada, incluindo saldo disponível, pendente e total movimentado.

{
  "available_balance": 125000,
  "pending_balance": 15000,
  "currency": "AOA",
  "total_earned": 520000,
  "last_updated": "2026-04-10T14:00:00.000Z"
}

6. Estados de Pagamento

Como interpretar cada estado

pending

O link foi criado e ainda aguarda pagamento. Continue em polling.

paid

Pagamento confirmado. Pare o polling e avance o pedido no seu backend.

expired

O link venceu ou foi expirado manualmente. Gere um novo link se necessário.

failed

Houve falha no processamento da tentativa de pagamento. Trate como estado terminal.

cancelled

Pode existir no seu domínio de negócio, mas não é um estado nativo devolvido pela PayZap API v1.

7. Sistema de Polling

Como verificar o pagamento sem webhooks

O polling é a estratégia oficial de confirmação nesta API. O fluxo recomendado é criar o link, armazenar o id internamente e chamar o endpoint de status até receber um estado terminal.

Frequência recomendada

Use 5 segundos como padrão. Se quiser uma abordagem mais leve, use 10 segundos.

Quando parar

Interrompa quando o estado for paid, expired ou failed.

Boa prática

Faça o polling no backend sempre que possível e notifique o frontend com o estado já validado.

const API_BASE = "https://api.payzap.ao/v1";
const API_KEY = process.env.PAYZAP_SECRET_KEY;

async function getPaymentStatus(id) {
  const response = await fetch(`${API_BASE}/payment-links/${id}/status?sync=true`, {
    headers: {
      Authorization: `Bearer ${API_KEY}`
    }
  });

  const payload = await response.json();

  if (!response.ok) {
    throw new Error(payload?.error?.message || "Falha ao consultar status");
  }

  return payload;
}

function waitForPayment(id, onPaid, onFinishedWithError) {
  const interval = setInterval(async () => {
    try {
      const status = await getPaymentStatus(id);

      if (status.status === "paid") {
        clearInterval(interval);
        onPaid(status);
        return;
      }

      if (["expired", "failed"].includes(status.status)) {
        clearInterval(interval);
        onFinishedWithError(status);
      }
    } catch (error) {
      clearInterval(interval);
      onFinishedWithError({ message: error.message });
    }
  }, 5000);

  return interval;
}

Evite sobrecarga

Não faça polling em múltiplas abas ou múltiplos workers para o mesmo pagamento. Centralize as consultas, use backoff quando houver erro temporário e pare o processo assim que encontrar um estado terminal.

8. Tratamento de Erros

Formato padrão de erros

Quando uma chamada falha, a PayZap API devolve um objeto error. Em erros de validação, os campos param e type também podem ser incluídos.

{
  "error": {
    "code": "invalid_request",
    "message": "O campo 'amount' é obrigatório",
    "param": "amount",
    "type": "validation_error"
  }
}
HTTP Código Quando acontece
400 invalid_request Dados inválidos, moeda não suportada, campo obrigatório ausente ou payload malformado.
401 unauthorized API Key inválida, não fornecida ou conta desativada.
404 not_found O recurso não foi encontrado para a conta autenticada.
429 too_many_requests Pode surgir em camadas de proteção de infraestrutura quando a integração ultrapassa o ritmo seguro de chamadas.
500 api_error Erro interno inesperado. Registe o erro e tente novamente com retry controlado.

9. Rate Limits

Limites operacionais recomendados

A versão atual da PayZap API não publica cabeçalhos padronizados de rate limit, mas para uma integração estável recomendamos trabalhar com um orçamento de até 100 requisições por minuto por API Key.

Ao exceder o limite

Reduza a frequência, implemente backoff exponencial e evite repetir polling agressivo para o mesmo pagamento.

Boa estratégia

Agrupe verificações no backend e não consulte /status em loops abaixo de 5 segundos.

10. Segurança

Recomendações obrigatórias de segurança

Nunca exponha a API Key

Não coloque sk_live em JavaScript público, apps mobile sem proxy ou páginas estáticas.

Use o backend como intermediário

Crie links e consulte estados a partir do seu servidor. O frontend deve falar com o seu backend.

HTTPS é obrigatório

Proteja credenciais e payloads usando apenas HTTPS entre cliente, backend e PayZap API.

11. Exemplos de Integração

Implementações práticas

Backend Node.js

import express from "express";

const app = express();
app.use(express.json());

app.post("/api/payments/create-link", async (req, res) => {
  const response = await fetch("https://api.payzap.ao/v1/payment-links", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${process.env.PAYZAP_SECRET_KEY}`
    },
    body: JSON.stringify({
      amount: req.body.amount,
      currency: "AOA",
      description: req.body.description,
      customer_name: req.body.customer_name,
      customer_email: req.body.customer_email,
      metadata: {
        order_id: req.body.order_id
      }
    })
  });

  const payload = await response.json();
  return res.status(response.status).json(payload);
});

Frontend seguro

async function createPaymentLink() {
  const response = await fetch("/api/payments/create-link", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      amount: 25000,
      description: "Pedido #1024 - Camisa oficial",
      customer_name: "Maria Fernandes",
      customer_email: "maria.fernandes@email.com",
      order_id: "1024"
    })
  });

  const data = await response.json();

  if (!response.ok) {
    throw new Error(data?.error?.message || "Falha ao criar link");
  }

  window.location.href = data.payment_url;
}

12. Boas Práticas

Recomendações para uma integração sólida

1. Valide pagamentos sempre no backend antes de liberar produto, serviço ou acesso.

2. Nunca confie apenas no frontend para decidir se um pagamento foi concluído.

3. Guarde o id do link e o seu order_id em metadata para facilitar conciliação.

4. Use polling com intervalo mínimo de 5 segundos e pare assim que chegar a um estado terminal.

5. Se um link expirar, gere um novo em vez de reutilizar links antigos manualmente.

13. Sandbox

Ambiente de testes

Quando a sua conta tiver sandbox habilitado, utilize credenciais separadas, dados fictícios e fluxos isolados do ambiente produtivo. Se o seu acesso ainda não tiver sandbox dedicado, faça testes com valores controlados e pedidos claramente identificados como teste.

Boas práticas no sandbox

Use metadata.test_mode, descrições como "TESTE" e contactos fictícios para separar os registos.

Dados fake

Nunca teste com API Keys reais expostas e não misture pedidos de teste com pedidos de clientes finais.

14. FAQ

Perguntas frequentes

Como sei se o pagamento foi feito?

Consulte GET /payment-links/:id/status em polling até o estado mudar para paid. O campo paid_at será preenchido quando houver confirmação.

Quanto tempo demora?

Depende do cliente e do processamento do pagamento. Para a integração, considere verificações a cada 5 segundos até o estado ficar terminal.

Posso cancelar um link?

Pode expirar manualmente usando POST /payment-links/:id/expire. Na API v1, a operação resulta em expired, não em cancelled.

15. Changelog

Histórico da documentação

v1

Lançamento da documentação pública da PayZap API

Inclusão da referência completa dos endpoints, guia de autenticação, fluxo de polling, exemplos de integração, práticas de segurança e FAQ para integrações modernas.