Skip to navigation

Summary

A one-off item priced FLAT can now bill a unit price and a quantity, not only a single lump sum. A subscription can move between the plans of a pricing plan group in one API call. Credits can now belong to one seat instead of a shared pool. An invoice that spent an amount-denominated wallet now books that spend out of the wallet when it goes final. E-invoicing has a new downloadable report. An invoice’s payment status can now be set directly. Workflows can export invoices to an ERP and tag the emails they send. An integration can now be addressed by its reference.

Pricing

A one-off item can bill a unit price and a quantity A one-off charge used to carry only a single lump sum. To sell four products at 100 EUR, you had to calculate 400 EUR and enter that amount yourself. A one-off pricing item config priced FLAT now carries a unit count, the same way a per-seat item carries seats. The band’s amount becomes the unit price. Its fixed_amount stays a flat fee, charged once. The line bills fixed_amount + amount × units. FIXED is unchanged: it still bills a single lump sum.

You can set the count in three places. default_units on the pricing item config sets the plan-level default. When absent, it defaults to 1. units on a pricing plan schedule overrides the default per subscription. It is keyed on the pricing item config, the same way seats_values is:

Units on a schedule
"units": [
{ "pricing_item_config_id": "pico_5RmXe2QbtKfYuA9DcNH3P", "number": "4" }
]

On an on-demand charge, you state the quantity yourself. units is required for a FLAT item, and it must be positive. It does not fall back to default_units. default_units is a prefill for an ordering flow. It is not a quantity you confirmed.

Order three more units
curl -X POST https://test.api.solvimon.com/v1/invoices/charge-on-demand-pricing-items \
-H "X-API-KEY: <apiKey>" \
-H "Content-Type: application/json" \
-d '{
"pricing_plan_schedule_id": "ppsc_jwDeeN0tYSY3F7BkeN1v",
"pricing_items": [
{ "pricing_item_id": "proi_hwDeeN0vcYJaBLAc0C1W", "units": { "number": "3" } }
]
}'

A unit count is always a number. default_units.amount and default_units.count are rejected. Use number instead. Both fields are accepted only on a one-off item priced FLAT.

A count of zero is valid on a schedule. It bills no line. Ordering zero units on demand is rejected: it is not an order. A fixed wallet grant on such an item scales by the unit count. A top-up product that grants 500 credits per unit grants 1500 credits for three units. A grant that converts from the paid amount, or takes a percentage of it, cannot scale this way. It is rejected at configuration time with credits_grant.conversion and amount_grant.percentage are not supported on a ONE_OFF pricing item priced FLAT. Copying or migrating a schedule carries its units across.

Move a subscription between the plans of a pricing plan group Pricing plan groups have held the rules for moving between related plans since they were introduced. Until now, there was no way to execute the move. POST /v1/pricing-plan-subscriptions/{id}/change-plan performs it:

Upgrade a subscription to another plan in its group
curl -X POST https://test.api.solvimon.com/v1/pricing-plan-subscriptions/ppsu_jwDeeN0tYSY3F7BkeN1v/change-plan \
-H "X-API-KEY: <apiKey>" \
-H "Content-Type: application/json" \
-d '{
"pricing_plan_id": "ppla_QwDeeN0vcYJaBLAc0C29"
}'

The target plan must belong to the same group as the subscription’s current plan. That group must be ACTIVE. Solvimon infers the direction from the members’ order. A move from a lower order to a higher order is an upgrade. It follows the group’s upgrade_type. A move from a higher order to a lower order is a downgrade. It follows the group’s downgrade_type. That policy sets the timing:

PolicyTiming
IMMEDIATEStarts now, or at a start_at you supply
IMMEDIATE_PRO_RATAStarts now, or at a start_at you supply
NEXT_BILLING_PERIODStarts at the next invoice date; rejects a caller-supplied start_at
NOT_ALLOWEDRejects the transition

You can also move a plan sold in several billing periods between those periods. Pass billing_period with the same pricing_plan_id. The direction then follows the length of the period instead of the order. The response is the new schedule. See Plan changes in a pricing plan group.

