Skip to navigation

Summary

A wallet denominated in a currency now pays for the invoice. Solvimon deducts the money from the taxable base of the lines the wallet covers, so no amount is taxed twice. You can now require approval before a pricing plan schedule becomes active. A coupon can now continue on the next schedule of a subscription. You can now backdate a discount to billing periods whose invoices are still draft. Solvimon now bills AvaTax partial exemptions as partial. You can now manage pricing plan groups in Desk. The customer portal is now available in German and Italian. Solvimon now disables a webhook after 20 consecutive failed deliveries. Desk now shows workflow executions on the customer and the invoice they ran for.

Pricing

Activating a pricing plan schedule can require approval An approval policy now accepts PRICING_PLAN_SCHEDULE as its source resource type. When such a policy applies, POST /v1/pricing-plan-schedules/{id}/activate does not activate the schedule. It creates an approval request, sets the schedule’s approval_status to PENDING_REVIEW, and returns the schedule in DRAFT. The schedule becomes active when an approver approves the request. A user who prepares a change can therefore ask for its release without the permission to release it.

Approval uses the same endpoints as quotes and invoices: POST /v1/approval-requests/{id}/approve, POST /v1/approval-requests/{id}/decline, and POST /v1/approval-requests/{id}/cancel. The same approver models apply: by group or ranked. A renegotiation usually changes more than one schedule. The three actions are therefore also available in bulk: POST /v1/approval-requests/approve, POST /v1/approval-requests/decline, and POST /v1/approval-requests/cancel.

Approve every schedule of a change in one request
curl -X POST https://test.api.solvimon.com/v1/approval-requests/approve \
-H "X-API-KEY: <apiKey>" \
-H "Content-Type: application/json" \
-d '{
"resource_ids": ["appr_jwDeeN0tYSY3F7BkeN1v", "appr_QwDeeN0vcYJaBLAc0C29"]
}'

Solvimon acts on each request separately. The response contains one result for each resource id. Each result has a status of SUCCEEDED or FAILED. A failed result also contains the error that stopped it. One failed request does not roll back the others.

To find the schedules that wait for review, read the subscription with GET /v1/pricing-plan-subscriptions/{id}. pending_review_pricing_plan_schedule_ids lists the schedules of the subscription that are pending review, in start_at order. pricing_plan_schedule_infos is unchanged: it lists only the active schedules. GET /v1/approval-requests now accepts source_ids[] for several sources in one request, in addition to source_id. Solvimon rejects a request that sends both.

A platform can have one active approval policy for each source type. These policies contain a single always-approve rule, and a second policy would repeat it. Solvimon also approves schedules in timeline order. You cannot activate a schedule while the schedule before it is still draft or pending review. See Requiring approval to activate.

A coupon can carry over to the next schedule You redeem a coupon against a pricing plan schedule, so its discounts belong to that schedule. POST /v1/pricing-plan-schedules/{id}/migrate and POST /v1/pricing-plan-schedules/{id}/copy now accept coupon_discount_behaviour. This field sets what happens to the coupons that are still active when you replace the schedule:

Continue the active coupons on the new schedule
{
"pricing_plan_version_id": "ppve_QwDeeN0vcYJaBLAc0C29",
"start_at": "2026-10-01T00:00:00+02:00",
"coupon_discount_behaviour": "CARRY_OVER"
}

NONE is the default. The discounts end with their schedule, as before. CARRY_OVER continues them on the new schedule for the remaining time of the coupon. Solvimon calculates the end date from the original start of the coupon. A three-month coupon that has run for two months therefore continues for one month on the new schedule. Solvimon does not redeem the coupon a second time. See Coupons across schedule changes.

A discount can be backdated while its invoices are still draft A discount can now start in any billing period whose invoice is not issued. The lock on billed periods now follows the last FINAL invoice. An invoice that is still DRAFT, for example on hold and not sent, therefore leaves its period open. You can add an ad hoc discount that you agreed on before the invoice goes out. A period with a FINAL invoice stays closed. The same rule applies when you remove a discount clause that has already started. See Invoice lifecycle.

An on-demand charge started from a payment carries its quantity When you charge an on-demand item through POST /v1/payments/authorize, you now state the quantity and the amount in the payment context. Each item accepts the same two optional fields as the direct request: units and flexible_amount. The flow can therefore charge a one-off item priced FLAT for the units ordered, and a flexible item for the agreed amount. FIXED items work as before.

Pricing items on the payment context
{
"pricing_items": [
{ "pricing_item_id": "prii_5RmXe2QbtKfYuA9DcNH3P", "units": { "number": "2" } },
{ "pricing_item_id": "prii_2PnBx7VdtRgLmE4WcQJ8K", "flexible_amount": { "quantity": "50.00", "currency": "EUR" } }
]
}

