Skip to main content

Squillify development is paused indefinitely. Read why, and discover what this experiment achieved. Read the story

MicroSkills Reference

Commercial Price Rounding

commerce.price_rounding

ProductionBounded custom (Class B)Deterministicstrictinstantv1.0.0
No network

Overview

You send an amount, its currency, and the rules your pricing policy uses, and we apply them in the order you gave, returning the final price plus every step that got there. Four different ideas stay separate on purpose: rounding to the currency's own decimals, rounding to a ladder step such as 0.50, rounding to the coin you name as the smallest one your till can give, and forcing a charm ending such as 99. We never reorder or optimise your chain — a ladder then a charm ending and a charm ending then a ladder are both legitimate policies and give different answers, so the order is yours. The number of decimals a currency has comes from the platform's single currency source, never from a table in this skill — and neither does the coin: we keep no denomination table, so CASH_ROUNDING always needs the increment from you. Any property other than amount, currency and rules is refused rather than ignored, at the top level of the request as much as inside a rule. This is not display formatting and not minor-unit conversion.

Pricing rules are simple one at a time and treacherous together: rounding to cents, snapping to a ladder, landing on a coin and forcing a 99 ending are four different decisions that teams routinely collapse into one helper, and the helper then disagrees with the till. Keeping them apart, applying them in the order you chose, and reporting each step makes the answer reviewable instead of surprising.

Reliability

Fully deterministic and exact: every step runs in decimal arithmetic, never in floating point, so a step never loses a cent, and the same amount under the same chain always gives the same price. The chain is applied verbatim, so reversing two rules is a different policy and a different answer. Every decimal string we return — price, original, and each step's before and after — is written at the currency's decimals, or at the value's own scale when a step legitimately produced more, and that writing never rounds: it pads with zeros or leaves the digits alone. A property this skill does not implement is refused, not ignored: an unknown top-level property is a broken request and comes back as the platform's TOOL_INPUT_INVALID, while an unknown property inside a rule is this skill's own PRICE_RULE_INVALID naming the rule's index. Failures, and what to do about each. PRICE_AMOUNT_INVALID — trigger: amount is unreadable as a plain decimal, negative, carries more than 12 decimals, or the chain pushes it past 1E18; retryable: no, the same request always fails; next: send the amount as a plain string of zero or more with at most 12 decimals. PRICE_RULE_INVALID — trigger: rules is empty, a rule's type is not one of the six, a rule carries a property its type does not use (mode on CASH_ROUNDING, increment on ENDING), or mode is not a rounding mode we know; retryable: no; next: fix the rule we name by index and remove the property that does not belong, since we refuse an unknown property rather than ignore it. PRICE_INCREMENT_INVALID — trigger: INCREMENT or CASH_ROUNDING without an increment, or with one that is zero, negative, unreadable, or finer than 12 decimals; retryable: no; next: send a positive decimal step such as "0.05". PRICE_ENDING_INVALID — trigger: an ENDING rule with no ending, an ending whose digit count does not match the currency's decimals, a non-digit ending, an endingDirection outside NEAREST, DOWN and UP, or an ENDING rule on a currency with no decimals at all; retryable: no; next: send exactly as many digits as the currency has decimals, and use an INCREMENT rule for a no-decimal currency. PRICE_RULE_CHAIN_TOO_LONG — trigger: more than 8 rules in one call; retryable: no; next: shorten the chain, because past a handful of rules the later ones almost always re-round what an earlier one already settled. CURRENCY_UNKNOWN — trigger: a currency code outside the twenty supported, or a blank one; retryable: no; next: pick a supported code, and convert on your side first if you price in another currency.

Context footprint

The answer is one small object: a price, the amount it came from, one entry per rule, and the currency with its decimals. Nothing scales with your catalogue. A successful call costs 1 execution credit.

When to use it

When a calculated amount has to become a price a shelf, a ladder or a cash drawer can carry, and you want to see how it got there.