The move builds a new schedule on the target plan. It does not carry over the optional pricings, commitments, discounts, or seats configured on the schedule it replaces. It works whether the current schedule follows a pricing plan version or a rate card. Solvimon validates the currency against the target version’s settings. For the customer portal, GET /v1/portal/pricing-plan-subscriptions/{id}/pricing-plan-group returns the group a subscription’s plan belongs to. A self-service plan picker needs this to know which plans it may offer.

A credits-priced config takes its periods from the credits item A pricing item config that prices usage in credits used to declare its own billing_period and pricing_period. These could disagree with the CREDITS item that settles the credit type it consumes. Where they disagreed, each pricing period’s overage landed on its own invoice instead of the one invoice for the billing period. For example, August’s usage was invoiced on 1 September instead of 1 October. Both periods are now inherited from the credits item. This keeps the overage and the credits it draws on the same invoice.

Three configurations that used to be accepted are now rejected: a credits-priced config with its own periods, credits items that disagree on a cadence, and a pricing period wider than its billing period.

See Credits in pricing plans.

A draft schedule can be corrected, and a draft subscription can be removed Two validations used to treat a draft as though it were already billing. A draft schedule’s start date could not move into the past, even though a contract being prepared often starts earlier than the day you configure it. A draft subscription could not be deleted while it still carried draft schedules, which is every draft subscription. Solvimon now allows both. See Draft schedules.

Fixes

  • You can now add a discount to a product item that a coupon already discounts. The request used to fail with start_at before previous, needs to start after, regardless of the dates you sent. The index named in the error pointed at a clause the caller never sent: the coupon’s own discount, appended to the list during the merge and out of date order. Both clauses were always valid. Only their order was not.
  • Migrating a pricing plan schedule that carries override pricings now succeeds. POST /v1/pricing-plan-schedules/{id}/migrate used to fail with Pricing ... not in the pricing plan version ... whenever the schedule had any override, even though the request never touches overrides. Solvimon was resolving the override against the version being migrated away from.
  • Activating a draft schedule beside an existing one no longer fails on its seats. Ending the adjacent schedule used to pass the draft’s own override pricings on as if they belonged to the active schedule. That schedule then rejected them as pricings its version does not contain.

Wallets and credits

Seat-owned credits SEAT_POOL grants credits per seat into one shared customer pool. Any seat can spend any credit in that pool. PER_SEAT is now the third wallet grant source. It keeps each seat’s credits to that seat: one grant per active seat assignment, restricted to the customer who occupies it. A seat can spend its own grant plus any unrestricted grant in the same wallet. A personal allowance and a shared pool can sit side by side.

Solvimon prorates the quantity by how much of the period the assignment covers. A seat handed over mid-month grants the incoming occupant only the remainder, not a full allowance. Assignments are not capped against the seats you paid for: credits follow the assignments. A period with a handover, or with more seats assigned than paid for, therefore grants more than the paid seats account for. Solvimon reports this excess rather than withholding it, because capping would make one seat’s credits depend on another’s. It is recorded at issuance and read back as over_granted: on the grant, on the wallet balance status, and per customer in customer_details.

A grant issued to a seat
{
"source": "PER_SEAT",
"seat": {
"customer_id": "cust_5RmXe2QbtKfYuA9DcNH3P",
"product_item_id": "proi_2PnBx7VdtRgLmE4WcQJ8K"
},
"grant_credits": { "quantity": "250", "credit_type_id": "ctyp_7KdRa4NvpWzYbT6FgXH2M" },
"over_granted": { "credits": { "quantity": "50", "credit_type_id": "ctyp_7KdRa4NvpWzYbT6FgXH2M" } }
}

A seat-owned grant must be attributable to one seat. PER_SEAT therefore requires a fixed credits_grant.credits on a pricing item priced PER_SEAT. Solvimon rejects an amount grant with PER_SEAT requires a fixed credits_grant.credits; a seat-owned amount grant is not supported. A wallet type granted from PER_SEAT cannot carry a second grant rule on the same wallet type: two rules would produce the same grant key, and Solvimon would drop the second one without a trace.

