Skip to content

Latest commit

 

History

History
290 lines (247 loc) · 11 KB

File metadata and controls

290 lines (247 loc) · 11 KB
title Axis Quickstart: From Signup to Live Payment in 5 Steps
sidebarTitle Quickstart
description 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.

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
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
{
  "email": "ada@paystackdemo.io",
  "password": "Sup3rS3cret!",
  "accountType": "business"
}
```

**Response**

```json
{
  "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**.
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
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
{
  "businessName": "Paystack Demo Ltd",
  "contactEmail": "ada@paystackdemo.io",
  "contactPhone": "+2348012345678"
}
```

**Response**

```json
{
  "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"
  }
}
```
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
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
{
  "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
{
  "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>
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
{
  "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.
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
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
{
  "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
{
  "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`)
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.