1. Autenticação
Todos os pedidos exigem três credenciais obrigatórias:
- Wallet ID — identificador único de 6 dígitos do merchant (header
X-Wallet-ID). - API Key — chave secreta começada por
ns_live_ouns_test_(headerAuthorization: Bearer …). - Base URL —
https://www.netshop.co.mz/api/v1(100% LIVE, sem subdomínios e sem ambiente de testes).
curl https://www.netshop.co.mz/api/v1/charges \
-H "Authorization: Bearer ns_live_sk_4f8a2c…" \
-H "X-Wallet-ID: 418207" \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-H "Content-Type: application/json"O Wallet ID é mostrado no canto superior direito do painel de cada merchant e em /app/definicoes. Pedidos sem Wallet ID válido devolvem 401 missing_or_invalid_wallet_id.
2. Base URL & Versões
A API é versionada por URL. A versão estável actual é v1. Servimos toda a plataforma a partir de netshop.co.mz — sem subdomínios (nada de pay., api. ou split.). Use sempre o domínio whitelabel:
Base URL (LIVE): https://www.netshop.co.mz/api/v1
Links de pagamento: www.netshop.co.mz/pay/{code}
Hosted checkout: www.netshop.co.mz/link/{id}
Split landing: www.netshop.co.mz/split/{id}Health-check: antes de ir a produção, valide a Base URL com GET https://www.netshop.co.mz/api/v1/ping — deve devolver { "ok": true, "canonical_host": true }. Se canonical_host vier false, a URL configurada no seu backend está errada.
curl -i https://www.netshop.co.mz/api/v1/ping3. Cobranças (Charges)
Criar uma cobrança Visa/Mastercard, M-Pesa, e-Mola ou mKesh. Para method:"card" a resposta inclui um checkout.hosted_url (página segura hospedada pelo NetShop); para carteiras móveis a transacção é confirmada em tempo real pelo cliente no telemóvel.
POST https://www.netshop.co.mz/api/v1/charges
{
"amount": 2500,
"currency": "MZN",
"method": "mpesa", // card | mpesa | emola | mkesh
"msisdn": "+258842828600", // obrigatório para wallets móveis (omitir em card)
"customer_email": "cli@ex.mz", // recomendado para cartões
"tokenize_for_recurring": false, // true → prepara o cartão para subscrições
"reference": "Fatura #2410",
"metadata": { "order_id": "ord_001" }
}Redirecionar o cliente para o seu site (return_url)
Envie return_url (HTTPS) no POST /charges. Após o pagamento, o cliente é reencaminhado para esse endereço em vez de ficar numa página NetShop. Aplica-se ao checkout de cartão e ao checkout hospedado e-Mola.
{
"amount": 2500,
"method": "card",
"reference": "Fatura #2410",
"return_url": "https://minhaloja.mz/checkout/retorno"
}
# NetShop acrescenta os parâmetros ao seu URL:
# https://minhaloja.mz/checkout/retorno?status=paid&id=ch_API-XXXX&reference=Fatura%20%232410
# status ∈ paid | failed | pendingO return_url é apenas uma conveniência de UX: confirme sempre o pagamento pelo webhook ou por GET /charges/{id} antes de libertar o produto.
Resposta:
{
"id": "ch_01HZ…",
"status": "paid", // paid | pending | failed
"amount": 2500,
"currency": "MZN",
"fees": { "platform": 375 },
"net": 2125,
"provider": { "transactionID": "DFR5KMP1B65", "thirdPartyReference": "ord_001" }
}Resposta (cartão / Checkout hospedado NetShop):
{
"id": "ch_PL-XXXX",
"status": "pending",
"method": "card",
"amount": 2500,
"currency": "MZN",
"reference": "Fatura #2410",
"checkout": {
"type": "hosted_url",
"hosted_url": "https://netshop.co.mz/pay/card/PL-XXXX?session=...",
"order_id": "PL-XXXX"
}
}Fluxo cartão: redireccione o cliente para hosted_url — a página de pagamento é servida pelo NetShop com a marca do seu merchant. Após a autorização, a transacção converge para paid ou failed e o evento é enviado para o webhook que configurou no dashboard.
Consultar estado de uma cobrança
Se o seu sistema não receber a confirmação pelo webhook (ou pela resposta síncrona), consulte o estado actual da transacção. Este endpoint é a fonte de verdade — pode chamar sempre que precisar de reconciliar.
GET https://www.netshop.co.mz/api/v1/charges/{id}
# {id} aceita:
# • o "id" devolvido no POST /charges (ex.: ch_NSABC123)
# • o "reference" que enviou (ex.: Fatura #2410)curl https://www.netshop.co.mz/api/v1/charges/ch_NSABC123 \
-H "Authorization: Bearer ns_live_sk_4f8a2c…" \
-H "X-Wallet-ID: 418207"Resposta:
{
"id": "ch_NSABC123",
"status": "paid", // paid | pending | failed
"amount": 2500,
"currency": "MZN",
"method": "mpesa",
"reference": "Fatura #2410",
"msisdn": "842828600",
"fee": 250,
"net": 2250,
"provider": {
"transactionID": "DFR5KMP1B65",
"thirdPartyReference": "NSABC123",
"responseCode": "INS-0",
"responseDesc": "Request processed successfully"
},
"failed_reason": null,
"card": {
"masked_pan": "512345xxxxxx0008",
"first6": "512345",
"last4": "0008",
"brand": "MASTERCARD",
"scheme": "MASTERCARD",
"funding_method": "CREDIT",
"issuer": "BANCO XYZ",
"issuer_country": "MOZ",
"expiry_month": 5,
"expiry_year": 30
},
"created_at": "2026-07-14T14:03:11.000Z",
"processed_at": "2026-07-14T14:03:22.000Z"
}O objecto card só é devolvido em cobranças method: "card" e contém apenas dados não sensíveis (PAN mascarado com os primeiros 6 e últimos 4 dígitos, marca/scheme, país emissor). O mesmo objecto é enviado no webhook charge.paid / charge.failed.
Cobranças presas em pending há mais de 5 minutos disparam automaticamente a rotina de reconciliação com o provedor antes de responderem, pelo que o estado devolvido reflecte o mais recente disponível. Se a cobrança não existir para o Wallet ID autenticado, a API devolve 404 charge_not_found.
4. Links de Pagamento
POST https://www.netshop.co.mz/api/v1/payment-links
{
"title": "Curso UX 2026",
"amount": 4500,
"currency": "MZN",
"expires_at": "2026-08-01T23:59:00Z",
"max_uses": 50,
"redirect_url": "https://minhaloja.mz/obrigado"
}Devolve { "id": "...", "slug": "abc123", "url": "https://www.netshop.co.mz/pay/abc123", "expires_at": ..., "max_uses": ..., "uses_count": 0 }. Branding (logo, cores, nome, contactos) é herdado automaticamente do perfil do merchant.
GET https://www.netshop.co.mz/api/v1/payment-links # lista os últimos 100 links
GET https://www.netshop.co.mz/api/v1/payment-links/{id|slug} # estado do link (expired, exhausted, uses_count)
PATCH https://www.netshop.co.mz/api/v1/payment-links/{id|slug} # actualizar expires_at, max_uses, amount, status, redirect_url
DELETE https://www.netshop.co.mz/api/v1/payment-links/{id|slug} # arquivar o link
# Exemplo: definir/remover limites depois de criado
curl -X PATCH https://www.netshop.co.mz/api/v1/payment-links/abc123 \
-H "Authorization: Bearer $NETSHOP_API_KEY" \
-H "X-Wallet-Id: 123456" \
-H "Content-Type: application/json" \
-d '{"expires_at":"2026-09-30T23:59:00Z","max_uses":100}'
# Remover o limite: envie null
# {"expires_at": null, "max_uses": null}Expiração dos links
Um link só expira se lhe definir expires_at (ou um limite de utilizações max_uses). Sem esses campos o link permanece válido até ser arquivado/desactivado no painel. Quando o cliente abre um link já expirado, a página mostra o aviso de link expirado e nenhuma cobrança é criada.
# Cliente abre link expirado → página "Link expirado" (erro LINK_EXPIRED)
# Link já usado o nº máximo → LINK_EXHAUSTED
# Link arquivado/inactivo → LINK_INACTIVE
# Consulta de estado: como nunca existiu cobrança para esse link,
# GET /charges/{referencia} devolve 404 charge_not_found.5. Split Payments
Distribuir uma cobrança por várias sub-contas (regras criadas em /app/sub-contas):
POST https://www.netshop.co.mz/api/v1/splits/process
{
"split_id": "uuid-do-split",
"transaction_reference": "ord_001",
"gross_amount": 10000,
"platform_fee": 1500,
"gateway_fee": 0,
"payment_method": "mpesa",
"currency": "MZN",
"metadata": {}
}É idempotente por (merchant, transaction_reference): o mesmo pedido nunca distribui duas vezes.
6. Subscrições / Débito Directo (Visa·Mastercard)
Débito automático recorrente está disponível exclusivamente em Visa/Mastercard. Carteiras móveis (M-Pesa, e-Mola, mKesh) não suportam mandatos recorrentes — para cobranças únicas use POST /charges.
POST https://www.netshop.co.mz/api/v1/subscriptions
{
"amount": 1200,
"currency": "MZN",
"frequency": "monthly",
"custom_interval_days": null,
"reference": "PLAN-PRO-2026-001",
"label": "Subscrição Plano Pro",
"customer_name": "Ana Macuácua",
"customer_email": "ana@exemplo.mz",
"metadata": { "plan": "pro" }
}Frequências aceites: daily, weekly, monthly, yearly, custom (obriga custom_interval_days entre 1 e 365).
Resposta:
{
"id": "sub_01HZ…",
"reference": "PLAN-PRO-2026-001",
"status": "pending",
"amount": 1200,
"currency": "MZN",
"frequency": "monthly",
"customer": { "name": "Ana Macuácua", "email": "ana@exemplo.mz" },
"checkout": { "type": "hosted_url", "url": "https://www.netshop.co.mz/s/PLAN-PRO-2026-001" }
}Abra checkout.url para o cliente aceitar o mandato, autorizar o 1º ciclo e tokenizar o cartão. Após o pagamento paid, a subscrição passa a active e os ciclos seguintes são debitados automaticamente pelo NetShop nas datas do plano (sem nova interacção do cliente).
7. Payouts (B2C)
Envie dinheiro da sua carteira NetShop para qualquer MSISDN M-Pesa ou e-Mola. Mesmo modelo de autenticação, idempotência e webhooks das cobranças. Sem mínimo em B2C automatizado.
O payout debita apenas o saldo disponível na sua conta NetShop (cobranças liquidadas menos comissões e payouts anteriores). Pedidos acima do disponível são rejeitados com 422 insufficient_balance.
POST https://www.netshop.co.mz/api/v1/payouts
{
"amount": 1500,
"currency": "MZN",
"method": "mpesa", // mpesa | emola
"msisdn": "+258842828600", // MSISDN do destinatário
"reference": "SAL-2410-001", // identificador único no seu sistema
"metadata": { "purpose": "salario" }
}Resposta:
{
"id": "po_NB01HZ…",
"status": "completed", // completed | pending | failed
"amount": 1500,
"currency": "MZN",
"method": "mpesa",
"fees": { "our": 90, "provider": 60 },
"net": 1350,
"reference": "SAL-2410-001",
"provider": {
"transactionID": "DFR5KMP1B65",
"thirdPartyReference": "NB01HZ…"
}
}Payouts assíncronos (status:"pending") convergem via callback do provedor. Assim que confirmados, disparamos payout.completed ou payout.failed no seu webhook. Cartões (Visa/Mastercard) não suportam B2C — para reembolsos use POST /refunds.
Consultar estado de um payout
Se não receber a confirmação pelo webhook (ou pela resposta síncrona), consulte o estado actual do payout. Fonte de verdade — pode chamar sempre que precisar de reconciliar.
GET https://www.netshop.co.mz/api/v1/payouts/{id}
# {id} aceita:
# • o "id" devolvido no POST /payouts (ex.: po_NB01HZ…)
# • o "reference" que enviou (ex.: SAL-2410-001)curl https://www.netshop.co.mz/api/v1/payouts/po_NB01HZ \
-H "Authorization: Bearer ns_live_sk_4f8a2c…" \
-H "X-Wallet-ID: 418207"Resposta:
{
"id": "po_NB01HZ…",
"status": "completed", // completed | pending | failed
"amount": 1500,
"currency": "MZN",
"method": "mpesa",
"reference": "SAL-2410-001",
"msisdn": "842828600",
"fees": { "our": 90, "provider": 60 },
"net": 1350,
"provider": {
"transactionID": "DFR5KMP1B65",
"thirdPartyReference": "NB01HZ…",
"responseCode": "INS-0",
"responseDesc": "Request processed successfully"
},
"failed_reason": null,
"created_at": "2026-07-14T14:03:11.000Z",
"processed_at": "2026-07-14T14:03:22.000Z"
}Payouts presos em pending há mais de 5 minutos disparam automaticamente a rotina de reconciliação com o provedor antes de responderem. Se o payout não existir para o Wallet ID autenticado, a API devolve 404 payout_not_found.
8. Reembolsos (Refunds)
Reembolsos totais ou parciais de uma cobrança liquidada. Cartões são reembolsados pela gateway para o mesmo cartão; carteiras móveis (M-Pesa, e-Mola, mKesh) são devolvidas ao MSISDN pagador. O pedido entra como pending e é executado pela NetShop.
POST https://www.netshop.co.mz/api/v1/refunds
{
"charge_id": "ch_API-MSNBAIES-XS13D", // id ou reference da cobrança
"amount": 500, // opcional → omitir reembolsa o total
"reason": "requested_by_customer", // duplicate | fraudulent | requested_by_customer
// | product_not_received | other
"note": "Cliente cancelou a encomenda"
}Resposta 202:
{
"id": "re_RF8KD2P1",
"status": "pending", // pending | completed | failed | rejected
"charge_id": "ch_API-MSNBAIES-XS13D",
"amount": 500,
"currency": "MZN",
"method": "card",
"is_partial": true,
"fee_refund": 50,
"net": 450,
"reason": "requested_by_customer",
"failed_reason": null,
"reference": "RF8KD2P1",
"created_at": "2026-08-10T15:02:11.000Z"
}GET https://www.netshop.co.mz/api/v1/refunds/{id} # id: re_RF8KD2P1, RF8KD2P1 ou o id da cobrança
curl https://www.netshop.co.mz/api/v1/refunds/re_RF8KD2P1 \
-H "Authorization: Bearer ns_live_sk_4f8a2c…" \
-H "X-Wallet-ID: 418207"Erros específicos: 404 charge_not_found, 422 charge_not_refundable (a cobrança não está paid), 422 refund_exceeds_charge e 422 refund_exceeds_remaining (já reembolsado no todo ou em parte).
9. Webhooks
Eventos enviados ao seu endpoint HTTPS, com retentativas exponenciais até 72h:
- charge.paid
- charge.failed
- charge.pending
- refund.created
- payout.completed
- payout.failed
- dispute.opened
- subscription.renewed
Cada pedido inclui o header X-NetShop-Signature (HMAC-SHA256 sobre o corpo). Valide sempre antes de processar:
const expected = hmacSha256(secret, rawBody);
if (!timingSafeEqual(expected, signatureHeader)) reject(401);10. Idempotência
Todos os POST aceitam Idempotency-Key (UUID único). Pedidos repetidos com a mesma chave devolvem a resposta original — seguro para retries com timeout.
11. Limites & Mínimos
Valores mínimos por método de pagamento e por payout, aplicáveis em LIVE:
| Operação | Método | Mínimo |
|---|---|---|
| Cobrança | M-Pesa | 10 MT |
| Cobrança | mKesh | 10 MT |
| Cobrança | e-Mola | 10 MT |
| Cobrança | Visa / Mastercard | 50 MT |
| Cobrança ZAR | Visa / Mastercard | R 10 |
| Payout manual | Banco / Wallet | 1 000 MT |
| Payout automático / B2C | M-Pesa, e-Mola, mKesh | Sem mínimo |
12. Estados & Códigos de Erro
Estado é a fonte de verdade
Use sempre o campo status devolvido por GET /charges/{id} (ou pelo webhook) como decisão final. Só paid e failed são estados terminais.
| status | Significado | Acção |
|---|---|---|
| paid | Pago e liquidado (terminal) | Libertar produto/serviço |
| failed | Recusado ou cancelado (terminal) | Mostrar failed_reason |
| pending | Em curso: cliente ainda não confirmou no telemóvel, 3DS por concluir ou callback do provedor por chegar | Voltar a consultar (polling 5–10 s, até 30 min) |
Nos payouts o estado terminal de sucesso chama-se completed (equivalente a paid). Nos reembolsos: pending → completed | failed | rejected.
responseCode / responseDesc / failed_reason
provider.responseCodeeprovider.responseDesc— preenchidos assim que o provedor (M-Pesa, PaySuite/e-Mola, mKesh, MPGS) responde, em qualquer estado. São o código e a mensagem crus do provedor; use-os para diagnóstico, nunca para decidir o estado.failed_reason— preenchido apenas quandostatus = failed. É a mensagem legível a mostrar ao merchant/cliente. Empaidependingvemnull.- Em cartões (MPGS) o
responseCodepode virnulle a razão da recusa aparece emfailed_reason.
| responseCode | Mensagem típica | status resultante |
|---|---|---|
| INS-0 | Request processed successfully | paid |
| INS-1 | Internal error / transacção não concluída | failed |
| INS-6 | Transaction failed | failed |
| INS-2006 | Saldo insuficiente do cliente | failed |
| INS-2051 | MSISDN inválido | failed |
| INS-9 | Request timeout — cliente não confirmou a tempo | pending |
| TIMEOUT | Sem resposta do provedor; o pagador pode ter sido debitado | pending |
| min_amount | Valor abaixo do mínimo do método | failed |
| processing | e-Mola/mKesh: push enviado, a aguardar o PIN do cliente | pending |
| DECLINED / 3DS_FAILED | Cartão recusado pelo emissor ou 3DS falhado | failed |
A lista de códigos dos provedores pode crescer — trate qualquer código desconhecido pelo status e mostre responseDesc/failed_reason como texto.
Erros HTTP da API
401 missing_or_invalid_api_key
401 missing_or_invalid_wallet_id
403 wallet_id_mismatch
400 validation_error
422 processing_failed
422 amount_below_minimum · amount_above_maximum · method_disabled
422 charge_not_refundable · refund_exceeds_charge · refund_exceeds_remaining
404 charge_not_found · payout_not_found · refund_not_found
409 idempotency_conflict
429 rate_limited
500 internal_error13. SDKs Oficiais
- Node.js / TypeScript —
npm i @netshop/node - Python —
pip install netshop - PHP —
composer require netshop/netshop-php - Java —
com.netshop:netshop-java:1.x
Plugins prontos: WooCommerce e WHMCS. Para Shopify use o guia NetShop + Shopify (Custom Payment).