# FahiPay Wallet API Access wallet balances, spending limits, usage, and transaction history for your personal FahiPay account. **Base URL:** `https://api.fahipay.mv/wallet` ## Authentication Authenticate every request with an API key from [FahiPay Developers](https://fahipay.mv/dev/). ### API key Send your API key in the `X-API-Key` header without a prefix: ```sh curl 'https://api.fahipay.mv/wallet/balance' -H 'Accept: application/json' -H 'X-API-Key: YOUR_API_KEY' ``` Use HTTPS and keep your API key on your server. Each request accesses the wallet associated with your authenticated account. You cannot select another user's wallet through request parameters. ## Endpoints | Method | Path | Description | | --- | --- | --- | | GET | `/balance` | Get wallet balances. | | GET | `/usage` | Get wallet limits, usage, and remaining allowances. | | GET | `/transactions` | Get paginated transaction history. | Paths in the table are relative to the base URL. Only GET requests are supported. A trailing slash is optional. Requests do not require a body. ## Response format Successful requests return HTTP 200. The response shape depends on the endpoint: | Endpoint | Response shape | | --- | --- | | `/balance` | An object with `success: true` and a `data` array of account balance records. | | `/usage` | An object with `success: true` and a `data` object. | | `/transactions` | An object with `success: true`, a `data` array, and `pagination`. | Errors return an appropriate HTTP status and an `error` object: ```json { "success": false, "error": { "code": "unauthorized", "message": "You are not logged in." } } ``` Use `error.code` to handle errors in your application. Response messages provide a human-readable explanation. Responses use `Content-Type: application/json; charset=utf-8` and `Cache-Control: no-store`. ## Get balance ```http GET /wallet/balance ``` No query parameters are required. ### Example response ```json { "success": true, "data": [ { "account_number": "123456789012", "currency": "MVR", "ledger_balance": 1500.5, "available_balance": 1500.5, "hold_balance": 0 } ] } ``` | Field | Description | | --- | --- | | `account_number` | Your wallet account number. | | `currency` | Currency code. Currently `MVR`. | | `ledger_balance` | Reported wallet balance, rounded to two decimal places. | | `available_balance` | Currently returns the same amount as `ledger_balance`. | | `hold_balance` | Currently returns `0`; separate held-funds reporting is not available. | Amounts are JSON numbers. Trailing decimal zeroes are not guaranteed: `1500.00` may appear as `1500`. Negative balances may be returned. ## Get usage and limits ```http GET /wallet/usage ``` Returns your verification tier, wallet limits, usage, remaining allowances, and reset times. No query parameters are required. ### Response fields The response contains `success: true` and a `data` object with these fields: | Field | Description | | --- | --- | | `tier` | Your account's verification tier. | | `limits.per_transaction` | Per-transaction limit. | | `limits.daily` | Daily limit. | | `limits.weekly` | Weekly limit. | | `limits.monthly` | Monthly limit. | | `usage` | Usage information for your wallet. | | `remaining` | Remaining allowances for your wallet. | | `reset_at.daily` | Next daily reset time. | | `reset_at.weekly` | Next weekly reset time. | | `reset_at.monthly` | Next monthly reset time. | Limits depend on your account. Read the returned values rather than assuming fixed limits. Reset timestamps use ISO 8601 format in Maldives time (`+05:00`). Daily resets are at the next midnight, weekly resets are at the next Sunday midnight, and monthly resets are at midnight on the first day of the next month. Example `reset_at` object: ```json { "daily": "2026-09-11T00:00:00+05:00", "weekly": "2026-09-13T00:00:00+05:00", "monthly": "2026-10-01T00:00:00+05:00" } ``` ## List transactions ```http GET /wallet/transactions?limit=10 ``` Returns successful and failed transactions, with the most recently recorded transactions first. ### Query parameters | Parameter | Required | Default | Description | | --- | --- | --- | --- | | `limit` | No | `10` | Number of records per page, from 1 to 100. Use whole numbers without leading zeroes. | | `before` | No | None | The `next_cursor` from the previous response. Omit it for the first page. | ### Example response All transaction references, dates, merchant names, bill details, and amounts below are fictional. ```json { "success": true, "data": [ { "tid": "FP20260110120000DEMO", "time": "2026-01-10T12:00:00+05:00", "type": "payment", "name": "Example Store", "details": "Example order DEMO-001", "amount": -25, "status": "success" }, { "tid": "FP20260109120000DEMO", "time": "2026-01-09T12:00:00+05:00", "type": "payment", "name": "Mobile bill payment", "details": "Example bill DEMO-002", "amount": -249.5, "status": "success" }, { "tid": "FP20260108120000DEMO", "time": "2026-01-08T12:00:00+05:00", "type": "payment", "name": "Internet bill payment", "details": "Example bill DEMO-003", "amount": -100, "status": "success" }, { "tid": "FP20260107120000DEMO", "time": "2026-01-07T12:00:00+05:00", "type": "payment", "name": "Mobile bill payment", "details": "Example bill DEMO-004", "amount": -50, "status": "success" }, { "tid": "FP20260106120000DEMO", "time": "2026-01-06T12:00:00+05:00", "type": "payment", "name": "Utility bill payment", "details": "Example bill DEMO-005", "amount": -75.25, "status": "success" }, { "tid": "FP20260105120000DEMO", "time": "2026-01-05T12:00:00+05:00", "type": "payment", "name": "Internet bill payment", "details": "Example bill DEMO-006", "amount": -150, "status": "success" }, { "tid": "FP20260104120000DEMO", "time": "2026-01-04T12:00:00+05:00", "type": "payment", "name": "Water bill payment", "details": "Example bill DEMO-007", "amount": -200, "status": "success" }, { "tid": "FP20260103120000DEMO", "time": "2026-01-03T12:00:00+05:00", "type": "payment", "name": "Electricity bill payment", "details": "Example bill DEMO-008", "amount": -125, "status": "success" }, { "tid": "FP20260102120000DEMO", "time": "2026-01-02T12:00:00+05:00", "type": "payment", "name": "Council bill payment", "details": "Example bill DEMO-009", "amount": -60, "status": "success" }, { "tid": "FP20260101120000DEMO", "time": "2026-01-01T12:00:00+05:00", "type": "payment", "name": "Mobile bill payment", "details": "Example bill DEMO-010", "amount": -300, "status": "success" } ], "pagination": { "limit": 10, "has_more": true, "next_cursor": "FP20260101120000DEMO" } } ``` | Field | Description | | --- | --- | | `tid` | Transaction reference. | | `time` | Transaction timestamp in ISO 8601 format, including its timezone offset. | | `type` | Transaction type. | | `name` | Transaction name. | | `details` | Transaction description. | | `amount` | Signed transaction amount as a JSON number. | | `status` | `success` or `failed`. | The top-level `success` indicates whether the API request succeeded. It does not indicate the outcome of individual transactions. Check each transaction's `status`; the presence of an amount does not mean a failed transaction moved funds. Amounts are in **MVR** and may include fractional values. The number of displayed decimal places is not fixed. Parse timestamps using the offset included in each value. ### Pagination | Field | Description | | --- | --- | | `pagination.limit` | Requested page size, or the default of 10. | | `pagination.has_more` | Whether more records are available. | | `pagination.next_cursor` | Reference to use for the next page; `null` when there are no more records. | To continue, pass `next_cursor` as `before`: ```http GET /wallet/transactions?limit=10&before=FP20260101120000DEMO ``` The transaction identified by the cursor is excluded from the next page. New transactions do not shift records between subsequent pages. To refresh the latest transactions, start again without `before`. Stop when `has_more` is false. The last page may contain fewer records than `limit`, or no records: ```json { "success": true, "data": [], "pagination": { "limit": 10, "has_more": false, "next_cursor": null } } ``` Always use the cursor returned by the API. An invalid or unavailable cursor returns HTTP 400 with `invalid_pagination`. If a previously returned cursor is no longer accepted, restart without `before`. Page numbers, offsets, and total record counts are not supported. ## Rate limits Your account can make **60 requests per 60-second window**, shared across all wallet endpoints. Authenticated requests that return validation, method, or endpoint errors also count toward the limit. When you exceed the limit, the API returns HTTP 429: ```http HTTP/1.1 429 Too Many Requests Retry-After: 20 ``` ```json { "success": false, "error": { "code": "rate_limited", "message": "Too many requests." } } ``` When present, `Retry-After` tells you how many seconds to wait before retrying. Temporary access restrictions can also return 429 without this header. Avoid immediate repeated retries; reduce request frequency and retry with increasing delays. ## Errors | HTTP status | Error code | Description | Recommended action | | --- | --- | --- | --- | | 400 | `invalid_pagination` | Invalid page size or cursor. | Use a limit from 1 to 100 and a cursor returned by the API. | | 401 | `unauthorized` | Authentication failed or expired. | Check your Wallet API key from FahiPay Developers. | | 404 | `not_found` | Endpoint not found. | Check the request URL. | | 405 | `method_not_allowed` | Unsupported HTTP method. | Use GET. The response includes `Allow: GET`. | | 429 | `rate_limited` | Too many requests or a temporary access restriction. | Wait before retrying and follow `Retry-After` when present. | | 500 | `internal_error` | The request could not be completed. | Retry with a delay; contact support if the error persists. | ### Example server error ```json { "success": false, "error": { "code": "internal_error", "message": "An unexpected error occurred." } } ``` ## Request a feature Missing an API feature? Email [info@fahipay.mv](mailto:info@fahipay.mv?subject=FahiPay%20Wallet%20API%20feature%20request) with a short description of what you're building, the feature you need, and how it would help your integration.