> 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.

# Workflows

Workflows react to billing events and run actions automatically, such as emailing an invoice when it goes final or chasing an overdue payment.

---

## Why this matters

Without workflows, invoice delivery and dunning are manual: someone exports a PDF, writes an email, and tracks who has been chased. A workflow turns that into configuration. You declare which event to react to, which customers it covers, and what should happen, and Solvimon records every run so you can audit it later.

## How it works

A workflow is made of three objects:

```mermaid
erDiagram
    WORKFLOW ||--o{ WORKFLOW-ACTION : "has"
    WORKFLOW ||--o{ WORKFLOW-TRIGGER : "produces"
    WORKFLOW-TRIGGER }o--|| INVOICE : "fires for"
    WORKFLOW-TRIGGER ||--o{ WORKFLOW-ACTION : "runs"
```

* **Workflow** (Configuration API) defines the resource type, the variant that starts it, and the customer scope.
* **Workflow action** (Configuration API) defines what happens when the workflow runs. See [Workflow actions](/platform-guides/workflows/workflow-actions).
* **Workflow trigger** (Transaction API) is the record created each time the workflow matches an event, pointing at the invoice, payment, subscription or wallet involved. Every trigger runs the workflow's active actions. See [Workflow triggers](/platform-guides/workflows/workflow-triggers).

The split matters because configuration and history are separate: a workflow and its actions are things you edit, while a trigger is an immutable record of one occurrence. Editing an action does not change what past triggers did.

### Types and variants

The `type` field selects the resource the workflow runs for, and the matching configuration object carries the `variant` that decides which condition starts it.

| Type                        | Variant                     | Starts when                                                                                                                |
| --------------------------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `INVOICE`                   | `TO_FINAL`                  | An invoice is finalized.                                                                                                   |
| `INVOICE`                   | `OVERDUE`                   | An invoice passes its due date, repeated per configured period.                                                            |
| `INVOICE`                   | `UPCOMING_PAYMENT_REMINDER` | A configured period before the charge date.                                                                                |
| `PAYMENT`                   | `FAILED_PAYMENT`            | A payment attempt fails.                                                                                                   |
| `PRICING_PLAN_SUBSCRIPTION` | `FREE_TRIAL_REMINDER`       | A configured period before a free trial ends.                                                                              |
| `WALLET`                    | `WALLET_BALANCE`            | A wallet balance drops below a threshold.                                                                                  |
| `USAGE`                     | –                           | A customer's consumption crosses a threshold of their [usage limit](/platform-guides/meter-and-event-design/usage-limits). |

### Status lifecycle

| Status     | Meaning                                      |
| ---------- | -------------------------------------------- |
| `DRAFT`    | Being built. Never fires.                    |
| `INACTIVE` | Configured and ready, but not running.       |
| `ACTIVE`   | Running in production.                       |
| `ARCHIVED` | Permanently disabled. Cannot be reactivated. |

Statuses exist to support a safe rollout: build in `DRAFT`, activate for a small `customer_ids` scope, then widen the scope once you have verified the output.

## Implementation

### Create a workflow

Create the workflow first; it owns the actions you attach to it afterwards. This example emails the invoice to a single pilot customer when it goes final:

**`Create an invoice delivery workflow`**

```bash Create an invoice delivery workflow
curl -X POST https://test.api.solvimon.com/v1/workflows \
  -H "X-API-KEY: <apiKey>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Invoice final delivery",
    "reference": "invoice-final-delivery",
    "description": "Email the invoice PDF when it becomes final",
    "type": "INVOICE",
    "status": "DRAFT",
    "customer_ids": ["cust_AbD3DqausjOYiMNDZY11F"],
    "invoice": {
      "variant": "TO_FINAL"
    }
  }'
```

**`Response`**