Solvimon validates both fields when you create the payment context. An incorrect quantity therefore returns an error to the caller before the customer pays. Solvimon still reads payment contexts stored in the earlier shape.

Wallets and credits

A wallet denominated in a currency pays for the invoice A CREDIT wallet type funded with an amount holds money, not credits. Such a wallet now pays for the invoice lines it is allowed to cover. Solvimon invoices the customer for the remainder.

The wallet holds a net amount, because Solvimon already charged tax on the top-up that funded it. Solvimon therefore deducts the money from the net amount of the line, and the covered part has no tax. Solvimon charges and taxes the remainder of the line as usual. For example, a 30.00 EUR line at 21% VAT against a 10.00 EUR balance invoices 20.00 EUR plus 4.20 EUR VAT:

NetVATTotal
Line as priced30.006.3036.30
Covered from the wallet-10.000.00-10.00
Charged20.004.2024.20

Solvimon always splits the coverage and never skips it. If the balance is less than the line, the wallet covers part of the line and Solvimon charges the remainder. Only lines whose product tax category matches the tax category of the wallet type are in scope. Other lines do not change. Solvimon applies the deduction last: after included volume, credits, discounts, and minimum commitment, and before tax. The deduction applies to the net amount that remains. A customer with both types of wallet spends credits first, because credits reduce volume and the money wallet reduces the amount.

Each charge reports what each wallet paid in a new wallet_balances list. Each entry names the wallet and gives its figures:

What one wallet paid for a charge
"wallet_balances": [
{
"wallet_id": "wall_5RmXe2QbtKfYuA9DcNH3P",
"used_balance": { "amount": { "quantity": "10.00", "currency": "EUR" } },
"left_balance": { "amount": { "quantity": "0.00", "currency": "EUR" } },
"available_balance": { "amount": { "quantity": "10.00", "currency": "EUR" } }
}
]

The list has one entry for each wallet that paid. A charge that a credits wallet and a money wallet both paid therefore reports the figures of each wallet separately. wallet_balances replaces wallet_balance_details, which holds one wallet at a time and only credits. See “Deprecated API fields” below, and An amount-denominated wallet pays for the invoice.

A grant into such a wallet must be in the currency of the wallet. Solvimon rejects a fixed grant in a different currency with wallet type <reference> is denominated in EUR, but the grant is in USD. Solvimon also rejects a grant that takes a percentage of pricing in a different currency, because there is no conversion. The error tells you to use a fixed grant or a different wallet type. A wallet type created before the default currency became mandatory has no default currency. You cannot grant into it until you set one.

Customers

A live seat assignment protects the resources it references Seat assignments record which child customer occupies which seat. Solvimon attributes per-seat credits against them. Solvimon now protects three resources while a live assignment references them: the child customer in the seat, the parent customer that holds the seat, and the per-seat product item that defines the seat type. For example, Solvimon rejects POST /v1/customers/{id}/archive for a child customer who still holds a live seat. A seat therefore cannot stay occupied by a customer that is no longer operational. The error names the assignment that blocks the change, and its status. First end the assignment: set end_at with PATCH /v1/seat-assignments/{id}. Then change the status. See Seat-based credits.

Fixes

  • You can now remove a billing email. PATCH /v1/customers/{id} with {"email": null} used to return INVALID_FIELD, although an empty string cleared the email. null, "", and whitespace now all mean no email.

Invoices

AvaTax partial exemptions are billed as partial Some jurisdictions tax part of a line and exempt the remainder. Software in Texas is a common example: 8.25% applies to 80% of the base, and the other 20% is exempt. Solvimon now stores the taxable fraction that AvaTax returns on the rate, and applies it. Solvimon calculates the rates on the taxable part of the base. The exempt remainder becomes a single 0% summary. The invoice and the tax filing therefore both show the split. The Texas example produces four tax lines: three on the 80% base, and one exempt line for the 20%. The invoice shows the exempt part once, not once per jurisdiction. A fully taxable or fully exempt line does not change. An invoice that is already issued keeps its tax. To apply the split to it, refresh it with POST /v1/invoices/{id}/refresh. See Tax calculation and integrations.

Fixes

  • Custom fields now persist after an invoice refresh. A CUSTOM_FIELD refresh with POST /v1/invoices/{id}/refresh used to update the “show on invoice” fields in the response and in the regenerated PDF. It did not write them to the invoice. The next GET returned the values from before the refresh.

Workflows

