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

# Fund and subscribe

> Mint a deposit account, collect payment over bank transfer or stablecoin, and let settlement activate the subscription or wallet top-up.

Funding on Convexity Infra is **push-based**: instead of charging a stored card,
you mint a one-time **deposit account**, your payer sends the exact amount to it,
and settlement does the rest: recording the payment, activating the subscription
or crediting the wallet balance, and granting product access. This guide walks
through the whole flow.

## 1. Mint a deposit account

Call [Create deposit account](/api-reference/payments/create-deposit-account) with
what the funding is *for*: the `purpose`:

<Tabs>
  <Tab title="Subscription">
    ```bash theme={null}
    curl -X POST https://api.convexity.tools/v1/payments/subscribe \
      -H "Authorization: Bearer <access_token>" \
      -H "Content-Type: application/json" \
      -d '{
        "purpose": "SUBSCRIPTION",
        "planId": 42,
        "billingCycle": "MONTHLY"
      }'
    ```

    `billingCycle` is **required**; it sizes the paid period. There is no
    subscription id to send: renewals and upgrades are resolved server-side from
    `planId` (see [Renewals and upgrades](#4-renewals-and-upgrades)). A free (\$0)
    plan is activated immediately and returns an empty `data` array.
  </Tab>

  <Tab title="Wallet top-up">
    ```bash theme={null}
    curl -X POST https://api.convexity.tools/v1/payments/subscribe \
      -H "Authorization: Bearer <access_token>" \
      -H "Content-Type: application/json" \
      -d '{
        "purpose": "WALLET_TOPUP",
        "amount": 15
      }'
    ```

    `amount` is in **USD major units** (`15` = \$15). The credited balance is the
    USD value, whichever rail the payer uses.
  </Tab>
</Tabs>

By default you get one account per active **settlement rail**: you may receive a
bank account *and* a stablecoin wallet. Pass `?providerType=FIAT` or
`?providerType=STABLECOIN` to pin one rail.

## 2. Show the payer where to send money

`data` is an array of account objects, discriminated on `kind`. Branch on it and
render only that rail's fields:

<Tabs>
  <Tab title="FIAT: bank transfer">
    ```json theme={null}
    {
      "kind": "FIAT",
      "accountNumber": "0123456789",
      "accountName": "Acme Ltd / Konga",
      "bankName": "Providus Bank",
      "bankCode": "001",
      "amountExpected": 22556.39,
      "fxRate": 0.000665,
      "expiryAt": "2026-07-10T12:00:00.000Z"
    }
    ```

    Render: *Transfer ₦22,556.39 to 0123456789 (Providus Bank) before the expiry.*
  </Tab>

  <Tab title="USDC: on-chain">
    ```json theme={null}
    {
      "kind": "STABLECOIN",
      "walletAddress": "0x9aE4...93aA",
      "token": "USDC",
      "pegCurrency": "USD",
      "blockchainNetwork": "Base",
      "chainId": 8453,
      "amountExpected": 15,
      "fxRate": 0.000665,
      "expiryAt": "2026-07-10T11:30:00.000Z"
    }
    ```

    Render: *Send 15 USDC on Base to 0x9aE4…93aA before the expiry.*
  </Tab>

  <Tab title="cNGN: on-chain, naira value">
    ```json theme={null}
    {
      "kind": "STABLECOIN",
      "walletAddress": "0xEf69...a01D",
      "token": "cNGN",
      "pegCurrency": "NGN",
      "blockchainNetwork": "Base",
      "chainId": 8453,
      "amountExpected": 22556.39,
      "amountExpectedNgn": 22556.39,
      "fxRate": 0.000665,
      "expiryAt": "2026-07-10T11:30:00.000Z"
    }
    ```

    cNGN is pegged **1:1 to the naira**, so the token amount *is* the naira
    amount. Render the naira value: *Send ₦22,556.39 (22,556.39 cNGN) on Base to
    0xEf69…a01D before the expiry.*
  </Tab>
</Tabs>

<Warning>
  Deposit accounts are **one-time and short-lived**: roughly 1 hour for bank
  accounts and 30 minutes for stablecoin wallets (`expiryAt` is authoritative).
  The payer must send the **exact** `amountExpected`. After expiry, mint a new
  account; never reuse or cache an old one.
</Warning>

### The FX rate is locked

Every amount in the response is priced at one NGN/USD rate, returned as `fxRate`
(USD per 1 NGN). That rate is **locked until `expiryAt`**: when the deposit
lands, settlement converts at the quoted rate, not the live market rate. A $10
plan paid in cNGN settles as exactly $10 even if the market moved while the payer
was completing the transfer.

## 3. Settlement is automatic

There is nothing to poll aggressively or confirm manually:

<Steps>
  <Step title="The deposit is detected">
    Bank transfers arrive via the payment provider's webhook; stablecoin deposits
    are picked up by the on-chain indexer and re-verified on-chain before
    anything is credited.
  </Step>

  <Step title="The payment is recorded">
    An idempotent payment record is written, visible in
    [List project payments](/api-reference/payments/list-project-payments) with
    both the charged amount and its USD value.
  </Step>

  <Step title="The purpose is applied">
    A subscription payment activates (or renews) the subscription and grants the
    plan's product access. A wallet top-up credits your USD balance.
  </Step>
</Steps>

To confirm from your side, check
[List my subscriptions](/api-reference/subscriptions/list-my-subscriptions) for an
`ACTIVE` subscription, or [List project payments](/api-reference/payments/list-project-payments)
for a `SUCCESS` payment with your account's `reference`.

<Note>
  A payment that arrives with the wrong amount for a subscription is **not
  lost**: it is credited to your wallet balance instead, and the payment record's
  `description` explains why.
</Note>

## 4. Renewals and upgrades

Both reuse the same endpoint: the server works out what the request means:

* **Renewal**: send the same `planId` again (typically after the subscription
  expires or enters its grace window). The existing subscription is extended;
  no id needs to be sent.
* **Upgrade**: request a *different* plan of the **same product** while you hold
  an active paid subscription. The charge is **prorated**: the unused value of
  the current subscription (`current plan price × fraction of the period
  remaining`) is credited against the new plan's price, and every amount in the
  response already reflects the discount. On settlement the new subscription
  starts a full fresh period, the old one is cancelled, and its product access
  is replaced.

For example: 10 days into a $10/month plan, upgrading to $25/month credits
$6.67 of unused time and charges $18.33.

<Warning>
  **Downgrades are not supported.** If the remaining credit would cover the whole
  new price, the request is rejected with an explanatory error.
</Warning>

## Reference

* [Create deposit account](/api-reference/payments/create-deposit-account): full
  request/response schema with examples for every rail.
* [List project payments](/api-reference/payments/list-project-payments): every
  payment recorded for your project, with amounts in both currencies.
* [List my subscriptions](/api-reference/subscriptions/list-my-subscriptions):
  your project's subscriptions and their statuses.