```json Response
{
  "object_type": "WORKFLOW",
  "id": "wf_7KcQm1RtbXeUvL2NpHZ4S",
  "name": "Invoice final delivery",
  "reference": "invoice-final-delivery",
  "description": "Email the invoice PDF when it becomes final",
  "type": "INVOICE",
  "status": "DRAFT",
  "customer_ids": ["cust_AbD3DqausjOYiMNDZY11F"],
  "invoice": {
    "variant": "TO_FINAL"
  },
  "created_at": "2026-07-31T09:14:02Z"
}
```

Omit `customer_ids` to apply the workflow to every customer.

### Schedule-based variants

`OVERDUE`, `UPCOMING_PAYMENT_REMINDER` and `FREE_TRIAL_REMINDER` need a schedule expressed as a list of periods. Each period produces one step, so the workflow below chases at 7, 15 and 30 days past due:

**`Create a dunning workflow`**

```bash Create a dunning workflow
curl -X POST https://test.api.solvimon.com/v1/workflows \
  -H "X-API-KEY: <apiKey>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Overdue reminder 7/15/30",
    "reference": "overdue-reminder-7-15-30",
    "type": "INVOICE",
    "status": "DRAFT",
    "invoice": {
      "variant": "OVERDUE",
      "overdue": {
        "periods": [
          { "type": "DAY", "value": 7 },
          { "type": "DAY", "value": 15 },
          { "type": "DAY", "value": 30 }
        ]
      }
    }
  }'
```

For `UPCOMING_PAYMENT_REMINDER` the same structure goes under `invoice.upcoming_payment.periods`, and the periods count backwards from the charge date. For `FREE_TRIAL_REMINDER` use `pricing_plan_subscription.reminder_periods`, counting backwards from the trial end.

Wallet workflows use a threshold instead of a schedule. Only `LESS_THAN` is supported as the comparator:

**`Create a low-balance workflow`**

```bash Create a low-balance workflow
curl -X POST https://test.api.solvimon.com/v1/workflows \
  -H "X-API-KEY: <apiKey>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Low wallet balance",
    "reference": "low-wallet-balance",
    "type": "WALLET",
    "status": "DRAFT",
    "wallet": {
      "variant": "WALLET_BALANCE",
      "wallet_balance": {
        "wallet_type_id": "wtyp_5RmXe2QbtKfYuA9DcNH3P",
        "comparator": "LESS_THAN",
        "threshold": {
          "credits": {
            "quantity": "100",
            "credit_type_id": "ctyp_2PnBx7VdtRgLmE4WcQJ8K"
          }
        }
      }
    }
  }'
```

A wallet threshold carries either `credits` or `amount`, and which one is not your choice: it follows the unit the wallet type's ledger is denominated in. There is no conversion between a credit type and a currency, so a threshold in the other unit is rejected rather than converted.

| Wallet type                                    | Threshold | Has to match                           |
| ---------------------------------------------- | --------- | -------------------------------------- |
| `CREDIT` with `credit.grant_type` of `CREDITS` | `credits` | `credit.credits_grant.credit_type_id`  |
| `CREDIT` with `credit.grant_type` of `AMOUNT`  | `amount`  | `credit.amount_grant.default_currency` |

An `amount` threshold on a credits-denominated wallet type is rejected with `amount threshold not allowed for CREDITS wallets`, and a `credits` threshold on an amount-denominated one with `credits threshold not allowed for AMOUNT credit wallets`. A `percentage` threshold is not supported for wallet balances, and a `BALANCE` wallet type is refused on `wallet.wallet_balance.wallet_type_id`: wallet balance workflows cover credit wallets only. See [Credit types & wallets](/platform-guides/wallets-credits/credit-types-wallets) for how a wallet type is denominated.

