# Dime Recurring Payments

Enable subscriptions by creating a **standard Order** and adding two fields to the JWT payload:

- `is_subscription: true`
- `subscription_instructions: { recurring_frequency, billing_cycles }`


This instructs Dime to provision and schedule **automatic recurring charges** after the initial checkout.

**Version:** 1.0.0

## When to use

Use this flow when you want a customer to:

- Complete a **first checkout** (hosted page) and
- Automatically be billed again on a **weekly / monthly / yearly** cadence for a defined number of cycles.


> Tip: Include `tokenize: true` to securely store the card for future cycles. If you already have a saved card token, you can start the plan via a sale/auth on the Payments API instead—this guide focuses on doing it from an **Order** checkout.


## Endpoint

**POST** `/orders`

### Headers

- `client_key` (string, required)


### Body

| Field | Type | Required | Description |
|  --- | --- | --- | --- |
| `lang` | string | Yes | Example: `en` |
| `data` | string (JWT) | Yes | Signed JWT with your standard order fields **plus** the subscription fields below. |


## Subscription Fields (add inside the JWT payload)

```jsonc
{
  // ... your standard Order fields (currency, id, subtotal, total, email, items[], billingPerson, shippingPerson, etc.)

  "is_subscription": true,
  "subscription_instructions": {
    "recurring_frequency": "WEEKLY" /* or "MONTHLY" or "YEARLY" */,
    "billing_cycles": 12             /* total number of planned rebills */
  },

  // Recommended when starting from an Order checkout
  "tokenize": true
}
```

### Field semantics

- **`is_subscription`** (boolean): Must be `true` to signal a subscription order.
- **`subscription_instructions.recurring_frequency`** (enum): One of `"WEEKLY"`, `"MONTHLY"`, `"YEARLY"`. Determines the cadence for subsequent charges.
- **`subscription_instructions.billing_cycles`** (integer): Total number of *recurring* charges after the initial checkout (or total billing periods including the first—depending on your account setting). Default behavior is **recurring cycles after the initial payment** unless configured otherwise.
- **`tokenize`** (boolean, recommended): If `true`, the first checkout securely stores the customer’s payment method for subsequent cycles.


> If you already hold a saved card token, you may skip `tokenize` and use the **Payments API** (`/payments/sale`) to start the plan with a token after the order is created. The order flow here focuses on hosted checkout + tokenization in one step.


## Example Unsigned Payload (Recurring Order)

```json
{
  "webhookUrl": "https://webhookurl",
  "redirectUrl": "https://redirectUrl",
  "checkoutUrl": "https://checkoutUrl",
  "currency": "USD",
  "id": "SUB-10001",
  "subtotal": 49.00,
  "total": 49.00,
  "email": "subscriber@example.com",
  "items": [
    {
      "id": "PLAN-BASIC",
      "name": "Basic Plan – Monthly",
      "price": 49.00,
      "quantity": 1
    }
  ],
  "is_subscription": true,
  "subscription_instructions": {
    "recurring_frequency": "MONTHLY",
    "billing_cycles": 12
  },
  "tokenize": true
}
```

### Signing the Payload

```javascript
const jwt = require('jsonwebtoken');
const payload = { /* the object above */ };
const signedData = jwt.sign(payload, 'your_secret_key');
```

### Final Request Body

```json
{
  "lang": "en",
  "data": "<signed_jwt_token>"
}
```

### Response (201)

```json
{
  "order_url": "https://sandbox.dimepay.app/e-order/abcd1234"
}
```

Open `order_url` in the browser to complete the first checkout.

## How it works

1. **Create Order** with `is_subscription: true` and `subscription_instructions`.
2. **First Checkout** (hosted page) is paid by the customer; if `tokenize: true`, Dime stores the payment method.
3. **Schedule** is created using `recurring_frequency` and `billing_cycles`.
4. **Subsequent charges** are attempted automatically using the stored payment method.
5. **Webhooks** fire on each invoice attempt/success/failure so you can update your system and notify customers.
6. **Lifecycle management** (pause, cancel, change plan) is handled through your Dime dashboard or API endpoints (if enabled for your account).


> If a charge fails, Dime will follow your configured retry/dunning rules and emit webhooks for visibility.


## Webhook considerations

Expect webhooks for:

`invoice.payment_succeeded` / `invoice.payment_failed`

The decoded JWT payload includes transaction and subscription data, along with a `details` object containing the transaction body, subscription body, and a message identifying the event.

### Example decoded JWT payload

```json
{
  "...transaction": "...",
  "...subscription": "...",
  "details": {
    "transaction": "transactionBody",
    "subscription": "subscriptionBody",
    "message": "SUBSCRIPTION_CREATED"
  }
}
```

The `details.message` field indicates the subscription event type. Possible values include:

- `SUBSCRIPTION_CREATED` — The subscription was created.
- `SUBSCRIPTION_STATUS_CHANGED` — The subscription status changed.


Use the subscription identifiers and order references to reconcile subscription state in your system.

## Security

All requests require your API key header:

```http
client_key: <your_api_key>
```

## Node.js Example — Create a Recurring Order

> Requires **axios** and **jsonwebtoken**.


```bash
npm install axios jsonwebtoken
```

```javascript
// create-recurring-order.js
const axios = require('axios');
const jwt = require('jsonwebtoken');

const API = 'https://sandbox.api.dimepay.app/dapi/v1';
const CLIENT_KEY = 'your_client_key';
const SIGNING_SECRET = 'your_secret_key';

async function createRecurringOrder() {
  const payload = {
    webhookUrl: 'https://webhookurl',
    redirectUrl: 'https://redirectUrl',
    checkoutUrl: 'https://checkoutUrl',
    currency: 'USD',
    id: 'SUB-10001',
    subtotal: 49.00,
    total: 49.00,
    email: 'subscriber@example.com',
    items: [
      { id: 'PLAN-BASIC', name: 'Basic Plan – Monthly', price: 49.00, quantity: 1 }
    ],
    is_subscription: true,
    subscription_instructions: {
      recurring_frequency: 'MONTHLY',
      billing_cycles: 12
    },
    tokenize: true
  };

  const signed = jwt.sign(payload, SIGNING_SECRET);

  const res = await axios.post(`${API}/orders`, {
    lang: 'en',
    data: signed
  }, {
    headers: { client_key: CLIENT_KEY }
  });

  console.log('Hosted Subscription URL:', res.data.order_url);
}

createRecurringOrder().catch(err => {
  console.error(err.response?.data || err.message);
});
```