An invoice that spent an amount-denominated wallet books that money out at final A CREDIT wallet type funded with an amount keeps its ledger in a currency. Usage covered by such a wallet used to be held only as a reservation. The available balance already reflected it, so a second invoice could not spend the same money, but no money had actually left the wallet. When the invoice goes FINAL, the covered amount now leaves the wallet, oldest-expiring grant first. Solvimon recognises it as revenue with no tax, because it already charged tax on the top-up that funded the balance. Voiding or recalculating the invoice before it is final releases the reservation, and the balance becomes spendable again. Re-running a final invoice does not book the spend twice. See Credit types & wallets.

Quotes

Pricing defined directly on a schedule appears on the quote A quote whose schedule carries its own pricing, instead of pricing from a pricing plan version, used to show that pricing nowhere: not on the quote overview, and not on the generated PDF. Both now show it. The quote overview also gained an “expand all” action. You can read a quote with several products in one pass, instead of opening each section separately.

Additional settings on a new quote are collapsed The quote creation form now groups its secondary fields into the same collapsible “Additional settings” section the subscription form uses. Billing currency overrides the pricing plan’s currency. Left open, the field invited a sales user to fill it in as though it were required. Collapsed, Solvimon sets it only when you are genuinely overriding the currency.

Invoices

Set an invoice’s payment status directly payment_status on an invoice used to be read-only. You could change it only by recording a payment. You can now patch it directly on a FINAL invoice, for settlement that happened outside Solvimon:

Mark a final invoice as paid
curl -X PATCH https://test.api.solvimon.com/v1/invoices/invo_jwDeeN0tYSY3F7BkeN1v \
-H "X-API-KEY: <apiKey>" \
-H "Content-Type: application/json" \
-d '{ "payment_status": "PAID" }'

You can only set PAID or UNPAID. PARTIALLY_PAID and OVERPAID follow from the paid and open amounts, so Solvimon rejects them. Solvimon also rejects a request that sets the deprecated paid flag to a value the status contradicts. You cannot set the field while creating an invoice.

See Invoice payment status.

Avalara e-invoicing moves to ELR 1.6 The Avalara integration now runs on E-Invoicing and Live Reporting 1.6. It reports a business status and an authority status alongside the document status. Two refresh behaviours come with this. Statuses stamped on the same millisecond now sort by their message instead of arbitrarily. Follow-up now stops once the most recently submitted e-invoice reaches a final state. Earlier failed attempts no longer keep follow-up alive. See E-invoicing.

The new invoice PDF renderer is enabled per platform The rendering service that already produces quote PDFs was introduced for invoices as an opt-in preview. An entitlement on your platform now selects it. It covers every invoice PDF, not only a download from Desk. The copy attached when an invoice is finalised or emailed goes through the same renderer, so one invoice cannot look two different ways. The download button is translated into the languages the customer portal supports. The renderer is still opt-in. Contact your account manager to have it switched on.

Search a full invoice history by date A date range on POST /v1/invoices/search now returns its page correctly on a platform with years of invoices behind it. A wide range used to risk running past the request timeout and returning a 500. You can now ask for a quarter or a year in one request, for a reporting or reconciliation run. Payment, payment request, bulk action, and subscription search filter on dates the same way, and answer faster.

This change also fixes a related bug: a bound given with sub-second precision now matches the second that contains it. It previously matched nothing at all.

Filter invoices by the workflow that acted on them You can now filter invoices on the status of the workflow actions that ran against them. Use workflow_action_execution_statuses[] when listing, and workflow_action_execution_status in a search body. You can now pull invoices whose workflow actions failed in one request. Before this, you had to read the execution log and look each invoice up yourself.

Fixes

  • You can now finalise a credit note against a one-off invoice without a manual refresh. The PATCH to FINAL used to return a 500, and the validator reported a total of 0. Solvimon was not reloading the sales tax rates of a one-off product for a credit note the way it does for the one-off invoice itself.
  • AvaTax rates are now loaded for the next schedule as well as the previous one. An invoice spanning two schedules, where the second schedule prices products the first does not, used to be taxed without rates for those products.

