Unified charge API
Optional cloud path: one HTTP contract across many SSLCommerz / bKash credential slots. Default product is library-first — start at /docs/library (simulator + guides). Customer funds settle at merchant gateway accounts either way.
Getting started
- Sign in to the portal (
demo@payway.local/ChangeMe123!in dev) to get a JWT. - Add at least one credential slot (SSLCommerz or bKash).
- Mint an API key and store it in your backend secrets.
- Follow the implementation guide (Web Forms Path A/B, then redirect + confirm status).
- Or call POST /v1/charges directly and redirect to
checkoutUrl. - Receive the result via webhooks and/or poll GET /v1/charges/{id}.
http://localhost:5080. Every path below is prefixed with /v1. The interactive “Try it” panels call whatever base URL you set.orderId, successUrl,preferredGateway). Send API keys only from your backend — never ship them in a browser bundle.SDKs & plugins
Prefer a thin client over raw HTTP when you can:
| Stack | Package | Install |
|---|---|---|
| .NET (Web Forms → 8) | Sianik.PayWay | NuGet — TFMs net462+ through net8 (samples for net45/net35) |
| Node / TypeScript | @sianik/payway | npm install @sianik/payway (Node 14+) |
| PHP | sianik/payway | composer require sianik/payway (PHP 7.4+) |
| WooCommerce | PayWay for WooCommerce | Install zip from GitHub Releases (payway-woocommerce-x.y.z.zip) |
All clients need baseUrl + apiKey. SSLCommerz / bKash credentials stay in the PayWay portal. Step-by-step (Web Forms first): Implementation guide.
Authentication
Two token types, both sent as Authorization: Bearer <token>:
| Token | Used for | How to get it |
|---|---|---|
pk_… API key | /v1/charges (server-to-server) | Portal → Create API key (shown once) |
| Portal JWT | /v1/portal/* management | POST /v1/portal/auth/login (7-day expiry) |
/v1/portal/auth/loginPublicPortal login
Exchange tenant owner email + password for a 7-day portal JWT.
Use the returned access_token as a Bearer token for every /v1/portal/* management call. The dev seed tenant is demo@payway.local / ChangeMe123!.
Headers
| Header | Value | Required | Notes |
|---|---|---|---|
Content-Type | application/json | yes |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
email | string | yes | Tenant owner email. |
password | string | yes | Plain password; verified with BCrypt server-side. |
Request examples
curl -X POST "https://api.payway.sianik.com/v1/portal/auth/login" \
-H "Content-Type: application/json" \
-d '{
"email": "demo@payway.local",
"password": "ChangeMe123!"
}'Responses
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…",
"tenant_id": 1,
"name": "Demo Tenant"
}UNAUTHORIZED{
"code": "UNAUTHORIZED",
"message": "Invalid credentials."
}Try it
https://api.payway.sianik.com/v1/portal/auth/loginError model
Errors return the matching HTTP status with a JSON body { "code": "…", "message": "…" }. Decrypted gateway secrets are never returned.
| HTTP | code | When |
|---|---|---|
| 400 | VALIDATION_ERROR | Bad payload (amount ≤ 0, missing orderId/successUrl/failUrl, currency ≠ BDT). |
| 401 | UNAUTHORIZED | Missing or invalid API key / credentials. |
| 402 | WALLET_DEPLETED | Free tier exhausted and SaaS fee credit is 0 (operator-seeded; no self-serve top-up). |
| 403 | TENANT_INACTIVE | Tenant account disabled. |
| 404 | NOT_FOUND | Session / resource not found. |
| 409 | NO_ROUTE | No enabled credential slots match the request. |
| 502 | GATEWAY_UNAVAILABLE | Every candidate slot failed with an infra error. |