When you want the price rendered for a human, converted into cents, converted into another currency, or taxed.

Scope

Note
Apply an ordered chain of enumerated commercial rounding and charm-pricing rules to one amount in one currency, reporting every step.

Non-goals

  • Does not format a price for display — finance.format_currency does that
  • Does not convert between major and minor units, which is finance.convert_minor_units
  • Does not convert between currencies and does not fetch a rate
  • Does not compute tax; apply tax with finance.calculate_vat on the result
  • Does not choose a pricing strategy, reorder your chain, or optimise it
  • Does not keep a currency table of its own

Properties

IdempotentRetry safeStreaming supportedFile input supportedRequires external service

Capabilities

math

Cost & billing

Flat rate per invocation

MetercallsBillable onsuccessCost per call1 credit

File handling

Accepts file_refProduces file_refMax input1 MB

How we handle your data

Sensitive output possible
What this means

This skill may receive sensitive content and may return submitted, transformed, extracted, or reformatted content.

Squillify guarantees
  • Runs inside Squillify
  • This skill runs inside Squillify.
  • Payloads are not sent to an external service by this skill.
  • Squillify does not permanently store submitted payloads.
  • Telemetry records metadata only, not submitted content.
  • Submitted payloads are not used for training.
  • Submitted payloads are not reviewed by humans.
  • This skill does not target sensitive data.
  • The response may contain submitted or transformed content.
Your responsibility

Squillify does not determine whether submitted content is sensitive. Your application is responsible for deciding what data it is allowed to submit. Your application is responsible for securing the response.

Read the Microskill Data Handling Policy

Input schema

FieldTypeRequiredDescription
amountobjectYesDecimal accepted as a precise string or JSON number with at most 12 fractional digits.
currencystringYesISO 4217 pricing currency.
rulesarrayYesFrom 1 through 8 closed rounding rules applied in caller order.

Output schema

FieldTypeRequiredDescription
pricestringYesCanonical plain-decimal amount.
originalstringYesCanonical plain-decimal amount.
changedbooleanYesWhether the final value differs.
stepsarrayYesFrom 1 through 8 applied steps in caller order, each a closed type with before and after amounts.
currencystringYesCanonical ISO 4217 pricing currency.
exponentintegerYesCurrency minor-unit exponent.

API contract

POST /v1/execute
curl
curl -sS -X POST "$BASE/v1/execute" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"skillKey":"commerce.price_rounding","input":{"amount":"19.427","currency":"CHF","rules":[{"type":"MINOR_UNITS"},{"type":"CASH_ROUNDING","increment":"0.05"}]}}'
Integrations
TypeScript SDK
import { Squillify } from "@squillify/sdk";

const sq = new Squillify({ apiKey: process.env.SQUILLIFY_API_KEY });

const { output } = await sq.execute("commerce.price_rounding", {"currency":"CHF","rules":[{"type":"MINOR_UNITS"},{"type":"CASH_ROUNDING","increment":"0.05"}],"amount":"19.427"});

Errors

CodeHTTPRetryableDescription
VALIDATION_ERROR400NoThe request payload failed schema validation.
UNAUTHORIZED401NoMissing or invalid API key.
SKILL_NOT_ACCESSIBLE403NoThe API key is not granted access to this skill.
SKILL_NOT_AVAILABLE_FOR_PLAN403NoThis skill is not included in your current plan.
PLAN_ELIGIBILITY_UNAVAILABLE503YesPlan eligibility could not be decided. Retry after backoff.
SKILL_NOT_FOUND404NoThe requested skill or version does not exist.
TENANT_RATE_LIMITED429YesRequest rate limit exceeded. Retry after backoff.
QUOTA_EXCEEDED429YesPlan quota exhausted. Retryable once the quota period resets.
EXECUTION_TIMEOUT504YesExecution exceeded the allowed time budget.
PRICE_AMOUNT_INVALID400NoThe request payload failed this skill's input validation.
PRICE_RULE_INVALID400NoThe request payload failed this skill's input validation.
PRICE_INCREMENT_INVALID400NoThe request payload failed this skill's input validation.
PRICE_ENDING_INVALID400NoThe request payload failed this skill's input validation.
PRICE_RULE_CHAIN_TOO_LONG429NoA size, quota, rate, or time limit was exceeded.
CURRENCY_UNKNOWN400NoThe request payload failed this skill's input validation.

