Introduction
API ClicPay v2 - M-Pesa, e-Mola, NetShop e autenticação
ClicPay API — v2
Visão geral
Esta documentação apresenta a API ClicPay v2, destinada à integração de soluções de pagamento (M-Pesa, e-Mola, Mkesh, NetShop), gestão de carteiras digitais e consulta de estados de transações.
Objetivo
Permitir que aplicações de terceiros criem e confirmem pagamentos, consultem o estado de transações, obtenham históricos e gerenciem carteiras de utilizadores de forma segura e auditável.
Autenticação
A API utiliza OAuth2 (Laravel Passport). Para testar endpoints protegidos na interface, insira um token Bearer através da opção Authorize. Sem um token válido, os pedidos autenticados irão retornar erros de autorização.
Testes e exemplos
Utilize a funcionalidade Try It Out para executar pedidos diretamente a partir da documentação. Os exemplos de código disponíveis no canto superior direito suportam Bash, JavaScript, PHP e Python.
Exemplos de pedidos e respostas
Sempre que possível, cada endpoint inclui exemplos de payloads de pedido e exemplos de resposta. Estes servem como referência, mas os valores reais podem variar conforme o ambiente (sandbox / produção).
Boas práticas de integração
- Forneça números de telefone no formato indicado na descrição de cada endpoint.
- Valide localmente os campos obrigatórios antes de enviar pedidos para evitar chamadas desnecessárias.
- Utilize os códigos de erro e mensagens retornadas para tratamento de falhas.
- Envie sempre uma
Idempotency-Keynos pedidos que movem dinheiro. Ver abaixo.
Idempotência
Um timeout de rede não lhe diz se a cobrança saiu. Repetir arrisca cobrar duas vezes; não repetir perde o pagamento. A Idempotency-Key resolve isso: repetir um pedido com a mesma chave devolve a resposta original em vez de cobrar de novo.
Aplica-se a todos os POST de iniciação de pagamento: as seis rotas C2B (eMola, M-Pesa, mKesh, normais e /direct), card-payment e split/collect.
Como usar
- Gere a chave ANTES do primeiro envio (UUID v4 recomendado, 1 a 128 caracteres) e reutilize-a em cada retentativa do MESMO pagamento.
- A chave é privada da sua conta e vale 48 horas. Dois clientes diferentes podem usar a mesma chave sem colidir.
- Guarde a chave junto do pedido. Ela está ligada ao corpo que a acompanhou: um corpo diferente com a mesma chave é recusado com 422.
- Num replay recebe o cabeçalho
Idempotent-Replayed: truee exactamente o mesmo corpo e estado HTTP da primeira resposta.
A ordem das chaves do JSON não conta, e 100, 100.0 e "100.00" são o mesmo montante. Já a ordem dos elementos de splits[] conta, porque é significativa.
O que acontece a cada resposta
| Resposta | A chave fica | Repetir com a mesma chave |
|---|---|---|
| 200 / 201 sucesso | guardada | devolve o mesmo corpo |
| 400 de validação | guardada | devolve o mesmo 400 |
4xx de rejeição do operador (com transaction_id) |
guardada | devolve o mesmo corpo |
500 com transaction_id |
guardada | devolve o mesmo 500; consulte /transactions/{referencia}/status |
| 401, 403, 429 | libertada | processa de novo |
500 sem transaction_id |
libertada | processa de novo |
| 409 em curso | retida | espere o Retry-After e repita |
A regra por trás da tabela: a chave só é libertada quando é certo que nada aconteceu. Se a transacção chegou a existir, a resposta fica guardada, mesmo sendo um erro, porque o operador pode já ter sido contactado.
Os dois erros que vai encontrar
409 idempotency_request_in_progress— outro pedido com essa chave ainda está a correr. Espere oRetry-Aftere repita com a MESMA chave. Gerar uma chave nova neste momento é a forma mais directa de cobrar o cliente duas vezes.422 idempotency_key_reused_with_different_payload— é bug de integração. A chave está ligada ao pedido. Corpo novo exige chave nova.
Quando a M-Pesa diz que o pedido e repetido
A M-Pesa tambem deduplica do lado dela, pela referencia que lhe enviamos. Se reconhecer um pedido como repeticao de uma cobranca anterior devolve INS-10, e a ClicPay responde 200 com status em PROCESSING e provider_response_code igual a INS-10.
Isso NAO e uma falha. E o contrario: significa que a cobranca anterior seguiu. A accao correcta e consultar /transactions/{referencia}/status, nunca repetir. O mesmo vale para INS-9, em que a M-Pesa nao respondeu a tempo e o desfecho e desconhecido: a transacao fica em PROCESSING e resolve-se por consulta.
A regra geral, que vale para os tres operadores: um estado nao-terminal nunca autoriza uma segunda cobranca. Consulte antes de repetir.
Confirmar um pagamento: o polling e a fonte de verdade
O webhook e aceleracao, nao garantia. Perde-se. A forma oficial de confirmar um pagamento e GET /transactions/{referencia}/status, que pergunta ao operador quando a transacao ainda nao esta num estado final.
- O
statusvem em MAIUSCULAS:PENDING,PROCESSING,SUCCESSFUL,FAILED,CANCELLED,REFUNDED,PARTIALLY_REFUNDED,AWAITING_ACTION,REJECTED. Sao nove, e nao quatro. A documentacao anterior dizia minusculas e estava errada: quem tenha escritostatus === 'successful'a partir dela nunca viu um pagamento confirmado. checked_atdiz quando o estado foi confirmado junto do operador pela ultima vez. Dentro de uma janela de 15 segundos a ClicPay devolve o valor guardado sem voltar a contactar o operador, por isso nao vale a pena consultar mais depressa do que isso.- Estados finais sao absorventes: nao sao re-consultados e nunca mudam por uma consulta posterior.
- Uma consulta que falhe NAO altera o estado. Recebe
200com o estado que havia e umchecked_atnovo. AWAITING_ACTIONsignifica que a ClicPay tentou confirmar durante 48 horas e o operador nunca deu resposta conclusiva. Nao quer dizer que falhou: quer dizer que nao foi possivel saber, e que alguem da ClicPay vai olhar.
Nunca repita uma cobranca por causa de um estado nao-terminal. Consulte. Repetir e o que produz o pagamento duplicado, e para isso serve a Idempotency-Key descrita acima.
Um detalhe do card-payment: o replay devolve a sessão de checkout original, que pode já ter expirado do lado do NetShop. Isso é intencional, porque o replay é o registo da resposta original. Se precisa de uma sessão nova, use uma chave nova, que é o que semanticamente descreve um pagamento novo.
Authenticating requests
To authenticate requests, include an Authorization header with the value "Bearer {YOUR_AUTH_KEY}".
All authenticated endpoints are marked with a requires authentication badge in the documentation below.
Para testar a API, insira seu token Bearer no campo "Authorize". Você pode obter um token através do endpoint de autenticação da API.
Transações M-Pesa
Iniciar cobrança C2B M-Pesa
requires authentication
Idempotência. Envie Idempotency-Key com um valor único por tentativa de
pagamento (UUID v4 recomendado, máximo 128 caracteres). Repetir o pedido com a
mesma chave e o mesmo corpo devolve a resposta guardada, com o mesmo estado HTTP
e o mesmo clicpay_reference, acompanhada do cabeçalho Idempotent-Replayed: true,
sem contactar o operador e sem criar uma segunda transacção. A chave é privada da
sua conta e vale 48 horas. Sem o cabeçalho, o comportamento é o de sempre.
Em 409, outro pedido com essa chave ainda está a ser processado: espere o
Retry-After e repita com a mesma chave. Gerar uma chave nova nesse momento é
o caminho para o pagamento duplicado.
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/c2b/mpesa" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Idempotency-Key: 9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"msisdn\": \"841234567\",
\"amount\": 1000,
\"reference_description\": \"Pagamento de serviços\",
\"internal_notes\": \"Pedido #9001\",
\"splits\": [
\"architecto\"
]
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/c2b/mpesa"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Idempotency-Key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pedido #9001",
"splits": [
"architecto"
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/c2b/mpesa';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key' => '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'msisdn' => '841234567',
'amount' => 1000.0,
'reference_description' => 'Pagamento de serviços',
'internal_notes' => 'Pedido #9001',
'splits' => [
'architecto',
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/c2b/mpesa'
payload = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pedido #9001",
"splits": [
"architecto"
]
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key': '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (200):
{
"message": "Transação iniciada com sucesso",
"clicpay_reference": "CPAYMPSESC2BABCDE12345",
"status": "pending",
"transaction_id": 789,
"split_summary": {
"direct": [],
"collect": []
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (409, Pedido anterior com a mesma chave ainda em curso):
{
"error": "idempotency_request_in_progress",
"message": "Um pedido com esta Idempotency-Key ainda está a ser processado. Aguarde e repita com a MESMA chave.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"retry_after_seconds": 12
}
Example response (422, Erro de validação):
{
"errors": {
"splits.0.wallet_split_id": [
"O split não pertence a esta carteira ou não é dynamic_load."
]
}
}
Example response (422, Idempotency-Key reutilizada com um corpo diferente):
{
"error": "idempotency_key_reused_with_different_payload",
"message": "Esta Idempotency-Key já foi usada com um corpo diferente.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11"
}
Example response (422, Idempotency-Key com formato inválido):
{
"error": "idempotency_key_invalid",
"message": "O cabeçalho Idempotency-Key deve ter entre 1 e 128 caracteres.",
"max_length": 128
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Iniciar cobrança C2B M-Pesa (direct)
requires authentication
Idempotência. Envie Idempotency-Key com um valor único por tentativa de
pagamento (UUID v4 recomendado, máximo 128 caracteres). Repetir o pedido com a
mesma chave e o mesmo corpo devolve a resposta guardada, com o mesmo estado HTTP
e o mesmo clicpay_reference, acompanhada do cabeçalho Idempotent-Replayed: true,
sem contactar o operador e sem criar uma segunda transacção. A chave é privada da
sua conta e vale 48 horas. Sem o cabeçalho, o comportamento é o de sempre.
Em 409, outro pedido com essa chave ainda está a ser processado: espere o
Retry-After e repita com a mesma chave. Gerar uma chave nova nesse momento é
o caminho para o pagamento duplicado.
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/c2b/mpesa/direct" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Idempotency-Key: 9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"msisdn\": \"841234567\",
\"amount\": 1000,
\"reference_description\": \"Pagamento de serviços\",
\"internal_notes\": \"Pedido #9001\",
\"splits\": [
\"architecto\"
]
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/c2b/mpesa/direct"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Idempotency-Key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pedido #9001",
"splits": [
"architecto"
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/c2b/mpesa/direct';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key' => '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'msisdn' => '841234567',
'amount' => 1000.0,
'reference_description' => 'Pagamento de serviços',
'internal_notes' => 'Pedido #9001',
'splits' => [
'architecto',
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/c2b/mpesa/direct'
payload = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pedido #9001",
"splits": [
"architecto"
]
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key': '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (200):
{
"message": "Transação iniciada com sucesso",
"clicpay_reference": "CPAYMPSESC2BABCDE12345",
"status": "pending",
"transaction_id": 789,
"split_summary": {
"direct": [],
"collect": []
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (409, Pedido anterior com a mesma chave ainda em curso):
{
"error": "idempotency_request_in_progress",
"message": "Um pedido com esta Idempotency-Key ainda está a ser processado. Aguarde e repita com a MESMA chave.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"retry_after_seconds": 12
}
Example response (422, Erro de validação):
{
"errors": {
"splits.0.value_type": [
"O campo value_type deve ser percentage ou amount."
]
}
}
Example response (422, Idempotency-Key reutilizada com um corpo diferente):
{
"error": "idempotency_key_reused_with_different_payload",
"message": "Esta Idempotency-Key já foi usada com um corpo diferente.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11"
}
Example response (422, Idempotency-Key com formato inválido):
{
"error": "idempotency_key_invalid",
"message": "O cabeçalho Idempotency-Key deve ter entre 1 e 128 caracteres.",
"max_length": 128
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
POST api/v2/wallets/{wallet_id}/b2c/mpesa
requires authentication
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/b2c/mpesa" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"msisdn\": \"841234567\",
\"amount\": 500,
\"reference_description\": \"Compra online\",
\"internal_notes\": \"Pedido #12345\"
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/b2c/mpesa"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"msisdn": "841234567",
"amount": 500,
"reference_description": "Compra online",
"internal_notes": "Pedido #12345"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/b2c/mpesa';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'msisdn' => '841234567',
'amount' => 500.0,
'reference_description' => 'Compra online',
'internal_notes' => 'Pedido #12345',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/b2c/mpesa'
payload = {
"msisdn": "841234567",
"amount": 500,
"reference_description": "Compra online",
"internal_notes": "Pedido #12345"
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (200):
{
"message": "Transação iniciada com sucesso",
"clicpay_reference": "CP123456789",
"status": "pending",
"transaction_id": 124
}
Example response (400):
{
"errors": {
"msisdn": [
"Número de telefone inválido"
],
"amount": [
"Valor deve ser entre 1 e 50000"
]
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (403):
{
"message": "Acesso negado à carteira"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
clicpay_reference
string
Referência única da transação
status
string
Status atual (pending/successful/failed)
transaction_id
integer
ID interno da transação
Transações eMola
Iniciar cobrança C2B eMola
requires authentication
Idempotência. Envie Idempotency-Key com um valor único por tentativa de
pagamento (UUID v4 recomendado, máximo 128 caracteres). Repetir o pedido com a
mesma chave e o mesmo corpo devolve a resposta guardada, com o mesmo estado HTTP
e o mesmo clicpay_reference, acompanhada do cabeçalho Idempotent-Replayed: true,
sem contactar o operador e sem criar uma segunda transacção. A chave é privada da
sua conta e vale 48 horas. Sem o cabeçalho, o comportamento é o de sempre.
Em 409, outro pedido com essa chave ainda está a ser processado: espere o
Retry-After e repita com a mesma chave. Gerar uma chave nova nesse momento é
o caminho para o pagamento duplicado.
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/c2b/emola" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Idempotency-Key: 9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"msisdn\": \"841234567\",
\"amount\": 1000,
\"reference_description\": \"Pagamento de serviços\",
\"internal_notes\": \"Pedido #9001\",
\"splits\": [
\"architecto\"
]
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/c2b/emola"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Idempotency-Key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pedido #9001",
"splits": [
"architecto"
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/c2b/emola';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key' => '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'msisdn' => '841234567',
'amount' => 1000.0,
'reference_description' => 'Pagamento de serviços',
'internal_notes' => 'Pedido #9001',
'splits' => [
'architecto',
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/c2b/emola'
payload = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pedido #9001",
"splits": [
"architecto"
]
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key': '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (200):
{
"message": "Transação iniciada com sucesso",
"clicpay_reference": "CPAYEMOLAC2BABCDE12345",
"status": "pending",
"transaction_id": 789,
"provider_reference": null,
"provider_response_code": "0",
"split_summary": {
"direct": [
{
"wallet_split_id": 42,
"mode": "b2c_direct",
"allocated": 300,
"recipients": [
{
"msisdn": "841234567",
"amount": 300
}
]
}
],
"collect": [
{
"wallet_split_id": 43,
"mode": "wallet_collect",
"allocated": 200
}
]
}
}
Example response (400):
{
"message": "Erro do provedor",
"clicpay_reference": "CPAY...",
"status": "failed"
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (403):
{
"message": "Sem acesso à carteira ou carteira inactiva."
}
Example response (409, Pedido anterior com a mesma chave ainda em curso):
{
"error": "idempotency_request_in_progress",
"message": "Um pedido com esta Idempotency-Key ainda está a ser processado. Aguarde e repita com a MESMA chave.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"retry_after_seconds": 12
}
Example response (422, Erro de validação):
{
"errors": {
"splits.0.wallet_split_id": [
"O split não pertence a esta carteira ou não é dynamic_load."
]
}
}
Example response (422, Idempotency-Key reutilizada com um corpo diferente):
{
"error": "idempotency_key_reused_with_different_payload",
"message": "Esta Idempotency-Key já foi usada com um corpo diferente.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11"
}
Example response (422, Idempotency-Key com formato inválido):
{
"error": "idempotency_key_invalid",
"message": "O cabeçalho Idempotency-Key deve ter entre 1 e 128 caracteres.",
"max_length": 128
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
clicpay_reference
string
Referência única da transação ClicPay.
status
string
Estado actual: pending | successful | failed.
split_summary
object
Presente quando splits[] foi enviado. direct lista B2C imediatos; collect lista acumulações. Splits ignorados (inactivos, limite atingido) não aparecem.
Iniciar cobrança C2B eMola (direct)
requires authentication
Idempotência. Envie Idempotency-Key com um valor único por tentativa de
pagamento (UUID v4 recomendado, máximo 128 caracteres). Repetir o pedido com a
mesma chave e o mesmo corpo devolve a resposta guardada, com o mesmo estado HTTP
e o mesmo clicpay_reference, acompanhada do cabeçalho Idempotent-Replayed: true,
sem contactar o operador e sem criar uma segunda transacção. A chave é privada da
sua conta e vale 48 horas. Sem o cabeçalho, o comportamento é o de sempre.
Em 409, outro pedido com essa chave ainda está a ser processado: espere o
Retry-After e repita com a mesma chave. Gerar uma chave nova nesse momento é
o caminho para o pagamento duplicado.
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/c2b/emola/direct" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Idempotency-Key: 9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"msisdn\": \"841234567\",
\"amount\": 1000,
\"reference_description\": \"Pagamento de serviços\",
\"internal_notes\": \"Pedido #9001\",
\"splits\": [
\"architecto\"
]
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/c2b/emola/direct"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Idempotency-Key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pedido #9001",
"splits": [
"architecto"
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/c2b/emola/direct';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key' => '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'msisdn' => '841234567',
'amount' => 1000.0,
'reference_description' => 'Pagamento de serviços',
'internal_notes' => 'Pedido #9001',
'splits' => [
'architecto',
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/c2b/emola/direct'
payload = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pedido #9001",
"splits": [
"architecto"
]
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key': '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (200):
{
"message": "Transação iniciada com sucesso",
"clicpay_reference": "CPAYEMOLAC2BABCDE12345",
"status": "pending",
"transaction_id": 789,
"split_summary": {
"direct": [],
"collect": []
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (409, Pedido anterior com a mesma chave ainda em curso):
{
"error": "idempotency_request_in_progress",
"message": "Um pedido com esta Idempotency-Key ainda está a ser processado. Aguarde e repita com a MESMA chave.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"retry_after_seconds": 12
}
Example response (422, Erro de validação):
{
"errors": {
"splits.0.value_type": [
"O campo value_type deve ser percentage ou amount."
]
}
}
Example response (422, Idempotency-Key reutilizada com um corpo diferente):
{
"error": "idempotency_key_reused_with_different_payload",
"message": "Esta Idempotency-Key já foi usada com um corpo diferente.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11"
}
Example response (422, Idempotency-Key com formato inválido):
{
"error": "idempotency_key_invalid",
"message": "O cabeçalho Idempotency-Key deve ter entre 1 e 128 caracteres.",
"max_length": 128
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
POST api/v2/wallets/{wallet_id}/b2c/emola
requires authentication
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/b2c/emola" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"msisdn\": \"841234567\",
\"amount\": 1000,
\"reference_description\": \"Pagamento de serviços\",
\"internal_notes\": \"Pagamento mensal\"
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/b2c/emola"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pagamento mensal"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/b2c/emola';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'msisdn' => '841234567',
'amount' => 1000.0,
'reference_description' => 'Pagamento de serviços',
'internal_notes' => 'Pagamento mensal',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/b2c/emola'
payload = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pagamento mensal"
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (200):
{
"message": "Transação iniciada com sucesso",
"clicpay_reference": "CP123456789",
"status": "pending",
"transaction_id": 123
}
Example response (400):
{
"errors": {
"msisdn": [
"Número de telefone inválido"
],
"amount": [
"Valor deve ser entre 1 e 50000"
]
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (403):
{
"message": "Acesso negado à carteira"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
clicpay_reference
string
Referência única da transação
status
string
Status atual (pending/successful/failed)
transaction_id
integer
ID interno da transação
Transações Mkesh
Iniciar cobrança C2B mKesh
requires authentication
Idempotência. Envie Idempotency-Key com um valor único por tentativa de
pagamento (UUID v4 recomendado, máximo 128 caracteres). Repetir o pedido com a
mesma chave e o mesmo corpo devolve a resposta guardada, com o mesmo estado HTTP
e o mesmo clicpay_reference, acompanhada do cabeçalho Idempotent-Replayed: true,
sem contactar o operador e sem criar uma segunda transacção. A chave é privada da
sua conta e vale 48 horas. Sem o cabeçalho, o comportamento é o de sempre.
Em 409, outro pedido com essa chave ainda está a ser processado: espere o
Retry-After e repita com a mesma chave. Gerar uma chave nova nesse momento é
o caminho para o pagamento duplicado.
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/c2b/mkesh" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Idempotency-Key: 9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"msisdn\": \"841234567\",
\"amount\": 1000,
\"reference_description\": \"Pagamento de serviços\",
\"internal_notes\": \"Pedido #9001\",
\"splits\": [
\"architecto\"
]
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/c2b/mkesh"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Idempotency-Key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pedido #9001",
"splits": [
"architecto"
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/c2b/mkesh';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key' => '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'msisdn' => '841234567',
'amount' => 1000.0,
'reference_description' => 'Pagamento de serviços',
'internal_notes' => 'Pedido #9001',
'splits' => [
'architecto',
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/c2b/mkesh'
payload = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pedido #9001",
"splits": [
"architecto"
]
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key': '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (200):
{
"message": "Transação iniciada com sucesso",
"clicpay_reference": "CPAYKMESHC2BABCDE12345",
"status": "pending",
"transaction_id": 789,
"split_summary": {
"direct": [],
"collect": []
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (409, Pedido anterior com a mesma chave ainda em curso):
{
"error": "idempotency_request_in_progress",
"message": "Um pedido com esta Idempotency-Key ainda está a ser processado. Aguarde e repita com a MESMA chave.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"retry_after_seconds": 12
}
Example response (422, Erro de validação):
{
"errors": {
"splits.0.wallet_split_id": [
"O split não pertence a esta carteira ou não é dynamic_load."
]
}
}
Example response (422, Idempotency-Key reutilizada com um corpo diferente):
{
"error": "idempotency_key_reused_with_different_payload",
"message": "Esta Idempotency-Key já foi usada com um corpo diferente.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11"
}
Example response (422, Idempotency-Key com formato inválido):
{
"error": "idempotency_key_invalid",
"message": "O cabeçalho Idempotency-Key deve ter entre 1 e 128 caracteres.",
"max_length": 128
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Iniciar cobrança C2B mKesh (direct)
requires authentication
Idempotência. Envie Idempotency-Key com um valor único por tentativa de
pagamento (UUID v4 recomendado, máximo 128 caracteres). Repetir o pedido com a
mesma chave e o mesmo corpo devolve a resposta guardada, com o mesmo estado HTTP
e o mesmo clicpay_reference, acompanhada do cabeçalho Idempotent-Replayed: true,
sem contactar o operador e sem criar uma segunda transacção. A chave é privada da
sua conta e vale 48 horas. Sem o cabeçalho, o comportamento é o de sempre.
Em 409, outro pedido com essa chave ainda está a ser processado: espere o
Retry-After e repita com a mesma chave. Gerar uma chave nova nesse momento é
o caminho para o pagamento duplicado.
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/c2b/mkesh/direct" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Idempotency-Key: 9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"msisdn\": \"841234567\",
\"amount\": 1000,
\"reference_description\": \"Pagamento de serviços\",
\"internal_notes\": \"Pedido #9001\",
\"splits\": [
\"architecto\"
]
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/c2b/mkesh/direct"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Idempotency-Key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pedido #9001",
"splits": [
"architecto"
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/c2b/mkesh/direct';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key' => '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'msisdn' => '841234567',
'amount' => 1000.0,
'reference_description' => 'Pagamento de serviços',
'internal_notes' => 'Pedido #9001',
'splits' => [
'architecto',
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/c2b/mkesh/direct'
payload = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pedido #9001",
"splits": [
"architecto"
]
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key': '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (200):
{
"message": "Transação iniciada com sucesso",
"clicpay_reference": "CPAYKMESHC2BABCDE12345",
"status": "pending",
"transaction_id": 789,
"split_summary": {
"direct": [],
"collect": []
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (409, Pedido anterior com a mesma chave ainda em curso):
{
"error": "idempotency_request_in_progress",
"message": "Um pedido com esta Idempotency-Key ainda está a ser processado. Aguarde e repita com a MESMA chave.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"retry_after_seconds": 12
}
Example response (422, Erro de validação):
{
"errors": {
"splits.0.value_type": [
"O campo value_type deve ser percentage ou amount."
]
}
}
Example response (422, Idempotency-Key reutilizada com um corpo diferente):
{
"error": "idempotency_key_reused_with_different_payload",
"message": "Esta Idempotency-Key já foi usada com um corpo diferente.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11"
}
Example response (422, Idempotency-Key com formato inválido):
{
"error": "idempotency_key_invalid",
"message": "O cabeçalho Idempotency-Key deve ter entre 1 e 128 caracteres.",
"max_length": 128
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
POST api/v2/wallets/{wallet_id}/b2c/mkesh
requires authentication
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/b2c/mkesh" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"msisdn\": \"841234567\",
\"amount\": 500,
\"reference_description\": \"Compra online\",
\"internal_notes\": \"Pedido #12345\"
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/b2c/mkesh"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"msisdn": "841234567",
"amount": 500,
"reference_description": "Compra online",
"internal_notes": "Pedido #12345"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/b2c/mkesh';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'msisdn' => '841234567',
'amount' => 500.0,
'reference_description' => 'Compra online',
'internal_notes' => 'Pedido #12345',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/b2c/mkesh'
payload = {
"msisdn": "841234567",
"amount": 500,
"reference_description": "Compra online",
"internal_notes": "Pedido #12345"
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (200):
{
"message": "Transação iniciada com sucesso",
"clicpay_reference": "CP123456789",
"status": "pending",
"transaction_id": 124
}
Example response (400):
{
"errors": {
"msisdn": [
"Número de telefone inválido"
],
"amount": [
"Valor deve ser entre 1 e 50000"
]
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (403):
{
"message": "Acesso negado à carteira"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
clicpay_reference
string
Referência única da transação
status
string
Status atual (pending/successful/failed)
transaction_id
integer
ID interno da transação
Transações NetShop
Iniciar pagamento por cartão
requires authentication
Idempotência. Envie Idempotency-Key com um valor único por tentativa de
pagamento (UUID v4 recomendado, máximo 128 caracteres). Repetir o pedido com a
mesma chave e o mesmo corpo devolve a resposta guardada, com o mesmo estado HTTP
e o mesmo clicpay_reference, acompanhada do cabeçalho Idempotent-Replayed: true,
sem contactar o operador e sem criar uma segunda transacção. A chave é privada da
sua conta e vale 48 horas. Sem o cabeçalho, o comportamento é o de sempre.
Em 409, outro pedido com essa chave ainda está a ser processado: espere o
Retry-After e repita com a mesma chave. Gerar uma chave nova nesse momento é
o caminho para o pagamento duplicado.
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/card-payment" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Idempotency-Key: 9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"amount\": 1500,
\"reference_description\": \"Pagamento de fatura\",
\"first_name\": \"João\",
\"last_name\": \"Silva\",
\"email\": \"QYvHk@example.com\",
\"phone\": \"84 123 4567\",
\"callback_url\": \"https:\\/\\/example.com\\/callback\",
\"from_app\": \"Loja Online\"
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/card-payment"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Idempotency-Key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"amount": 1500,
"reference_description": "Pagamento de fatura",
"first_name": "João",
"last_name": "Silva",
"email": "QYvHk@example.com",
"phone": "84 123 4567",
"callback_url": "https:\/\/example.com\/callback",
"from_app": "Loja Online"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/card-payment';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key' => '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'amount' => 1500.0,
'reference_description' => 'Pagamento de fatura',
'first_name' => 'João',
'last_name' => 'Silva',
'email' => 'QYvHk@example.com',
'phone' => '84 123 4567',
'callback_url' => 'https://example.com/callback',
'from_app' => 'Loja Online',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/card-payment'
payload = {
"amount": 1500,
"reference_description": "Pagamento de fatura",
"first_name": "João",
"last_name": "Silva",
"email": "QYvHk@example.com",
"phone": "84 123 4567",
"callback_url": "https:\/\/example.com\/callback",
"from_app": "Loja Online"
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key': '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (201):
{
"message": "Sessão criada.",
"clicpay_reference": "123456789",
"status": "pending",
"provider_reference": "123456789",
"provider_response_code": "200",
"provider_status_text": "Pending",
"initiated_at": "2023-01-01T00:00:00Z",
"completed_at": null,
"transaction_id": 123,
"checkout_url": "https://netshop.example.com/checkout/abc123",
"session_id": "abc123"
}
Example response (400):
{
"message": "Erro ao criar a sessão.",
"clicpay_reference": "123456789",
"status": "failed",
"transaction_id": 123,
"provider_response_code": "400"
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (403):
{
"message": "Acesso negado à carteira"
}
Example response (409, Pedido anterior com a mesma chave ainda em curso):
{
"error": "idempotency_request_in_progress",
"message": "Um pedido com esta Idempotency-Key ainda está a ser processado. Aguarde e repita com a MESMA chave.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"retry_after_seconds": 12
}
Example response (422, Erro de validação):
{
"errors": {
"amount": [
"O campo valor é obrigatório."
],
"reference_description": [
"O campo descrição da referência é obrigatório."
]
}
}
Example response (422, Idempotency-Key reutilizada com um corpo diferente):
{
"error": "idempotency_key_reused_with_different_payload",
"message": "Esta Idempotency-Key já foi usada com um corpo diferente.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11"
}
Example response (422, Idempotency-Key com formato inválido):
{
"error": "idempotency_key_invalid",
"message": "O cabeçalho Idempotency-Key deve ter entre 1 e 128 caracteres.",
"max_length": 128
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
clicpay_reference
string
Referência única da transação
status
string
Status atual (pending/successful/failed)
provider_reference
string
Referência do provedor de pagamento
provider_response_code
string
Código de resposta do provedor
provider_status_text
string
Descrição do status do provedor
message
string
Mensagem descritiva do status
initiated_at
string
Data e hora de início da transação (ISO 8601)
completed_at
string
Data e hora de conclusão da transação (ISO 8601)
transaction_id
integer
ID interno da transação
checkout_url
string
URL do checkout NetShop
session_id
string
ID da sessão NetShop
Estado de Transações
Consultar o estado de uma transação
requires authentication
Esta consulta é a fonte de verdade. O webhook é aceleração. Um webhook pode perder-se; esta rota pergunta ao operador. Nunca trate a ausência de webhook como falha de pagamento: consulte aqui.
Quando a transação ainda não está num estado final, a ClicPay contacta o
operador e devolve o que ele disser. Se a última verificação tiver menos de
15 segundos, devolve o valor guardado sem voltar a contactar: o campo
checked_at diz-lhe exactamente quando foi confirmado, para não ter de
adivinhar se o valor é recente.
Estados finais (SUCCESSFUL, FAILED, CANCELLED, REFUNDED) são
absorventes: não são re-consultados e nunca mudam por uma consulta
posterior.
Uma consulta que falhe não altera o estado. Recebe 200 com o estado
que havia, e checked_at actualizado. Um estado não-terminal nunca
autoriza uma segunda cobrança: consulte, não repita o pagamento.
Example request:
curl --request GET \
--get "https://clicpay.co.mz/api/v2/transactions/CPAYMPESAC2BAB12/status" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://clicpay.co.mz/api/v2/transactions/CPAYMPESAC2BAB12/status"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/transactions/CPAYMPESAC2BAB12/status';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/transactions/CPAYMPESAC2BAB12/status'
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()Example response (200, Pagamento confirmado):
{
"clicpay_reference": "CPAYMPESAC2BAB12",
"status": "SUCCESSFUL",
"provider_reference": "DGO4KXXBEVW",
"provider_response_code": "INS-0",
"provider_status_text": "Completed",
"message": "Transaction status: Completed",
"initiated_at": "2026-09-14T10:00:00+00:00",
"completed_at": "2026-09-14T10:00:42+00:00",
"checked_at": "2026-09-14T10:00:43+00:00"
}
Example response (200, Ainda em curso):
{
"clicpay_reference": "CPAYMPESAC2BAB12",
"status": "PROCESSING",
"provider_reference": null,
"provider_response_code": "INS-0",
"provider_status_text": "Pending",
"message": "Transaction status: Pending",
"initiated_at": "2026-09-14T10:00:00+00:00",
"completed_at": null,
"checked_at": "2026-09-14T10:00:20+00:00"
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (404):
{"message": "No query results for model [App\Models\Transaction]."}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
clicpay_reference
string
Referência ClicPay da transação.
status
string
Estado actual, em MAIÚSCULAS. Um de: PENDING, PROCESSING, SUCCESSFUL, FAILED, CANCELLED, REFUNDED, PARTIALLY_REFUNDED, AWAITING_ACTION, REJECTED. Compare em maiúsculas: a documentação anterior dizia minúsculas e estava errada.
provider_reference
string
Referência da transação do lado do operador, quando já existe.
provider_response_code
string
Código de resposta do operador (ex.: INS-0).
provider_status_text
string
Estado textual do operador (ex.: Completed).
message
string
Mensagem descritiva do estado.
initiated_at
string
Quando a ClicPay registou o pedido (ISO 8601).
completed_at
string
Quando a transação atingiu um estado final (ISO 8601), ou null.
checked_at
string
Quando o estado foi confirmado junto do operador pela última vez (ISO 8601), ou null se nunca foi.
Carteiras
GET api/v2/me/wallets
requires authentication
Example request:
curl --request GET \
--get "https://clicpay.co.mz/api/v2/me/wallets?payment_method_id=1&is_active=1&environment=production&include=paymentMethod&sort_by=created_at&sort_order=desc&per_page=20" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://clicpay.co.mz/api/v2/me/wallets"
);
const params = {
"payment_method_id": "1",
"is_active": "1",
"environment": "production",
"include": "paymentMethod",
"sort_by": "created_at",
"sort_order": "desc",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/me/wallets';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'payment_method_id' => '1',
'is_active' => '1',
'environment' => 'production',
'include' => 'paymentMethod',
'sort_by' => 'created_at',
'sort_order' => 'desc',
'per_page' => '20',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/me/wallets'
params = {
'payment_method_id': '1',
'is_active': '1',
'environment': 'production',
'include': 'paymentMethod',
'sort_by': 'created_at',
'sort_order': 'desc',
'per_page': '20',
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers, params=params)
response.json()Example response (200):
{
"data": [
{
"id": 1,
"name": "Minha Carteira",
"balance": 1000,
"payment_method": {
"id": 1,
"name": "eMola",
"slug": "emola"
}
}
],
"links": {
"first": "...",
"last": "...",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"per_page": 20,
"to": 1,
"total": 1
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
string[]
Lista de carteiras
id
integer
ID da carteira
name
string
Nome da carteira
balance
number
Saldo disponível
payment_method
object
Método de pagamento associado
Autenticação
Obter utilizador autenticado
requires authentication
Example request:
curl --request GET \
--get "https://clicpay.co.mz/api/user" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://clicpay.co.mz/api/user"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/user';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/user'
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()Example response (401):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"message": "Unauthenticated."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Obter token de acesso
requires authentication
Example request:
curl --request GET \
--get "https://clicpay.co.mz/api/me/token" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://clicpay.co.mz/api/me/token"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/me/token';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/me/token'
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()Example response (401):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"message": "Unauthenticated."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Carteiras e Subcarteiras
Listar carteiras do parceiro. Devolve as carteiras a que o utilizador autenticado tem acesso (carteiras pessoais + carteiras das organizações em que é membro).
requires authentication
Example request:
curl --request GET \
--get "https://clicpay.co.mz/api/v2/wallets?filter%5Bis_active%5D=1&filter%5Bpayment_method_id%5D=1&filter%5Benvironment%5D=production&filter%5Bsearch%5D=minha&sort=-created_at&per_page=20&page=1" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"filter\": {
\"is_active\": true,
\"payment_method_id\": 16,
\"environment\": \"production\",
\"search\": \"n\"
},
\"sort\": \"name\",
\"per_page\": 7,
\"page\": 66
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets"
);
const params = {
"filter[is_active]": "1",
"filter[payment_method_id]": "1",
"filter[environment]": "production",
"filter[search]": "minha",
"sort": "-created_at",
"per_page": "20",
"page": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"filter": {
"is_active": true,
"payment_method_id": 16,
"environment": "production",
"search": "n"
},
"sort": "name",
"per_page": 7,
"page": 66
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'filter[is_active]' => '1',
'filter[payment_method_id]' => '1',
'filter[environment]' => 'production',
'filter[search]' => 'minha',
'sort' => '-created_at',
'per_page' => '20',
'page' => '1',
],
'json' => [
'filter' => [
'is_active' => true,
'payment_method_id' => 16,
'environment' => 'production',
'search' => 'n',
],
'sort' => 'name',
'per_page' => 7,
'page' => 66,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets'
payload = {
"filter": {
"is_active": true,
"payment_method_id": 16,
"environment": "production",
"search": "n"
},
"sort": "name",
"per_page": 7,
"page": 66
}
params = {
'filter[is_active]': '1',
'filter[payment_method_id]': '1',
'filter[environment]': 'production',
'filter[search]': 'minha',
'sort': '-created_at',
'per_page': '20',
'page': '1',
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers, json=payload, params=params)
response.json()Example response (200):
{
"data": [
{
"id": 123,
"name": "Carteira Mpesa Principal",
"environment": "production",
"is_active": true,
"allow_c2b": true,
"allow_b2c": true,
"currency": "MZN",
"payment_method": {
"id": 1,
"name": "Mpesa",
"slug": "mpesa"
},
"owner": {
"type": "organization",
"id": 5,
"name": "Acme Lda"
},
"balance": {
"available": "1500.00",
"accumulated": "2000.00"
},
"commission": {
"c2b_percentage": "1.5000",
"b2c_percentage": "1.0000"
},
"created_at": "2026-01-15T10:30:00+00:00",
"updated_at": "2026-06-01T08:12:33+00:00"
}
],
"meta": {
"pagination": {
"type": "offset",
"per_page": 20,
"count": 1,
"current_page": 1,
"last_page": 1,
"from": 1,
"to": 1,
"total": 1
}
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (422):
{
"message": "Sort inválido.",
"errors": {
"sort": [
"Ordenação inválida..."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Detalhe de uma carteira.
requires authentication
Example request:
curl --request GET \
--get "https://clicpay.co.mz/api/v2/wallets/115665" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665'
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()Example response (200):
{
"data": {
"id": 123,
"name": "Carteira Mpesa Principal",
"environment": "production",
"is_active": true,
"allow_c2b": true,
"allow_b2c": true,
"currency": "MZN",
"payment_method": {
"id": 1,
"name": "Mpesa",
"slug": "mpesa"
},
"owner": {
"type": "organization",
"id": 5,
"name": "Acme Lda"
},
"balance": {
"available": "1500.00",
"accumulated": "2000.00"
},
"commission": {
"c2b_percentage": "1.5000",
"b2c_percentage": "1.0000"
},
"created_at": "2026-01-15T10:30:00+00:00",
"updated_at": "2026-06-01T08:12:33+00:00"
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (403):
{
"message": "This action is unauthorized."
}
Example response (404):
{
"message": "No query results for model [App\\Models\\Wallet]."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Saldo de uma carteira. Endpoint dedicado e leve. Resposta é cacheada por 60 segundos por carteira — ideal para dashboards e polling de reconciliação.
requires authentication
Example request:
curl --request GET \
--get "https://clicpay.co.mz/api/v2/wallets/115665/balance" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/balance"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/balance';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/balance'
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()Example response (200):
{
"data": {
"wallet_id": 123,
"currency": "MZN",
"available": "1500.00",
"accumulated": "2000.00",
"debits": "500.00",
"computed_at": "2026-06-03T15:42:11+00:00"
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (403):
{
"message": "This action is unauthorized."
}
Example response (404):
{
"message": "No query results for model [App\\Models\\Wallet]."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Listar subcarteiras (splits) de uma carteira.
requires authentication
Example request:
curl --request GET \
--get "https://clicpay.co.mz/api/v2/wallets/115665/splits?filter%5Bis_active%5D=1&filter%5Bsplit_mode%5D=wallet_collect&filter%5Bsearch%5D=split-a&sort=-created_at&per_page=20" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"filter\": {
\"is_active\": true,
\"split_mode\": \"wallet_collect\",
\"search\": \"b\"
},
\"sort\": \"name\",
\"per_page\": 22,
\"page\": 67
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/splits"
);
const params = {
"filter[is_active]": "1",
"filter[split_mode]": "wallet_collect",
"filter[search]": "split-a",
"sort": "-created_at",
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"filter": {
"is_active": true,
"split_mode": "wallet_collect",
"search": "b"
},
"sort": "name",
"per_page": 22,
"page": 67
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/splits';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'filter[is_active]' => '1',
'filter[split_mode]' => 'wallet_collect',
'filter[search]' => 'split-a',
'sort' => '-created_at',
'per_page' => '20',
],
'json' => [
'filter' => [
'is_active' => true,
'split_mode' => 'wallet_collect',
'search' => 'b',
],
'sort' => 'name',
'per_page' => 22,
'page' => 67,
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/splits'
payload = {
"filter": {
"is_active": true,
"split_mode": "wallet_collect",
"search": "b"
},
"sort": "name",
"per_page": 22,
"page": 67
}
params = {
'filter[is_active]': '1',
'filter[split_mode]': 'wallet_collect',
'filter[search]': 'split-a',
'sort': '-created_at',
'per_page': '20',
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers, json=payload, params=params)
response.json()Example response (200):
{
"data": [
{
"id": 100001,
"name": "Split Marketing",
"wallet_id": 123,
"environment": "production",
"is_active": true,
"allow_b2c": true,
"currency": "MZN",
"split_mode": "wallet_collect",
"split_value_type": "percentage",
"split_value": "30.0000",
"advanced_enabled": false,
"max_amount": null,
"balance": {
"available": "750.00",
"accumulated": "900.00",
"debits": "150.00"
},
"created_at": "2026-02-10T09:00:00+00:00",
"updated_at": "2026-06-01T08:12:33+00:00"
}
],
"meta": {
"pagination": {
"type": "offset",
"per_page": 20,
"count": 1,
"current_page": 1,
"last_page": 1,
"from": 1,
"to": 1,
"total": 1
}
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (403):
{
"message": "This action is unauthorized."
}
Example response (404):
{
"message": "No query results for model [App\\Models\\Wallet]."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Detalhe de uma subcarteira.
requires authentication
Example request:
curl --request GET \
--get "https://clicpay.co.mz/api/v2/wallets/115665/splits/100000" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/splits/100000"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/splits/100000';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/splits/100000'
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()Example response (200, Sucesso):
{
"data": {
"id": 100001,
"name": "Split Marketing",
"wallet_id": 123,
"environment": "production",
"is_active": true,
"allow_b2c": true,
"currency": "MZN",
"split_mode": "wallet_collect",
"split_value_type": "percentage",
"split_value": "30.0000",
"advanced_enabled": false,
"max_amount": null,
"balance": {
"available": "750.00",
"accumulated": "900.00",
"debits": "150.00"
},
"created_at": "2026-02-10T09:00:00+00:00",
"updated_at": "2026-06-01T08:12:33+00:00"
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (403):
{
"message": "This action is unauthorized."
}
Example response (404, Split não pertence à carteira indicada):
{
"message": "No query results for model [App\\Models\\WalletSplit]."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Saldo de uma subcarteira. Resposta cacheada por 60 segundos por subcarteira. Inclui `max_amount` e `remaining_capacity` quando a subcarteira tem cap configurado.
requires authentication
Example request:
curl --request GET \
--get "https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/balance" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/balance"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/balance';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/balance'
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()Example response (200):
{
"data": {
"wallet_split_id": 100001,
"wallet_id": 123,
"currency": "MZN",
"available": "750.00",
"accumulated": "900.00",
"debits": "150.00",
"max_amount": "5000.00",
"remaining_capacity": "4100.00",
"computed_at": "2026-06-03T15:42:11+00:00"
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (403):
{
"message": "This action is unauthorized."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Histórico cross-wallet de transacções. Devolve todas as transacções das carteiras a que o parceiro tem acesso.
requires authentication
Example request:
curl --request GET \
--get "https://clicpay.co.mz/api/v2/transactions?filter%5Bwallet_id%5D=123&filter%5Bdate_from%5D=2026-01-01&filter%5Bdate_to%5D=2026-06-30&filter%5Bstatus%5D=SUCCESSFUL&filter%5Btype%5D=C2B&filter%5Bprovider%5D=mpesa&filter%5Bclicpay_reference%5D=CPAYEMOLAC2B...&filter%5Bprovider_reference%5D=PROV-12345&sort=-created_at&paginator=cursor&per_page=50" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"filter\": {
\"date_from\": \"2026-09-15T00:58:45\",
\"date_to\": \"2052-10-08\",
\"status\": [
\"FAILED\"
],
\"type\": [
\"TRANSFER_IN\"
],
\"provider\": \"architecto\",
\"clicpay_reference\": \"n\",
\"provider_reference\": \"g\",
\"wallet_id\": 16
},
\"sort\": \"amount\",
\"paginator\": \"cursor\",
\"per_page\": 22,
\"page\": 67,
\"cursor\": \"architecto\"
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/transactions"
);
const params = {
"filter[wallet_id]": "123",
"filter[date_from]": "2026-01-01",
"filter[date_to]": "2026-06-30",
"filter[status]": "SUCCESSFUL",
"filter[type]": "C2B",
"filter[provider]": "mpesa",
"filter[clicpay_reference]": "CPAYEMOLAC2B...",
"filter[provider_reference]": "PROV-12345",
"sort": "-created_at",
"paginator": "cursor",
"per_page": "50",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"filter": {
"date_from": "2026-09-15T00:58:45",
"date_to": "2052-10-08",
"status": [
"FAILED"
],
"type": [
"TRANSFER_IN"
],
"provider": "architecto",
"clicpay_reference": "n",
"provider_reference": "g",
"wallet_id": 16
},
"sort": "amount",
"paginator": "cursor",
"per_page": 22,
"page": 67,
"cursor": "architecto"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/transactions';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'filter[wallet_id]' => '123',
'filter[date_from]' => '2026-01-01',
'filter[date_to]' => '2026-06-30',
'filter[status]' => 'SUCCESSFUL',
'filter[type]' => 'C2B',
'filter[provider]' => 'mpesa',
'filter[clicpay_reference]' => 'CPAYEMOLAC2B...',
'filter[provider_reference]' => 'PROV-12345',
'sort' => '-created_at',
'paginator' => 'cursor',
'per_page' => '50',
],
'json' => [
'filter' => [
'date_from' => '2026-09-15T00:58:45',
'date_to' => '2052-10-08',
'status' => [
'FAILED',
],
'type' => [
'TRANSFER_IN',
],
'provider' => 'architecto',
'clicpay_reference' => 'n',
'provider_reference' => 'g',
'wallet_id' => 16,
],
'sort' => 'amount',
'paginator' => 'cursor',
'per_page' => 22,
'page' => 67,
'cursor' => 'architecto',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/transactions'
payload = {
"filter": {
"date_from": "2026-09-15T00:58:45",
"date_to": "2052-10-08",
"status": [
"FAILED"
],
"type": [
"TRANSFER_IN"
],
"provider": "architecto",
"clicpay_reference": "n",
"provider_reference": "g",
"wallet_id": 16
},
"sort": "amount",
"paginator": "cursor",
"per_page": 22,
"page": 67,
"cursor": "architecto"
}
params = {
'filter[wallet_id]': '123',
'filter[date_from]': '2026-01-01',
'filter[date_to]': '2026-06-30',
'filter[status]': 'SUCCESSFUL',
'filter[type]': 'C2B',
'filter[provider]': 'mpesa',
'filter[clicpay_reference]': 'CPAYEMOLAC2B...',
'filter[provider_reference]': 'PROV-12345',
'sort': '-created_at',
'paginator': 'cursor',
'per_page': '50',
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers, json=payload, params=params)
response.json()Example response (200, Mesmo shape de /wallets/{wallet}/transactions):
{
"data": [],
"meta": {
"pagination": {
"type": "cursor",
"per_page": 50,
"count": 0,
"next_cursor": null,
"prev_cursor": null,
"has_more": false
}
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (422):
{
"message": "Filter inválido.",
"errors": {
"filter.status.0": [
"..."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Histórico de transacções de uma carteira.
requires authentication
Example request:
curl --request GET \
--get "https://clicpay.co.mz/api/v2/wallets/115665/transactions?filter%5Bdate_from%5D=2026-01-01&filter%5Bdate_to%5D=2026-06-30&filter%5Bstatus%5D=SUCCESSFUL&filter%5Btype%5D=C2B&filter%5Bprovider%5D=mpesa&filter%5Bclicpay_reference%5D=CPAYEMOLAC2B...&filter%5Bprovider_reference%5D=PROV-12345&sort=-created_at&paginator=cursor&per_page=50&cursor=architecto" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"filter\": {
\"date_from\": \"2026-09-15T00:58:45\",
\"date_to\": \"2052-10-08\",
\"status\": [
\"REFUNDED\"
],
\"type\": [
\"SUBSCRIPTION_PAYMENT\"
],
\"provider\": \"architecto\",
\"clicpay_reference\": \"n\",
\"provider_reference\": \"g\",
\"wallet_id\": 16
},
\"sort\": \"-completed_at\",
\"paginator\": \"offset\",
\"per_page\": 22,
\"page\": 67,
\"cursor\": \"architecto\"
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/transactions"
);
const params = {
"filter[date_from]": "2026-01-01",
"filter[date_to]": "2026-06-30",
"filter[status]": "SUCCESSFUL",
"filter[type]": "C2B",
"filter[provider]": "mpesa",
"filter[clicpay_reference]": "CPAYEMOLAC2B...",
"filter[provider_reference]": "PROV-12345",
"sort": "-created_at",
"paginator": "cursor",
"per_page": "50",
"cursor": "architecto",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"filter": {
"date_from": "2026-09-15T00:58:45",
"date_to": "2052-10-08",
"status": [
"REFUNDED"
],
"type": [
"SUBSCRIPTION_PAYMENT"
],
"provider": "architecto",
"clicpay_reference": "n",
"provider_reference": "g",
"wallet_id": 16
},
"sort": "-completed_at",
"paginator": "offset",
"per_page": 22,
"page": 67,
"cursor": "architecto"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/transactions';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'filter[date_from]' => '2026-01-01',
'filter[date_to]' => '2026-06-30',
'filter[status]' => 'SUCCESSFUL',
'filter[type]' => 'C2B',
'filter[provider]' => 'mpesa',
'filter[clicpay_reference]' => 'CPAYEMOLAC2B...',
'filter[provider_reference]' => 'PROV-12345',
'sort' => '-created_at',
'paginator' => 'cursor',
'per_page' => '50',
'cursor' => 'architecto',
],
'json' => [
'filter' => [
'date_from' => '2026-09-15T00:58:45',
'date_to' => '2052-10-08',
'status' => [
'REFUNDED',
],
'type' => [
'SUBSCRIPTION_PAYMENT',
],
'provider' => 'architecto',
'clicpay_reference' => 'n',
'provider_reference' => 'g',
'wallet_id' => 16,
],
'sort' => '-completed_at',
'paginator' => 'offset',
'per_page' => 22,
'page' => 67,
'cursor' => 'architecto',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/transactions'
payload = {
"filter": {
"date_from": "2026-09-15T00:58:45",
"date_to": "2052-10-08",
"status": [
"REFUNDED"
],
"type": [
"SUBSCRIPTION_PAYMENT"
],
"provider": "architecto",
"clicpay_reference": "n",
"provider_reference": "g",
"wallet_id": 16
},
"sort": "-completed_at",
"paginator": "offset",
"per_page": 22,
"page": 67,
"cursor": "architecto"
}
params = {
'filter[date_from]': '2026-01-01',
'filter[date_to]': '2026-06-30',
'filter[status]': 'SUCCESSFUL',
'filter[type]': 'C2B',
'filter[provider]': 'mpesa',
'filter[clicpay_reference]': 'CPAYEMOLAC2B...',
'filter[provider_reference]': 'PROV-12345',
'sort': '-created_at',
'paginator': 'cursor',
'per_page': '50',
'cursor': 'architecto',
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers, json=payload, params=params)
response.json()Example response (200):
{
"data": [
{
"id": 9876,
"clicpay_reference": "CPAYEMOLAC2BABCDE12345",
"provider_reference": "EMOLA-99887",
"type": "C2B",
"status": "SUCCESSFUL",
"currency": "MZN",
"amount": "500.00",
"received_amount": "493.50",
"customer_msisdn": "+258841234567",
"description": "Pagamento de Serviço",
"wallet": {
"id": 123,
"name": "Mpesa Principal",
"payment_method": {
"name": "Mpesa",
"slug": "mpesa"
}
},
"wallet_split": null,
"initiated_at": "2026-06-03T15:01:00+00:00",
"completed_at": "2026-06-03T15:01:18+00:00",
"created_at": "2026-06-03T15:01:00+00:00"
}
],
"meta": {
"pagination": {
"type": "cursor",
"per_page": 50,
"count": 1,
"next_cursor": null,
"prev_cursor": null,
"has_more": false
}
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (403):
{
"message": "This action is unauthorized."
}
Example response (422):
{
"message": "Sort inválido.",
"errors": {
"sort": [
"..."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Histórico de transacções de uma subcarteira.
requires authentication
Example request:
curl --request GET \
--get "https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/transactions?filter%5Bdate_from%5D=2026-01-01&filter%5Bdate_to%5D=2026-06-30&filter%5Bstatus%5D=SUCCESSFUL&filter%5Btype%5D=C2B&filter%5Bprovider%5D=mpesa&paginator=cursor&per_page=50" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"filter\": {
\"date_from\": \"2026-09-15T00:58:45\",
\"date_to\": \"2052-10-08\",
\"status\": [
\"PARTIALLY_REFUNDED\"
],
\"type\": [
\"DEPOSIT\"
],
\"provider\": \"architecto\",
\"clicpay_reference\": \"n\",
\"provider_reference\": \"g\",
\"wallet_id\": 16
},
\"sort\": \"-amount\",
\"paginator\": \"cursor\",
\"per_page\": 22,
\"page\": 67,
\"cursor\": \"architecto\"
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/transactions"
);
const params = {
"filter[date_from]": "2026-01-01",
"filter[date_to]": "2026-06-30",
"filter[status]": "SUCCESSFUL",
"filter[type]": "C2B",
"filter[provider]": "mpesa",
"paginator": "cursor",
"per_page": "50",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"filter": {
"date_from": "2026-09-15T00:58:45",
"date_to": "2052-10-08",
"status": [
"PARTIALLY_REFUNDED"
],
"type": [
"DEPOSIT"
],
"provider": "architecto",
"clicpay_reference": "n",
"provider_reference": "g",
"wallet_id": 16
},
"sort": "-amount",
"paginator": "cursor",
"per_page": 22,
"page": 67,
"cursor": "architecto"
};
fetch(url, {
method: "GET",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/transactions';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'filter[date_from]' => '2026-01-01',
'filter[date_to]' => '2026-06-30',
'filter[status]' => 'SUCCESSFUL',
'filter[type]' => 'C2B',
'filter[provider]' => 'mpesa',
'paginator' => 'cursor',
'per_page' => '50',
],
'json' => [
'filter' => [
'date_from' => '2026-09-15T00:58:45',
'date_to' => '2052-10-08',
'status' => [
'PARTIALLY_REFUNDED',
],
'type' => [
'DEPOSIT',
],
'provider' => 'architecto',
'clicpay_reference' => 'n',
'provider_reference' => 'g',
'wallet_id' => 16,
],
'sort' => '-amount',
'paginator' => 'cursor',
'per_page' => 22,
'page' => 67,
'cursor' => 'architecto',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/transactions'
payload = {
"filter": {
"date_from": "2026-09-15T00:58:45",
"date_to": "2052-10-08",
"status": [
"PARTIALLY_REFUNDED"
],
"type": [
"DEPOSIT"
],
"provider": "architecto",
"clicpay_reference": "n",
"provider_reference": "g",
"wallet_id": 16
},
"sort": "-amount",
"paginator": "cursor",
"per_page": 22,
"page": 67,
"cursor": "architecto"
}
params = {
'filter[date_from]': '2026-01-01',
'filter[date_to]': '2026-06-30',
'filter[status]': 'SUCCESSFUL',
'filter[type]': 'C2B',
'filter[provider]': 'mpesa',
'paginator': 'cursor',
'per_page': '50',
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers, json=payload, params=params)
response.json()Example response (200, Mesmo shape de /wallets/{wallet}/transactions):
{
"data": [],
"meta": {
"pagination": {
"type": "cursor",
"per_page": 50,
"count": 0,
"next_cursor": null,
"prev_cursor": null,
"has_more": false
}
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (403):
{
"message": "This action is unauthorized."
}
Example response (404, Split não pertence à carteira indicada):
{
"message": "No query results for model [App\\Models\\WalletSplit]."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Endpoints
GET api/v2/payment-cards
requires authentication
Example request:
curl --request GET \
--get "https://clicpay.co.mz/api/v2/payment-cards" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://clicpay.co.mz/api/v2/payment-cards"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/payment-cards';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/payment-cards'
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()Example response (401):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"message": "Unauthenticated."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
POST api/v2/wallets/{wallet_id}/payment-cards/setup
requires authentication
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/payment-cards/setup" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"callback_url\": \"http:\\/\\/www.bailey.biz\\/quos-velit-et-fugiat-sunt-nihil-accusantium-harum.html\",
\"from_app\": \"i\"
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/payment-cards/setup"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"callback_url": "http:\/\/www.bailey.biz\/quos-velit-et-fugiat-sunt-nihil-accusantium-harum.html",
"from_app": "i"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/payment-cards/setup';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'callback_url' => 'http://www.bailey.biz/quos-velit-et-fugiat-sunt-nihil-accusantium-harum.html',
'from_app' => 'i',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/payment-cards/setup'
payload = {
"callback_url": "http:\/\/www.bailey.biz\/quos-velit-et-fugiat-sunt-nihil-accusantium-harum.html",
"from_app": "i"
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (401):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"message": "Unauthenticated."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
POST api/v2/wallets/{wallet_id}/payment-cards/{paymentCard_id}/pay
requires authentication
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/payment-cards/16/pay" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"amount\": 16,
\"reference_description\": \"n\",
\"callback_url\": \"http:\\/\\/crooks.biz\\/et-fugiat-sunt-nihil-accusantium\",
\"from_app\": \"n\"
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/payment-cards/16/pay"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"amount": 16,
"reference_description": "n",
"callback_url": "http:\/\/crooks.biz\/et-fugiat-sunt-nihil-accusantium",
"from_app": "n"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/payment-cards/16/pay';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'amount' => 16,
'reference_description' => 'n',
'callback_url' => 'http://crooks.biz/et-fugiat-sunt-nihil-accusantium',
'from_app' => 'n',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/payment-cards/16/pay'
payload = {
"amount": 16,
"reference_description": "n",
"callback_url": "http:\/\/crooks.biz\/et-fugiat-sunt-nihil-accusantium",
"from_app": "n"
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (401):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"message": "Unauthenticated."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
GET api/v2/companies
requires authentication
Example request:
curl --request GET \
--get "https://clicpay.co.mz/api/v2/companies" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"https://clicpay.co.mz/api/v2/companies"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/companies';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/companies'
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()Example response (401):
Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
{
"message": "Unauthenticated."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Transações M-Pesa — B2C via Split
POST api/v2/wallets/{wallet_id}/splits/{walletSplit_id}/b2c/mpesa
requires authentication
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/b2c/mpesa" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"msisdn\": \"841234567\",
\"amount\": 500,
\"reference_description\": \"Pagamento parceiro\",
\"internal_notes\": \"Split B2C mensal\"
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/b2c/mpesa"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"msisdn": "841234567",
"amount": 500,
"reference_description": "Pagamento parceiro",
"internal_notes": "Split B2C mensal"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/b2c/mpesa';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'msisdn' => '841234567',
'amount' => 500.0,
'reference_description' => 'Pagamento parceiro',
'internal_notes' => 'Split B2C mensal',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/b2c/mpesa'
payload = {
"msisdn": "841234567",
"amount": 500,
"reference_description": "Pagamento parceiro",
"internal_notes": "Split B2C mensal"
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (200):
{
"message": "Transação iniciada com sucesso",
"clicpay_reference": "CPAYMPESAB2CABCDE12345",
"status": "pending",
"transaction_id": 790,
"wallet_split_id": 7
}
Example response (403):
{
"message": "Este split não tem permissão para realizar transações B2C."
}
Example response (422):
{
"message": "Saldo insuficiente no split."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Transações Mkesh — B2C via Split
POST api/v2/wallets/{wallet_id}/splits/{walletSplit_id}/b2c/mkesh
requires authentication
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/b2c/mkesh" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"msisdn\": \"841234567\",
\"amount\": 500,
\"reference_description\": \"Pagamento parceiro\",
\"internal_notes\": \"Split B2C mensal\"
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/b2c/mkesh"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"msisdn": "841234567",
"amount": 500,
"reference_description": "Pagamento parceiro",
"internal_notes": "Split B2C mensal"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/b2c/mkesh';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'msisdn' => '841234567',
'amount' => 500.0,
'reference_description' => 'Pagamento parceiro',
'internal_notes' => 'Split B2C mensal',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/b2c/mkesh'
payload = {
"msisdn": "841234567",
"amount": 500,
"reference_description": "Pagamento parceiro",
"internal_notes": "Split B2C mensal"
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (200):
{
"message": "Transação iniciada com sucesso",
"clicpay_reference": "CPAYMKESHB2CABCDE12345",
"status": "pending",
"transaction_id": 791,
"wallet_split_id": 7
}
Example response (403):
{
"message": "Este split não tem permissão para realizar transações B2C."
}
Example response (422):
{
"message": "Saldo insuficiente no split."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Transações eMola — B2C via Split
POST api/v2/wallets/{wallet_id}/splits/{walletSplit_id}/b2c/emola
requires authentication
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/b2c/emola" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"msisdn\": \"841234567\",
\"amount\": 500,
\"reference_description\": \"Pagamento parceiro\",
\"internal_notes\": \"Split B2C mensal\"
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/b2c/emola"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"msisdn": "841234567",
"amount": 500,
"reference_description": "Pagamento parceiro",
"internal_notes": "Split B2C mensal"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/b2c/emola';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'msisdn' => '841234567',
'amount' => 500.0,
'reference_description' => 'Pagamento parceiro',
'internal_notes' => 'Split B2C mensal',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/splits/100000/b2c/emola'
payload = {
"msisdn": "841234567",
"amount": 500,
"reference_description": "Pagamento parceiro",
"internal_notes": "Split B2C mensal"
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (200):
{
"message": "Transação iniciada com sucesso",
"clicpay_reference": "CPAYEMOLAB2CABCDE12345",
"status": "pending",
"transaction_id": 789,
"wallet_split_id": 7
}
Example response (403):
{
"message": "Este split não tem permissão para realizar transações B2C."
}
Example response (422):
{
"message": "Saldo insuficiente no split.",
"needed": 530,
"available": 200,
"missing": 330,
"wallet_split_id": 7
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Transações — Split Collect
Iniciar cobrança com split collect
requires authentication
Idempotência. Envie Idempotency-Key com um valor único por tentativa de
pagamento (UUID v4 recomendado, máximo 128 caracteres). Repetir o pedido com a
mesma chave e o mesmo corpo devolve a resposta guardada, com o mesmo estado HTTP
e o mesmo clicpay_reference, acompanhada do cabeçalho Idempotent-Replayed: true,
sem contactar o operador e sem criar uma segunda transacção. A chave é privada da
sua conta e vale 48 horas. Sem o cabeçalho, o comportamento é o de sempre.
Em 409, outro pedido com essa chave ainda está a ser processado: espere o
Retry-After e repita com a mesma chave. Gerar uma chave nova nesse momento é
o caminho para o pagamento duplicado.
Example request:
curl --request POST \
"https://clicpay.co.mz/api/v2/wallets/115665/split/collect" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Idempotency-Key: 9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"msisdn\": \"841234567\",
\"amount\": 1000,
\"reference_description\": \"Pagamento de serviços\",
\"internal_notes\": \"Pedido #9001\",
\"splits\": [
\"architecto\"
]
}"
const url = new URL(
"https://clicpay.co.mz/api/v2/wallets/115665/split/collect"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Idempotency-Key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pedido #9001",
"splits": [
"architecto"
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());$client = new \GuzzleHttp\Client();
$url = 'https://clicpay.co.mz/api/v2/wallets/115665/split/collect';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key' => '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'msisdn' => '841234567',
'amount' => 1000.0,
'reference_description' => 'Pagamento de serviços',
'internal_notes' => 'Pedido #9001',
'splits' => [
'architecto',
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));import requests
import json
url = 'https://clicpay.co.mz/api/v2/wallets/115665/split/collect'
payload = {
"msisdn": "841234567",
"amount": 1000,
"reference_description": "Pagamento de serviços",
"internal_notes": "Pedido #9001",
"splits": [
"architecto"
]
}
headers = {
'Authorization': 'Bearer {YOUR_AUTH_KEY}',
'Idempotency-Key': '9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()Example response (200):
{
"message": "Transação iniciada com sucesso",
"clicpay_reference": "CPAY...",
"status": "pending",
"transaction_id": 789,
"split_summary": {
"direct": [],
"collect": []
}
}
Example response (401):
{
"message": "Unauthenticated."
}
Example response (409, Pedido anterior com a mesma chave ainda em curso):
{
"error": "idempotency_request_in_progress",
"message": "Um pedido com esta Idempotency-Key ainda está a ser processado. Aguarde e repita com a MESMA chave.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11",
"retry_after_seconds": 12
}
Example response (422, Erro de validação):
{
"errors": {
"splits.0.wallet_split_id": [
"O split não pertence a esta carteira ou não é dynamic_load."
]
}
}
Example response (422, Idempotency-Key reutilizada com um corpo diferente):
{
"error": "idempotency_key_reused_with_different_payload",
"message": "Esta Idempotency-Key já foi usada com um corpo diferente.",
"idempotency_key": "9f1c2c1e-6a7c-4e1a-9c2a-7f0c2b3a5d11"
}
Example response (422, Idempotency-Key com formato inválido):
{
"error": "idempotency_key_invalid",
"message": "O cabeçalho Idempotency-Key deve ter entre 1 e 128 caracteres.",
"max_length": 128
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.