Usage workflows also use thresholds instead of a schedule, but the thresholds are relative to each customer's own [usage limit](/platform-guides/meter-and-event-design/usage-limits): the workflow holds the thresholds (percentages of the resolved limit, or absolute values) while the limit itself is stored per customer, so one platform-level workflow covers every customer. Each threshold crossing fires the workflow's actions once per billing period. See [Usage limits and threshold alerts](/platform-guides/meter-and-event-design/usage-limits) for the full setup, including `POST /v1/workflows/init` for idempotent provisioning.

### Change and activate

Every state transition is its own endpoint. All of them accept the resource ID or your own `reference`:

**`Activate`**

```bash title=Activate
curl -X POST https://test.api.solvimon.com/v1/workflows/invoice-final-delivery/activate \
  -H "X-API-KEY: <apiKey>"
```

**`Deactivate`**

```bash title=Deactivate
curl -X POST https://test.api.solvimon.com/v1/workflows/invoice-final-delivery/deactivate \
  -H "X-API-KEY: <apiKey>"
```

**`Archive`**

```bash title=Archive
curl -X POST https://test.api.solvimon.com/v1/workflows/invoice-final-delivery/archive \
  -H "X-API-KEY: <apiKey>"
```

A `DRAFT` workflow can also be deleted outright, in line with the other draft resources: subscriptions, customers and pricing plans. Deletion is governed by `WORKFLOW.DELETE`, and only draft workflows are deletable; an active one has to be deactivated rather than removed, so no execution history disappears:

**`Delete a draft workflow`**

```bash title="Delete a draft workflow"
curl -X DELETE https://test.api.solvimon.com/v1/workflows/invoice-final-delivery \
  -H "X-API-KEY: <apiKey>"
```

To change the configuration, use [PATCH /v1/workflows/\{ref}](https://docs.solvimon.com/api-docs/configuration-api/workflows/patch-workflows-by-resource-id-or-reference). Widening the customer scope is the usual rollout step:

**`Roll out to all customers`**

```bash title="Roll out to all customers"
curl -X PATCH https://test.api.solvimon.com/v1/workflows/invoice-final-delivery \
  -H "X-API-KEY: <apiKey>" \
  -H "Content-Type: application/json" \
  -d '{ "customer_ids": [] }'
```

### Via Desk

Go to **Settings → Workflows**. The list shows every workflow with its type, variant and status. The detail page holds the configuration, the attached actions, and a table of the executions the workflow has produced.

## Edge cases

* A workflow with no active actions still creates triggers, but nothing is sent. Attach and activate at least one action before activating the workflow.
* `ARCHIVED` is terminal. If you need the configuration back, create a new workflow; `reference` must be unique, so pick a new one.
* Changing `customer_ids` does not backfill. Customers added to the scope only get the workflow on the next matching event.
* If your action includes a pay link, verify the PSP integration and payment acceptor first. A workflow that sends a broken pay link still reports the send as successful.

## API reference

* [List workflows](https://docs.solvimon.com/api-docs/configuration-api/workflows/get-workflows) and [Search workflows](https://docs.solvimon.com/api-docs/configuration-api/workflows/post-workflows-search)
* [Create a workflow](https://docs.solvimon.com/api-docs/configuration-api/workflows/post-workflows)
* [Get a workflow](https://docs.solvimon.com/api-docs/configuration-api/workflows/get-workflows-by-resource-id-or-reference) and [Update a workflow](https://docs.solvimon.com/api-docs/configuration-api/workflows/patch-workflows-by-resource-id-or-reference)
* [Activate](https://docs.solvimon.com/api-docs/configuration-api/workflows/post-workflows-by-resource-id-or-reference-activate), [Deactivate](https://docs.solvimon.com/api-docs/configuration-api/workflows/post-workflows-by-resource-id-or-reference-deactivate), [Archive](https://docs.solvimon.com/api-docs/configuration-api/workflows/post-workflows-by-resource-id-or-reference-archive)

> **Note**
>
> `DELETE /v1/workflows/{resourceIdOrReference}` is not yet covered by the generated API reference, so there is no schema page to link to yet.