> ## Documentation Index
> Fetch the complete documentation index at: https://ifemafia.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Axis Quickstart: From Signup to Live Payment in 5 Steps

> Create a business account, provision a wallet, fund it, issue an API key, and fire your first payment — end-to-end in under 10 minutes.

This guide walks you through the complete Axis onboarding flow from zero to a live payment. You will sign up for a developer account, register your business, create a scoped wallet for your agent, fund the wallet via a virtual bank account, and fire your first payment intent — all in under 10 minutes. Every step below maps to a real API call your frontend or setup script will make.

<Steps>
  <Step title="Sign up">
    Create an Axis account by posting your credentials and account type to the auth endpoint. Use `accountType: "business"` if you are setting up payment infrastructure for a product, or `"developer"` for personal/sandbox use.

    When you sign up with `accountType: "business"`, Axis automatically provisions a business record and returns a `businessId` in the response — no separate business registration call is needed at this step.

    **Request**

    ```bash theme={null}
    curl -X POST https://your-axis-instance.com/v1/auth/signup \
      -H "Content-Type: application/json" \
      -d '{
        "email": "ada@paystackdemo.io",
        "password": "Sup3rS3cret!",
        "accountType": "business"
      }'
    ```

    ```json theme={null}
    {
      "email": "ada@paystackdemo.io",
      "password": "Sup3rS3cret!",
      "accountType": "business"
    }
    ```

    **Response**

    ```json theme={null}
    {
      "status": "success",
      "data": {
        "user": {
          "id": "a3f7c291-8b4e-4d2a-9f1c-0e5b7d3a6c82",
          "email": "ada@paystackdemo.io",
          "accountType": "business",
          "businessId": "b9e2d104-3c7f-4a1b-8e5d-2f0c9a4b6e31",
          "createdAt": "2025-01-15T09:00:00.000Z"
        },
        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJhM2Y3YzI5MS04YjRlLTRkMmEtOWYxYy0wZTViN2QzYTZjODIiLCJhY2NvdW50VHlwZSI6ImJ1c2luZXNzIiwiYnVzaW5lc3NJZCI6ImI5ZTJkMTA0LTNjN2YtNGExYi04ZTVkLTJmMGM5YTRiNmUzMSIsImlhdCI6MTcwNTMxMjAwMH0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
      }
    }
    ```

    Store the `token` — you will send it as `Authorization: Bearer <token>` on every subsequent developer-authenticated request. Tokens expire after **7 days**.
  </Step>

  <Step title="Register your business">
    Before you can create wallets, Axis requires basic business details for KYB (Know Your Business) purposes. Submit your business profile to the onboarding endpoint.

    **Request**

    ```bash theme={null}
    curl -X POST https://your-axis-instance.com/v1/onboarding \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
      -d '{
        "businessName": "Paystack Demo Ltd",
        "contactEmail": "ada@paystackdemo.io",
        "contactPhone": "+2348012345678"
      }'
    ```

    ```json theme={null}
    {
      "businessName": "Paystack Demo Ltd",
      "contactEmail": "ada@paystackdemo.io",
      "contactPhone": "+2348012345678"
    }
    ```

    **Response**

    ```json theme={null}
    {
      "status": "success",
      "data": {
        "businessId": "b9e2d104-3c7f-4a1b-8e5d-2f0c9a4b6e31",
        "businessName": "Paystack Demo Ltd",
        "contactEmail": "ada@paystackdemo.io",
        "contactPhone": "+2348012345678",
        "status": "active",
        "createdAt": "2025-01-15T09:01:30.000Z"
      }
    }
    ```
  </Step>

  <Step title="Create a wallet">
    Provision a wallet for your agent. You define the spending rules here — Axis enforces them on every payment intent the agent submits.

    | Field               | Purpose                                                               |
    | ------------------- | --------------------------------------------------------------------- |
    | `spendLimitPerTx`   | Maximum single transaction amount, in kobo                            |
    | `spendLimitPeriod`  | Maximum total spend within a rolling window, in kobo                  |
    | `periodWindowDays`  | Length of the rolling period window in days                           |
    | `expiry`            | ISO 8601 date-time after which the wallet rejects all payment intents |
    | `useAllowlist`      | When `true`, only merchants in `merchantAllowlist` are accepted       |
    | `merchantAllowlist` | Array of merchant name strings the agent is permitted to pay          |

    **Request**

    ```bash theme={null}
    curl -X POST https://your-axis-instance.com/api/wallets \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
      -d '{
        "name": "procurement-agent-wallet",
        "userId": "a3f7c291-8b4e-4d2a-9f1c-0e5b7d3a6c82",
        "spendLimitPerTx": 500000,
        "spendLimitPeriod": 5000000,
        "periodWindowDays": 30,
        "expiry": "2026-01-15T00:00:00.000Z",
        "useAllowlist": true,
        "merchantAllowlist": ["Dangote Cement", "MTN Nigeria", "Julius Berger"]
      }'
    ```

    ```json theme={null}
    {
      "name": "procurement-agent-wallet",
      "userId": "a3f7c291-8b4e-4d2a-9f1c-0e5b7d3a6c82",
      "spendLimitPerTx": 500000,
      "spendLimitPeriod": 5000000,
      "periodWindowDays": 30,
      "expiry": "2026-01-15T00:00:00.000Z",
      "useAllowlist": true,
      "merchantAllowlist": ["Dangote Cement", "MTN Nigeria", "Julius Berger"]
    }
    ```

    **Response**

    ```json theme={null}
    {
      "status": "success",
      "data": {
        "wallet": {
          "id": "wal_01hq9xkv9g7o0r4n0e6z",
          "name": "procurement-agent-wallet",
          "userId": "a3f7c291-8b4e-4d2a-9f1c-0e5b7d3a6c82",
          "balance": 0,
          "spendLimitPerTx": 500000,
          "spendLimitPeriod": 5000000,
          "periodWindowDays": 30,
          "expiry": "2026-01-15T00:00:00.000Z",
          "useAllowlist": true,
          "merchantAllowlist": ["Dangote Cement", "MTN Nigeria", "Julius Berger"],
          "status": "active",
          "createdAt": "2025-01-15T09:03:00.000Z"
        },
        "apiKey": {
          "id": "key_01hq9xkvah8p1s5o1f7a",
          "prefix": "ax_live_3f9a1c",
          "fullKey": "ax_live_3f9a1c0b2e7d4a8f5c1e3b9d2a7f0c4e8b1d5a3f7c2e9b4d0a6f8c1e3b5d2a7f4",
          "walletId": "wal_01hq9xkv9g7o0r4n0e6z",
          "createdAt": "2025-01-15T09:03:00.000Z"
        },
        "virtualAccount": {
          "id": "vac_01hq9xkvbh9q2t6p2g8b",
          "accountNumber": "0123456789",
          "accountName": "Axis / Paystack Demo Ltd",
          "bankName": "Guaranty Trust Bank",
          "bankCode": "058",
          "currency": "NGN"
        }
      }
    }
    ```

    <Warning>
      The `apiKey.fullKey` value is returned **exactly once** — at wallet creation. Axis stores only a hashed version and cannot recover the plain-text key later. Copy `fullKey` into a secure secrets manager (e.g. AWS Secrets Manager, HashiCorp Vault, or your CI/CD environment variables) immediately. If it is lost, you must create a new wallet to obtain a fresh key.
    </Warning>
  </Step>

  <Step title="Fund the wallet">
    Your wallet starts with a balance of `0`. To give the agent real spend authority, transfer NGN to the **virtual account number** returned in the previous step.

    From the response above:

    ```
    Account Number : 0123456789
    Account Name   : Axis / Paystack Demo Ltd
    Bank           : Guaranty Trust Bank (058)
    Currency       : NGN
    ```

    You can fund the wallet using:

    * **Internet banking or mobile app** — a standard NGN transfer to the account number above from any Nigerian bank.
    * **Programmatic transfer** — use your existing payment processor (e.g. Paystack, Flutterwave) to initiate a transfer to the virtual account.

    Once the inbound payment settles, Axis receives a webhook from the issuing bank and automatically credits the wallet balance. The credit is reflected in the wallet's `balance` field (in kobo) and recorded as a `LedgerEntry`.

    ```json theme={null}
    {
      "event": "wallet.funded",
      "data": {
        "walletId": "wal_01hq9xkv9g7o0r4n0e6z",
        "amountCredited": 2000000,
        "newBalance": 2000000,
        "currency": "NGN",
        "fundedAt": "2025-01-15T09:15:42.000Z"
      }
    }
    ```

    There is no polling required — subscribe to the `wallet.funded` webhook event in your Axis dashboard to be notified when funds arrive.
  </Step>

  <Step title="Fire a payment intent">
    Your agent is now ready to spend. It calls `POST /api/payment-intent`, authenticating with the `fullKey` via the `x-api-key` header — **not** the developer JWT. Axis validates the request against the wallet's rules before executing the bank transfer.

    **Request**

    ```bash theme={null}
    curl -X POST https://your-axis-instance.com/api/payment-intent \
      -H "Content-Type: application/json" \
      -H "x-api-key: ax_live_3f9a1c0b2e7d4a8f5c1e3b9d2a7f0c4e8b1d5a3f7c2e9b4d0a6f8c1e3b5d2a7f4" \
      -d '{
        "amount": 250000,
        "merchantName": "Dangote Cement",
        "recipientAccountNo": "0098765432",
        "recipientBankCode": "058",
        "reason": "Q1 2025 cement procurement — invoice #DC-00412"
      }'
    ```

    ```json theme={null}
    {
      "amount": 250000,
      "merchantName": "Dangote Cement",
      "recipientAccountNo": "0098765432",
      "recipientBankCode": "058",
      "reason": "Q1 2025 cement procurement — invoice #DC-00412"
    }
    ```

    | Field                | Type    | Required | Description                                                                           |
    | -------------------- | ------- | -------- | ------------------------------------------------------------------------------------- |
    | `amount`             | integer | ✅        | Amount in kobo (e.g. `250000` = ₦2,500.00)                                            |
    | `merchantName`       | string  | ✅        | Must match an entry in `merchantAllowlist` when `useAllowlist` is `true`              |
    | `recipientAccountNo` | string  | ✅        | 10-digit NUBAN account number of the recipient                                        |
    | `recipientBankCode`  | string  | ✅        | 3-digit NIP bank code (e.g. `058` for GTBank, `011` for First Bank, `057` for Zenith) |
    | `reason`             | string  | ❌        | Optional payment description attached to the transaction record                       |

    **Success response**

    ```json theme={null}
    {
      "status": "success",
      "data": {
        "transactionId": "txn_01hq9xkvci0r3u7q3h9c",
        "status": "successful",
        "amount": 250000,
        "currency": "NGN",
        "merchantName": "Dangote Cement",
        "recipientAccountNo": "0098765432",
        "recipientBankCode": "058",
        "recipientAccountName": "Dangote Cement PLC",
        "reason": "Q1 2025 cement procurement — invoice #DC-00412",
        "walletBalanceAfter": 1750000,
        "executedAt": "2025-01-15T10:02:17.000Z"
      }
    }
    ```

    Axis checks all of the following before executing the transfer. A failed check returns a `400` or `403` with a descriptive error:

    * Wallet is **active** and not expired
    * `amount` ≤ `spendLimitPerTx`
    * Total spend in the current period window + `amount` ≤ `spendLimitPeriod`
    * Wallet `balance` ≥ `amount`
    * `merchantName` is in `merchantAllowlist` (when `useAllowlist: true`)
  </Step>
</Steps>

<Tip>
  The example above uses the **API key** auth mode (`x-api-key` header), which is what agents use at runtime. The developer **JWT** mode (`Authorization: Bearer`) is used for provisioning operations like creating wallets, viewing audit logs, and managing keys. See the [Auth Overview](/guides/auth-overview) for a full breakdown of both modes, token lifetimes, and how to rotate keys without downtime.
</Tip>
