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

# Quote features

These features are used through [`create_quote`](/mcp-server/tools/create-quote), [`import_order_form`](/mcp-server/tools/import-order-form) and [`write_quote`](/mcp-server/tools/write-quote).

## Ramps

A ramp is a quote whose terms change over time, for example a discount in year one and list price after. `create_quote` builds it in one call: the request's own `start_at`, discount, commitment, add-ons and overrides are step 1, and `ramp[]` lists the later steps.

* Each step is `{start_at, discount?, commitment?, enabled_pricing_ids?, direct_pricings?, overrides?, copy_overrides_from?}`.
* Discounts and commitments are **not** carried over to the next step. Add-ons are, unless the step sets its own (`[]` drops them).
* Each step ends where the next one starts; the last step stays open. The initial term is not changed.
* Steps out of order, a step at or after the end of the initial term, and a ramp combined with an upgrade are refused before anything is written. A failure on any step leaves no quote behind.
* Every step bills its one-off fees at its start. A step that would bill the same one-off fee again is warned about (`one_off_repeated`), with the override that waives it.
* To add a step to an existing DRAFT quote, use `write_quote` with `action: create` on `quote_schedules`. It closes the open step at the new step's start.

**`Validate a three-year ramp with a first-year discount`**

```json Validate a three-year ramp with a first-year discount
{
  "customer_id": "cust_AbD3DqausjOYiMNDZY11F",
  "pricing_plan_version_id": "ppve_Zt6yUw2QmK9nXr4VcHb37",
  "start_at": "2026-12-01T00:00:00Z",
  "initial_term": {"type": "MONTH", "value": 36},
  "discount": {"totals": [{"percentage": "20"}]},
  "ramp": [{"start_at": "2027-12-01T00:00:00Z"}],
  "mode": "validate"
}
```

## Price overrides

A price override changes the price of one item on this quote only, without changing the plan. Each entry is keyed by `pricing_item_config_id` and takes one of:

| Field                    | Meaning                                                                                                     |
| ------------------------ | ----------------------------------------------------------------------------------------------------------- |
| `amount`                 | A new price for a config with a single price                                                                |
| `bands`                  | New tiers, in the price list's currency                                                                     |
| `included_volume`        | A different included volume                                                                                 |
| `pricing_period`         | Price per another period, e.g. €5,000 a year on a monthly-priced config. The billing period doesn't change. |
| `pricing_type` + `bands` | A different pricing model, see below                                                                        |
| `not_billed: true`       | Leave the item out of billing on this quote                                                                 |
| `remove: true`           | Back to the plan price                                                                                      |