Reporting

An e-invoicing report E-invoicing status used to be visible only per invoice, never in aggregate. To answer “which invoices have not been accepted yet,” you had to open them one at a time. A new E_INVOICING report joins the report downloads, with one line per e-invoice. Each line carries the invoice it belongs to (number, date, billing period, status, type, currency, amount, billing entity, and customer) and the e-invoicing side of it (external reference, processor, applied mandate, integration, current status and message, submitted at, last status at, and how many statuses it has been through). An invoice submitted more than once gets a line per submission, so a failure and the resubmission that followed it both appear in the extract. See E-invoicing report.

Integrations

Address an integration by its reference The reference on an integration tells several integrations of the same type apart. You could already use it everywhere except on the integration itself, which only accepted its resource id. GET, PATCH, and DELETE on /v1/integrations/{idOrReference} now accept either, and so do the deprecate and activate actions under it. If your code already knows an integration by its reference, it no longer has to store the generated id alongside it. You can also now delete draft ERP integrations.

Workflows

Export an invoice to an ERP from a workflow EXPORT_TO_ERP joins SEND_EMAIL_TO_CUSTOMER as a workflow action type. The action names the integration responsible for the export through export_to_erp.executor. The one available executor is THIRD_PARTY. It performs the export through the connected ERP integration and records a workflow execution row for it. An export that used to happen outside the workflow engine is now visible in the execution log beside the rest of the automation, with the same retry and status reporting. You can configure the action in Desk. The panel lists the ERP integrations connected to your platform.

Tag the emails a workflow sends The send-email action now accepts tags: up to 3 ASCII tags of at most 128 characters each. Solvimon passes them to Mailgun as o:tag, so you can filter and report on messages in the Mailgun dashboard. The legacy Paragon integration exposed this, and migrated templates lost it. You set tags per workflow, so you can tell different workflows apart. They apply only to a Mailgun account you connected yourself. A Solvimon-managed email integration rejects them with not allowed for Solvimon-managed email integrations, and tags its own traffic instead.

Find the workflow activity for one customer POST /v1/workflow-action-executions/search now accepts a customer_id filter. The workflow trigger endpoints accept expand[]=customer_id, which inlines the customer on the trigger. Before this, answering “what did the automation do for this customer” meant searching every execution and then looking up each row.

An overdue reminder template of its own Selecting a trigger preselects the email template written for it, which keeps a workflow from going out under the wrong wording. The overdue invoice trigger had no template of its own and fell back to the standard final invoice template. That template reads as though the invoice had just been issued, not as though it were late. There is now a dedicated overdue reminder template. The “Invoice: status set to overdue” trigger preselects it, and a new sandbox is created with it already configured for the overdue notification.

Customer portal

Pricing defined directly on a schedule is shown A subscription schedule can carry pricing of its own, in addition to or instead of the pricing that comes from a pricing plan version. The portal used to render only the pricing plan version’s pricing. A customer looking at their own subscription saw a plan that was missing the products negotiated onto it directly. The portal now lists those products with the rest.

Desk

Fixes

  • Deleting a customer or a subscription now updates the list you deleted it from. A delete the API refuses now reports why, instead of appearing to do nothing. Deleting from a detail page no longer returns you to the previous page regardless of what happened.
  • Text in the rich-text editor of a quote is now rendered in the PDF in the font it was written in, and the right-hand edge is no longer cut off.
  • Invoice numbering settings no longer submit an invoice date determination type that you did not change. Editing a self-billing numbering format used to re-submit the platform’s date determination type, default it to WHEN_INVOICE_GOES_TO_FINAL, and apply it at the wrong level. That could change when invoices take their date, across the whole platform.
  • A custom field shared by two integrations is now edited per integration. With two fields carrying the same reference on different integrations, Desk used to match on the reference alone. Both inputs showed the same value, and editing one changed the other.