# Topping up & payments > https://docs.errora.org/en/billing/payments ## Top up **Usage → Top up**: choose an amount and a gateway, and you are redirected to the gateway's page. On return, Errora **verifies** the payment with the gateway and only then credits the wallet. ```text GET /api/v1/payment-gateways # gateways available to you POST /api/v1/organizations/{org_id}/wallet/top-up # {"amount": 500000, "gateway": "zarinpal"} GET /api/v1/organizations/{org_id}/payments GET /payments/callback/{token} # the gateway returns the user here ``` Only the **verify** step moves money. A callback alone never credits a wallet — that is what keeps a forged return URL from minting credit. ## Gateways | Gateway | Use | | --- | --- | | **ZarinPal** | Production payments | | **Test gateway** | Local/staging — renders a confirm/reject page and returns through the same callback | Only the gateways this Errora instance has configured are offered at checkout. ## Payment states | State | Meaning | | --- | --- | | `pending` | Started, user is at the gateway | | `paid` | Verified and credited | | `failed` | The gateway rejected it, or verification failed | | `canceled` | The user came back without paying | The payments table lists every attempt with its reference and receipt, next to the wallet ledger. ## Permissions Topping up and viewing payments requires the **`org:billing`** capability — the `billing` role exists so finance can do this without engineering access. ## Troubleshooting | Symptom | Cause / fix | | --- | --- | | No gateways offered | No payment gateway is available right now — contact support | | Paid but balance unchanged | Verification failed — check the payment row's status; the money is with the gateway, not lost | | Callback returns an error | The callback token expired or was already used; start a new top-up | | Test gateway not offered | It only exists on local and staging environments, never in production |