Other limits

LimitValue
Recommended inline bytes32 KiB

Limitations

  • Does not format a price for display — finance.format_currency does that
  • Does not convert between major and minor units, which is finance.convert_minor_units
  • Does not convert between currencies and does not fetch a rate
  • Does not compute tax; apply tax with finance.calculate_vat on the result
  • Does not choose a pricing strategy, reorder your chain, or optimise it
  • Does not keep a currency table of its own
  • Formatting a price with a symbol and thousands separators
  • Converting between euros and cents
  • Adding VAT, which is a separate skill and a separate decision

How to call

POST /v1/execute (requires authentication)

Request bodyjson
{
  "skillKey": "commerce.price_rounding",
  "input": {
    "currency": "CHF",
    "rules": [
      {
        "type": "MINOR_UNITS"
      },
      {
        "type": "CASH_ROUNDING",
        "increment": "0.05"
      }
    ],
    "amount": "19.427"
  }
}

Examples

A Swiss shelf price, rounded to the 5-centime coin

Inputjson
{
  "currency": "CHF",
  "rules": [
    {
      "type": "MINOR_UNITS"
    },
    {
      "type": "CASH_ROUNDING",
      "increment": "0.05"
    }
  ],
  "amount": "19.427"
}
Expected outputjson
{
  "steps": [
    {
      "type": "MINOR_UNITS",
      "before": "19.427",
      "after": "19.43"
    },
    {
      "type": "CASH_ROUNDING",
      "before": "19.43",
      "after": "19.45"
    }
  ],
  "exponent": 2,
  "price": "19.45",
  "currency": "CHF",
  "changed": true,
  "original": "19.427"
}

A 0.50 price ladder, then a 99 charm ending — in that order

Inputjson
{
  "currency": "EUR",
  "rules": [
    {
      "type": "INCREMENT",
      "increment": "0.50"
    },
    {
      "endingDirection": "NEAREST",
      "type": "ENDING",
      "ending": "99"
    }
  ],
  "amount": "17.34"
}
Expected outputjson
{
  "steps": [
    {
      "type": "INCREMENT",
      "before": "17.34",
      "after": "17.50"
    },
    {
      "type": "ENDING",
      "before": "17.50",
      "after": "17.99"
    }
  ],
  "exponent": 2,
  "price": "17.99",
  "currency": "EUR",
  "changed": true,
  "original": "17.34"
}

A yen price, where the currency itself says there are no decimals

Inputjson
{
  "currency": "JPY",
  "rules": [
    {
      "type": "MINOR_UNITS"
    }
  ],
  "amount": "1234.56"
}
Expected outputjson
{
  "steps": [
    {
      "type": "MINOR_UNITS",
      "before": "1234.56",
      "after": "1235"
    }
  ],
  "exponent": 0,
  "price": "1235",
  "currency": "JPY",
  "changed": true,
  "original": "1234.56"
}
  • Land a calculated price on the 5-centime coin a Swiss till can actually give
  • Snap a cost-plus price onto a 0.50 ladder, then force a 99 ending
  • Round to a currency's real decimals without hard-coding that 0 means JPY

Avoid for

  • Formatting a price with a symbol and thousands separators
  • Converting between euros and cents
  • Adding VAT, which is a separate skill and a separate decision

Composable with

Safety & privacy

  • Runs without calling any external service.
  • Your payloads are never stored permanently.
  • Telemetry captures metadata only — never your payload contents.
  • We never train models on your payloads.
  • No human reviews your payloads.

Tags

pricingmathcurrencycommerce