Filter and expand the resources a workflow ran against POST /v1/workflow-action-executions/search now filters on pricing_plan_subscription_id and wallet_id. The existing invoice, customer, payment, action, workflow, trigger, and status filters still apply. Workflow triggers now expand the resources they reference: workflow_id on a workflow trigger, pricing_plan_subscription_id and pricing_plan_schedule_id on a subscription trigger, wallet_id on a wallet trigger, and payment_id on a payment trigger. An execution row expands its workflow_action_id. You can therefore read the execution log in one call, with the resources of each row inline.

A condition on the billing entity of the invoice On invoice workflows, a workflow condition can now test invoice.billing_entity.id. A platform that bills from several billing entities can give each entity its own automation. Before this, you had to run one workflow and filter afterwards.

Workflow executions are shown where the work happened Desk now shows the execution table on the customer screen, on the invoice screen, and on the workflow. Each table lists the executions for that resource. To see what the automation did for an invoice, open the invoice. Select a row to open a panel with the details of that execution. The full log stays on its own page, “All workflow executions”. See Monitoring and audit.

Fixes

  • An EXPORT_TO_ERP action now requires an integration. You could leave the field empty, and Desk saved an action that had no integration to export through.

Integrations

Solvimon disables a webhook that never succeeds Solvimon now disables a webhook automatically after 20 consecutive failed deliveries. disabled_reason on the webhook gives the reason, so you can tell a webhook that Solvimon disabled from one that you disabled. An endpoint that is permanently unavailable therefore leaves the delivery queue. Before this, Solvimon retried it without end, on a backoff of up to several hours. While a webhook is disabled this way, you cannot send it a test event or resend its penalty box payload. Reactivate the webhook with PATCH /v1/webhooks/{id} first. Reactivation also clears the reason. See Webhooks.

Customer portal

German and Italian The customer portal and hosted checkout are now available in German and Italian, in addition to English and Dutch. The language switcher is now a standard part of both. You do not have to enable it. The starting language is the selection the visitor made. Without a selection, it is the locale on the customer record. Geolocation is the last fallback, because the location of the browser does not identify the customer. A regional variant falls back to its language: de-AT shows German and nl-BE shows Dutch.

The pay-invoice page uses the checkout components Paying an invoice from the customer portal and paying through the hosted checkout now use the same components. A payment therefore behaves the same from both starting points. Solvimon now passes the invoice amount to the payment method options. The page therefore offers only the methods that can settle the currency of the invoice.

Payments

Restrict the payment methods an Adyen acceptor offers allowed_payment_methods on a payment acceptor of type PAYMENT_GATEWAY on Adyen limits the methods it offers to a set you select. For example, one billing entity can accept cards, and a second can accept cards and direct debit. Desk lists the methods enabled on the selected Adyen integration, for integrations that Solvimon owns. If you leave the field empty, the acceptor offers every method that the integration has enabled. See Payment options.

Desk

Manage pricing plan groups in Desk A pricing plan group lets a subscription move between related plans. Plan groups are now a tab next to pricing plans. You can create and maintain a group in Desk, without the pricing plan groups API. You create a group with its name, its plans, and its portal settings. Drag the plans to order them, lowest tier first. That order is the upgrade path. Upgrades, downgrades, and cancellations each have their own timing: immediately, immediately with pro-rated fees, from the next billing period, or not allowed. A toggle sets whether customers can move between these plans themselves in the self-serve portal. You deprecate and reactivate groups from the same context menu as the other catalog resources.

Fixes

  • Desk now creates a user with a role. The form used to allow a user without a role, and that user could not do anything. The form now preselects Read only.
  • Clearing the end date of a schedule now clears it. An absent end_at means “keep the end date of the source schedule”, and only an explicit null means “no end date”. Desk used to drop the key when you emptied the field. The schedule therefore kept the old end date, which was usually in the past.
  • Extending an active schedule past a draft schedule that follows it no longer fails with No adjacent schedule found but flag to adjust the NEXT schedule was passed. The save used to ask to shift the next schedule without a check that this schedule was a draft.
  • The customer screen now hides archived payment methods. The list shows only the methods you can charge.
  • Revenue items on a pricing plan version now have even spacing. A gap used to appear between two of them.

Deprecated API fields

The following fields are now deprecated. They continue to work for backwards compatibility. Migrate to the replacements.

  • wallet_balance_details (pricing item summary price details): use wallet_balances instead. The block holds one wallet at a time. A charge paid by two wallets therefore reports only the figures of the wallet that paid last. The block can also express only credits.
  • used_wallet_credits, left_wallet_credits, available_wallet_credits (pricing item summary wallet balance details): use the used_balance, left_balance, and available_balance of the matching entry in wallet_balances instead. These fields carry credits or an amount.