Guias, autenticação, endpoints e webhooks para conectar o seu produto ao PayMoz com segurança.
const payment = await fetch('/api/v1/payments', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY'
},
body: JSON.stringify({
amount: 1000,
method: 'MPESA'
})
});Guia inicial
01
Acesse o dashboard e configure o perfil da empresa.
02
Use a chave para autenticar as requisições.
03
Obrigatório para pagamentos eMola (assíncrono) e recomendado para todos os casos.
Segurança
Todas as requisições devem incluir a sua API Key no header Authorization usando o formato Bearer.
curl -X POST https://paymozapi.saphirat.co.mz/api/v1/payments -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json"Formato
A referência de transação deve ser uma string aleatória de exatamente 11 caracteres para garantir compatibilidade com o M-Pesa. Se o tamanho não for respeitado ou se houver colisão com uma referência existente, a transação falhará.
Use a função abaixo como exemplo para gerar referências válidas e únicas no seu código:
function generateReference() {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < 11; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
// Exemplo de uso
const reference = generateReference();
console.log(reference); // Saída: aB3x9pQ2z7 (exemplo)Referência
/api/v1/paymentsCria um novo pagamento e retorna a URL de checkout. O campo reference é opcional (se não fornecido, será gerado automaticamente).
const response = await fetch('https://paymozapi.saphirat.co.mz/api/v1/payments', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: 1000,
method: 'MPESA',
callbackUrl: 'https://seu-site.com/webhook',
returnUrl: 'https://seu-site.com/sucesso'
})
});{
"status": "success",
"data": {
"id": "pay_abc123",
"amount": 1000,
"reference": "aB3x9pQ2z7K",
"status": "PENDING",
"checkout_url": "https://paymoz.saphirat.co.mz/checkout/pay_abc123",
"checkoutUrl": "https://paymoz.saphirat.co.mz/checkout/pay_abc123"
}
}/api/v1/payments/directProcessa um pagamento direto (sem URL de checkout). Requer número de telefone do cliente. O comportamento difere consoante o método de pagamento:
M-Pesa
Resposta síncrona e imediata — recebes 200 OK com SUCCESS ou 400/500 com FAILED na própria resposta.
eMola
Resposta assíncrona — recebes 202 Accepted com PROCESSING imediatamente. O estado final (SUCCESS / FAILED) é enviado via webhook quando o cliente confirma no telefone.
⚠️ eMola requer webhook: Para pagamentos eMola via Direct Payment, configura sempre um callbackUrl (na requisição ou no perfil da wallet) para receberes o evento payment.success ou payment.failed. Sem webhook, nunca saberás se o cliente confirmou ou rejeitou o pagamento.
🎯 Deduplicação de Pixel (Facebook/Meta): O PayMoz envia sempre o evento Purchase via Conversions API com event_id = payment.id. No teu website, dispara o fbq com o mesmo eventID — o Meta deduplica automaticamente os dois eventos numa janela de 7 dias, contando apenas uma conversão.
// 1. Chama o Direct Payment e guarda o id da resposta
const { data } = await response.json(); // data.id = "pay_abc123"
// 2. Dispara o fbq com eventID = data.id (mesmo que o PayMoz usa no CAPI)
// O Meta deduplica — só conta uma conversão
fbq('track', 'Purchase', {
value: 1000,
currency: 'MZN',
order_id: data.reference
}, { eventID: data.id }); // ← mesmo event_id que o servidor enviafbc (string) — Cookie _fbc do browser do cliente. Melhora significativamente o match rate da Conversions API.fbp (string) — Cookie _fbp do browser do cliente. Melhora o match rate da Conversions API.customerEmail (string) — Email do cliente para melhor matching.customerName (string) — Nome do cliente.const response = await fetch('https://paymozapi.saphirat.co.mz/api/v1/payments/direct', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: 1000,
reference: 'aB3x9pQ2z7K',
method: 'MPESA',
customerPhone: '258841234567',
callbackUrl: 'https://seu-site.com/webhook',
description: 'Pagamento de exemplo',
// Opcional: cookies do browser para melhor match rate + deduplicação
fbc: getCookie('_fbc'), // cookie _fbc do browser do cliente
fbp: getCookie('_fbp'), // cookie _fbp do browser do cliente
customerEmail: 'cliente@example.com',
customerName: 'João Silva'
})
});O M-Pesa devolve o resultado final na própria resposta HTTP (200 OK).
{
"status": "success",
"message": "Payment processed successfully",
"data": {
"id": "pay_abc123",
"reference": "aB3x9pQ2z7K",
"amount": 1000,
"method": "MPESA",
"status": "SUCCESS",
"transactionId": "MP123456789",
"customerPhone": "258841234567",
"platformFee": 20,
"gatewayFee": 10,
"totalFee": 30,
"netAmount": 970,
"paidAt": "2026-07-13T12:34:56.789Z",
"createdAt": "2026-07-13T12:34:56.123Z"
}
}O eMola devolve 202 Accepted com estado PROCESSING. O resultado final (SUCCESS ou FAILED) será enviado via webhook após confirmação do cliente no telemóvel.
{
"status": "success",
"message": "Pagamento eMola iniciado. Aguarde a confirmação no seu telefone.",
"data": {
"id": "pay_abc123",
"reference": "aB3x9pQ2z7K",
"amount": 1000,
"method": "EMOLA",
"status": "PROCESSING",
"pagarPaymentId": "pag_xyz789",
"createdAt": "2026-07-13T12:34:56.123Z"
}
}/api/v1/payments/reference/:refConsulta o estado de um pagamento por referência.
const response = await fetch(
'https://paymozapi.saphirat.co.mz/api/v1/payments/reference/aB3x9pQ2z7K',
{
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
}
);{
"status": "success",
"data": {
"id": "pay_abc123",
"amount": 1000,
"reference": "aB3x9pQ2z7K",
"status": "SUCCESS",
"method": "MPESA",
"transactionId": "MP123456789",
"createdAt": "2026-07-13T12:34:56.123Z",
"paidAt": "2026-07-13T12:35:01.456Z"
}
}Eventos
Pagamentos eMola são sempre assíncronos. Quer seja via Checkout ou Direct Payment, o estado final do pagamento eMola só é conhecido quando recebes o webhook payment.success ou payment.failed. Sem webhook configurado, não tens forma de saber se o cliente confirmou o pagamento no telemóvel.
payment.createdPagamento criado (ainda não processado)
payment.successPagamento aprovado — liberta o produto/serviço
payment.failedPagamento falhado — notifica o utilizador
200 SUCCESS na própria resposta e o webhook payment.success é enviado em paralelo (redundância).PROCESSING. Só quando o cliente confirma/rejeita no telemóvel é que o webhook payment.success ou payment.failed chega ao teu sistema.app.post('/webhook', (req, res) => {
const { event, data } = req.body;
if (event === 'payment.success') {
console.log(`Pagamento ${data.reference} confirmado!`);
}
res.status(200).send('OK');
});