* Pass overrides on `create_quote`, on a ramp step (`ramp[].overrides`), or on an existing DRAFT quote with `write_quote` `action: set_overrides`, the quote or version id, and `body: {overrides, mode}` (`validate` first, then `apply`). `set_overrides` merges with the overrides already on the quote, including ones made in Desk. On a ramp, name the step with `body.pricing_plan_schedule_id`.
* **Per step.** Every ramp step has its own overrides; a step without them bills list price. `copy_overrides_from` starts a step from an earlier step's overrides, so you only pass what changes.
* **Not billed** removes the item from the quote and its invoices, without a €0 line. It shows as "not billed" in the quote's `commercials` and summary. `pricing_type: NONE` means the same.
* **Change the pricing model** with `pricing_type` and `bands`: `FLAT`, `TIERED` (graduated), `TOP_TIERED` (the top tier's rate for all usage) or `STAIR_STEP`. A percentage stays a percentage. Fixed fees, top-ups and pass-through configs are changed in the plan instead.
* A discount, commitment or markup on a config you override is refused, because the quote and its invoices would disagree. Prices of conditions inside a config keep their own price.
* Approval policies see *whether* a quote has an override, not its size. Writing overrides needs the permission to edit schedule pricing overrides.

**`Waive the platform fee in step 1, contract price in step 2`**

```json Waive the platform fee in step 1, contract price in step 2
{
  "start_at": "2026-12-01T00:00:00Z",
  "initial_term": {"type": "MONTH", "value": 12},
  "overrides": [{"pricing_item_config_id": "pico_platform", "amount": "0.00"}],
  "ramp": [{"start_at": "2027-03-01T00:00:00Z", "overrides": [
    {"pricing_item_config_id": "pico_platform", "amount": "15000.00"}
  ]}]
}
```

**`Change a flat 0.5% fee into graduated tiers`**

```json Change a flat 0.5% fee into graduated tiers
{
  "action": "set_overrides",
  "resource_type": "quotes",
  "id": "quot_Fk8nRw3TmQ6vLb2YcHd59",
  "body": {"mode": "validate", "overrides": [{
    "pricing_item_config_id": "pico_transaction_fee",
    "pricing_type": "TIERED",
    "bands": [
      {"percentage": "0.35", "tier_top_bound": {"amount": {"quantity": "10000000.00", "currency": "EUR"}}},
      {"percentage": "0.30"}
    ]
  }]}
}
```

## Entitlement overrides

Sets a negotiated feature value on the quote, for example 1 billing entity where the plan grants 3. Pass `entitlements` on `create_quote`, or update `quote_subscriptions` on a DRAFT quote. Each entry has `feature_reference` (or `feature_id`) and the value field of the feature's type: `number`, `switch`, `enum`, `amount` or `string`. `remove: true` goes back to the plan value.

The plan or an enabled add-on must grant the feature. On a ramp the value applies to every step. When the quote converts, Solvimon checks that the values were carried over to the subscription.

**`Limit billing entities to 1`**

```json Limit billing entities to 1
{"action": "update", "resource_type": "quote_subscriptions", "id": "ppsu_Lw6nQx3TmR8vKb2YcPd19", "body": {"entitlements": [{"feature_reference": "billing_entities", "number": "1"}]}}
```

## Direct pricing

Prices a product the plan doesn't carry, such as an implementation fee, on this quote only. Pass `direct_pricings` on `create_quote`, or use `write_quote` on `quote_pricings`. Items the plan already prices (override those instead), usage and seat items, and another currency are refused. **Approval policies don't see direct pricings**, so every call warns you; tell the approver before finalizing.

**`Add an implementation fee`**

```json Add an implementation fee
{"action": "create", "resource_type": "quote_pricings", "body": {"pricing_plan_schedule_id": "ppsc_Vb3nQx7TmR2kLw9YcPd48", "product_item_id": "proi_Hx2nRt8WqK5vLb3YcMd17", "amount": "2500.00", "name": "Implementation fee"}}
```

## Payment terms

The payment term is `due_date_configuration` on the quote's subscription: `{"type": "PERIOD_AFTER_INVOICE_DATE", "period": {"type": "DAY", "value": 30}}` or `{"type": "END_OF_THE_MONTH"}`. Set it on `create_quote`, or update `quote_subscriptions` on a DRAFT quote. `create_quote` returns the `payment_term` the quote got and where it came from, and warns `payment_term_default` when Solvimon's default applies.

## Quote text

A quote version's text is `content`: plain text (`{"type": "DEFAULT", "default": {"header": "...", "footer": "..."}}`) or rich text (`{"type": "TIPTAP", "tiptap": "<ProseMirror JSON as a string>"}`). Use headings, paragraphs and lists. **Tables are refused**, because the quote editor in Desk can't show them; write each row as a list item instead.

## Finalize and approvals

`write_quote` `action: finalize` locks a DRAFT version and starts any approval policy. Ask [`get_quotes`](/mcp-server/tools/get-quotes) `action: evaluate` first to see whether it will need approval.

On the live server, finalize works on the quote's latest DRAFT version and takes two calls:

1. Without `confirmed: true` nothing is written. The result says what finalizing does and whether it needs approval: the policies that fire, the approvers and the strategy. It warns when the quote's owner is the only approver.
2. With `confirmed: true` the version is finalized and the card shows it as FINAL or WAITING_APPROVAL.

If the approval evaluation can't be read (your role lacks the permission), the status is `UNKNOWN`, never "no approval needed". If an active policy is misconfigured, the finalize is refused before anything is written. A rep is never their own approver.

## Signing

The order is: finalize → `add_recipient` (signer or viewer) → `request_signature` (DocuSign when connected) → signed → `create_subscription`. `mark_signed` records a signature collected outside Solvimon. `request_signature` and `mark_signed` are confirm-first. The agent doesn't ask for signers before the version is FINAL, because the terms may still change. On live, signers are added in Desk.

## Upgrade quotes

`create_quote` with `upgrade_from_subscription_id` quotes an upgrade of a running subscription. On acceptance the current subscription is cancelled on the start date, unused prepaid fees are credited, and both are settled on one invoice. A standalone quote would instead run a second subscription next to the first one.

* `start_at` is required, and the customer must be the subscription's own.
* For now the target is a newer version of the same plan, or the same version with changed terms.
* Billing period, currencies, add-ons, discount, commitment and overrides are copied from the running schedule. Change them afterwards with `write_quote`.
* The quote card names the subscription it replaces and what acceptance does.