> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.solvimon.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.solvimon.com/_mcp/server.

# Bill your first B2C customer

By the end of this tutorial a customer will have an active subscription and a finalized, paid first invoice. Solvimon will automatically generate and charge subsequent invoices each billing period.

The full flow looks like this:

1. **Tokenize the card** in Adyen to get a stored payment method ID
2. **Create the customer** in Solvimon, linked to that Adyen shopper
3. **Initialize the subscription**, recording the first payment so the first invoice is immediately finalized and paid
4. **Set up webhooks** to handle future invoices and payment events

**What you'll need:**

* A Solvimon sandbox API key — see [Send your first API request](/platform-guides/getting-started/onboarding-and-tutorials/api-quickstart)
* A pricing plan already created in your sandbox — [set one up in Desk](https://test.desk.solvimon.com/) first
* A billing entity configured under **Settings → Billing entities**
* An Adyen test account with a merchant account configured for recurring payments

---

## Step 1: Tokenize the card in Adyen

Before creating the subscription, tokenize the customer's card details in Adyen. This stores the card and gives you a `recurring_detail_reference` you'll pass to Solvimon later.

### 1a. Submit the card payment to create the token

```bash
curl -X POST https://checkout-test.adyen.com/v71/payments \
  -H "X-API-KEY: <adyenApiKey>" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": {
      "currency": "EUR",
      "value": 0
    },
    "paymentMethod": {
      "type": "scheme",
      "encryptedCardNumber": "test_4111111111111111",
      "encryptedExpiryMonth": "test_03",
      "encryptedExpiryYear": "test_2030",
      "encryptedSecurityCode": "test_737"
    },
    "merchantAccount": "Adyen_B2C_Subscriptions",
    "recurringProcessingModel": "Subscription",
    "reference": "card_cust_1",
    "shopperReference": "cust_1",
    "storePaymentMethod": true
  }'
```

* `shopperReference`: Your identifier for this customer in Adyen. You'll use this same value as the Solvimon `custom_fields` reference in Step 2.
* `storePaymentMethod: true`: Tells Adyen to store the card for future recurring charges.
* `recurringProcessingModel: "Subscription"`: Required for subscription-type recurring payments.

### 1b. Retrieve the stored payment method ID

```bash
curl -X POST https://checkout-test.adyen.com/v71/paymentMethods \
  -H "X-API-KEY: <adyenApiKey>" \
  -H "Content-Type: application/json" \
  -d '{
    "merchantAccount": "Adyen_B2C_Subscriptions",
    "shopperReference": "cust_1"
  }'
```

Response:

```json
{
  "storedPaymentMethods": [
    {
      "id": "WC43X3RL9ZD3LTT5",
      "lastFour": "1111",
      "name": "VISA"
    }
  ]
}
```

Note the `id` — this is the `recurring_detail_reference` you'll use in Step 3.

---

## Step 2: Create the customer

Create the customer in Solvimon and link them to the Adyen shopper via `custom_fields`. Solvimon uses this to know which PSP payment methods belong to this customer.

```bash
curl -X POST https://test.api.solvimon.com/v1/customers \
  -H "X-API-KEY: <apiKey>" \
  -H "Content-Type: application/json" \
  -d '{
    "reference": "cust_1",
    "type": "INDIVIDUAL",
    "email": "john.doe@gmail.com",
    "roles": ["DEFAULT"],
    "individual": {
      "name": {
        "first_name": "John",
        "last_name": "Doe"
      },
      "residential_address": {
        "country": "NL"
      }
    },
    "custom_fields": [
      {
        "reference": "PAYMENT_GATEWAY:ADYEN:SHOPPER_REFERENCE",
        "value": "cust_1"
      }
    ]
  }'
```

**Parameter notes:**

* `reference`: Your identifier for this customer. Used to reference them in subsequent API calls.
* `custom_fields.reference`: The key identifying which PSP this links to.
  * `PAYMENT_GATEWAY:ADYEN:SHOPPER_REFERENCE` — for Adyen
  * `PAYMENT_GATEWAY:STRIPE:CUSTOMER_ID` — for Stripe (use the Stripe `cus_...` ID as the value)
* `custom_fields.value`: The customer's identifier in the PSP system — must match the `shopperReference` used in Step 1.

> **Note**
>
> 📘 You can only use payment methods that were created under the `shopperReference` set in `custom_fields`. Solvimon will reject payment attempts using methods belonging to a different shopper.

> **Note**
>
> 📘 See the [Customers API reference](/api-docs/configuration-api/customers/get-a-list-of-all-customers) for all available fields.

---

## Step 3: Initialize the subscription

`/init` creates the subscription and its first schedule in a single call. Providing `first_payment` tells Solvimon that the customer already paid (e.g. as part of checkout), which automatically finalizes the first invoice as paid. The `payment_method` stores the card so Solvimon can auto-charge future invoices.

```bash
curl -X POST https://test.api.solvimon.com/v1/pricing-plan-subscriptions/init \
  -H "X-API-KEY: <apiKey>" \
  -H "Content-Type: application/json" \
  -d '{
    "pricing_plan_subscription": {
      "reference": "cust_1_monthly_eur_20240915",
      "customer_reference": "cust_1",
      "billing_entity_reference": "entity_nl",
      "billing_time": "EXACT",
      "billing_currency": "EUR"
    },
    "pricing_plan_schedules": [
      {
        "pricing_plan_version_selector": {
          "pricing_plan_reference": "monthly_eur"
        },
        "start_at": "2024-09-15T00:00:00Z",
        "end_at": "2025-09-15T00:00:00Z"
      }
    ],
    "first_payment": {
      "payment_acceptor_reference": "adyen_b2c_subscriptions",
      "external_reference": "N9KKLBTLMJS8F6V5",
      "amount": {
        "quantity": "9.99",
        "currency": "EUR"
      },
      "result": "AUTHORIZED"
    },
    "payment_method": {
      "type": "CARD",
      "card": {
        "brand": "VISA",
        "last_four_digits": "1111"
      },
      "integration_reference": "adyen",
      "integration_details": {
        "payment_gateway_variant": "ADYEN",
        "adyen": {
          "recurring_detail_reference": "WC43X3RL9ZD3LTT5"
        }
      }
    }
  }'
```

**Parameter notes:**

`pricing_plan_subscription`:

* `reference`: Your identifier for this subscription.
* `customer_reference`: The reference of the customer created in Step 2.
* `billing_entity_reference`: The billing entity this subscription is invoiced from.
* `billing_time: "EXACT"`: Billing occurs on the same day of the month as `start_at` — e.g. if the subscription starts on the 15th, every subsequent invoice is on the 15th. Recommended for B2C.
* `billing_currency`: The currency used for all invoices on this subscription.

`pricing_plan_schedules`:

* `pricing_plan_version_selector.pricing_plan_reference`: The pricing plan to use. By default the latest `ACTIVE` version is used.
* `start_at`: Set to the date the customer paid and activated the subscription.
* `end_at`: Optional. When set, the subscription ends and no further invoices are generated after this date.

`first_payment`:

* Use this when the first payment was collected outside of Solvimon (e.g. during your checkout flow). Providing it causes Solvimon to automatically finalize the first invoice as paid.
* `external_reference`: The transaction reference from your PSP for this payment.
* `result: "AUTHORIZED"`: Confirms the payment succeeded.

`payment_method`:

* `integration_reference`: The reference to the [payment provider integration](/integrations/paymentserviceproviders) configured in Solvimon.
* `integration_details.adyen.recurring_detail_reference`: The stored payment method ID from Step 1b. Solvimon uses this to charge the customer's card for future invoices.

> **Tip**
>
> **Default billing terms:** Instead of specifying `billing_time`, `billing_currency`, and `billing_period` on every subscription, you can configure defaults under [Settings → Default platform settings](/platform-guides/platform-configuration/default-platform-settings). They apply automatically when those fields are omitted.

> **Tip**
>
> **Skipping payment collection?** Omit `first_payment` and `payment_method`. The subscription and schedule are still created and invoices will be generated — just not auto-charged.

---

## Alternative: Create customer and subscription in one call

If you want to create or update the customer at the same time as initializing the subscription, pass a `customer` object directly in the init request instead of a `customer_reference`:

```bash
curl -X POST https://test.api.solvimon.com/v1/pricing-plan-subscriptions/init \
  -H "X-API-KEY: <apiKey>" \
  -H "Content-Type: application/json" \
  -d '{
    "customer": {
      "reference": "cust_1",
      "type": "INDIVIDUAL",
      "email": "john.doe@gmail.com",
      "roles": ["DEFAULT"],
      "individual": {
        "name": {
          "first_name": "John",
          "last_name": "Doe"
        },
        "residential_address": {
          "country": "NL"
        }
      },
      "custom_fields": [
        {
          "reference": "PAYMENT_GATEWAY:ADYEN:SHOPPER_REFERENCE",
          "value": "cust_1"
        }
      ]
    },
    "pricing_plan_subscription": {
      "reference": "cust_1_monthly_eur_20240915",
      "billing_entity_reference": "entity_nl",
      "billing_time": "EXACT",
      "billing_currency": "EUR"
    },
    "pricing_plan_schedules": [
      {
        "pricing_plan_version_selector": {
          "pricing_plan_reference": "monthly_eur"
        },
        "start_at": "2024-09-15T00:00:00Z",
        "end_at": "2025-09-15T00:00:00Z"
      }
    ],
    "first_payment": {
      "payment_acceptor_reference": "adyen_b2c_subscriptions",
      "external_reference": "N9KKLBTLMJS8F6V5",
      "amount": {
        "quantity": "9.99",
        "currency": "EUR"
      },
      "result": "AUTHORIZED"
    },
    "payment_method": {
      "type": "CARD",
      "card": {
        "brand": "VISA",
        "last_four_digits": "1111"
      },
      "integration_reference": "adyen",
      "integration_details": {
        "payment_gateway_variant": "ADYEN",
        "adyen": {
          "recurring_detail_reference": "WC43X3RL9ZD3LTT5"
        }
      }
    }
  }'
```

Note that `customer_reference` is omitted from `pricing_plan_subscription` — the customer is identified via the `customer.reference` field instead. If a customer with that reference already exists, it will be updated.

---

## Step 4: Handle invoice and payment webhooks

Solvimon calls your endpoint when invoices and payments change state. Configure a webhook under **Settings → Webhooks**.

For a B2C subscription, handle these two events:

| Event               | When it fires                 | What to do                                                       |
| ------------------- | ----------------------------- | ---------------------------------------------------------------- |
| `invoice.finalized` | Invoice status moves to FINAL | Send a receipt, confirm the billing period in your system        |
| `payment.created`   | A payment attempt is made     | Check `result` — provision access on success, suspend on failure |

You can use a single webhook endpoint for both events.

> **Note**
>
> See the [Webhooks guide](/platform-guides/for-developers/webhooks) for payload shapes and verification.

---

## Step 5: Manage the subscription over time

**Cancel at period end** — set `end_at` on the current schedule:

```bash
curl -X PATCH https://test.api.solvimon.com/v1/pricing-plan-schedules/<schedule_id> \
  -H "X-API-KEY: <apiKey>" \
  -H "Content-Type: application/json" \
  -d '{
    "end_at": "2025-09-15T00:00:00Z"
  }'
```

**Upgrade to a new plan** — add a second schedule starting at the changeover date:

```bash
curl -X POST https://test.api.solvimon.com/v1/pricing-plan-schedules \
  -H "X-API-KEY: <apiKey>" \
  -H "Content-Type: application/json" \
  -d '{
    "pricing_plan_subscription_reference": "cust_1_monthly_eur_20240915",
    "pricing_plan_version_selector": {
      "pricing_plan_reference": "new_plan_reference"
    },
    "start_at": "2025-09-15T00:00:00Z"
  }'
```

**Update the payment method** — patch the subscription with the new `payment_method_id` when a customer updates their card. The updated method will be used for all subsequent invoices.