Skip to content
ApiqDevelopers
API v1.64.0Open console

Publish rule set

PUT/v1/config/rules
Idempotency-Key requiredAccepts X-Api-Key · oauthClientCredentials · bearer

Publish a new immutable rule-set version

Mints version baseVersion+1 from the full rule list in the body; prior versions stay readable forever.Show moreMints version baseVersion+1 from the full rule list in the body; prior versions stay readable forever. Optimistic concurrency: `baseVersion` must equal the current published version, otherwise 409 CONFLICT with details.currentVersion — re-read, re-simulate, re-publish. Two rules tying at the same layer/priority/specificity, or a lower layer widening a higher layer's cap, are 400 VALIDATION at publish time — never a runtime coin-flip. Negative-margin guard: when the quoted simulation priced any line at a negative margin, publish is 409 CONFLICT (details.reason NEGATIVE_MARGIN_OVERRIDE_REQUIRED, with details.simulationId and details.negativeMarginLines) unless the body sets negativeMarginOverride true AND gives a reason; an override with no reason (and no note) is 400 VALIDATION details.reason REASON_REQUIRED. The reason and the override are recorded on the version and on config.rules_published, not echoed on RuleSet. Emits config.rules_published on the event envelope. Requires rules:manage.

Headers

  • Idempotency-KeystringRequired
    Mandatory on mutations: **48h TTL**; replay with same body-hash returns the original response with Idempotency-Replayed true; same key + different body is 409 IDEMPOTENCY_CONFLICT; in-flight duplicate…Show moreMandatory on mutations: **48h TTL**; replay with same body-hash returns the original response with Idempotency-Replayed true; same key + different body is 409 IDEMPOTENCY_CONFLICT; in-flight duplicate is 409 IDEMPOTENCY_IN_PROGRESS.

Request body

  • baseVersionintegerRequired
    Must equal the current published version, else 409 CONFLICT (details.currentVersion)
  • simulationIdstringOptional
  • notestringOptional
    Change note shown in the console version history
  • reasonstringOptional
    Why this version is published. Mandatory with negativeMarginOverride — an override with no reason is 400 VALIDATION details.reason REASON_REQUIRED (a note stands in for it on an ordinary publish);…Show moreWhy this version is published. Mandatory with negativeMarginOverride — an override with no reason is 400 VALIDATION details.reason REASON_REQUIRED (a note stands in for it on an ordinary publish); longer than 500 characters is 400 VALIDATION INVALID_RULE. Recorded on the version and on config.rules_published; not echoed on RuleSet.
  • negativeMarginOverridebooleanOptionalDefault false
    Explicit override of the negative-margin guard: true publishes a rule list whose quoted simulation priced lines below their base.Show moreExplicit override of the negative-margin guard: true publishes a rule list whose quoted simulation priced lines below their base. Without it such a publish is 409 CONFLICT details.reason NEGATIVE_MARGIN_OVERRIDE_REQUIRED.
  • rulesarray of MarkupRuleRequired
    6 child attributes
    • ruleIdstringRequired
      Stable across versions; the id appliedRules[] quotes
    • layerstringRequired
      Where the rule sits; lower layers (ORG, SITE) can narrow a higher layer's rule, never widen it.
      • PLATFORM
      • TENANT
      • ORG
      • SITE
    • scopeMarkupRuleScopeRequired
      Where a rule applies. Every field optional; an absent field matches everything; more fields = more specific.Show moreWhere a rule applies. Every field optional; an absent field matches everything; more fields = more specific. Tenant is implied by the token, never sent.
      9 child attributes
      • domainstringOptional
        Canonical product code
      • supplierstringOptional
        Only offers of this supplier.
      • channelstringOptional
        Only sales through this channel, for example API, CONSOLE or AI.
      • siteIdstringOptional
        Only sales on this site.
      • posstringOptional
        Point-of-sale market
      • currencystringOptional
        ISO-4217 of the resolved display currency
      • productClassstringOptional
        Only offers of this product class.
      • validFromstring · date-timeOptional
        The rule applies from this time.
      • validTostring · date-timeOptional
        The rule applies until this time.
    • actionMarkupRuleActionRequired
      What a rule does. `value` is always an integer — no floats anywhere near money: basis points for the *_PCT kinds (1250 = 12.50%); minor units of `currency` for MARKUP_ABS and FEE_LINE; the rounding…Show moreWhat a rule does. `value` is always an integer — no floats anywhere near money: basis points for the *_PCT kinds (1250 = 12.50%); minor units of `currency` for MARKUP_ABS and FEE_LINE; the rounding increment in minor units for ROUND.
      5 child attributes
      • kindstringRequired
        What the rule does to the price, a percentage or absolute markup, a commission, a fee line or rounding.
        • MARKUP_PCT
        • MARKUP_ABS
        • COMMISSION_PCT
        • FEE_LINE
        • ROUND
      • valueintegerRequired
        An integer, in basis points for the percentage kinds (1250 is 12.50%) and in minor units of the currency otherwise.
      • currencystringOptional
        ISO-4217; required for MARKUP_ABS and FEE_LINE when scope.currency is absent
      • feeTypestringOptional
        FEE_LINE only — the breakdown label the fee renders under
      • roundingModestringOptional
        ROUND only; default UP
        • UP
        • DOWN
        • HALF_UP
    • floorMarkupRuleFloorOptional
      The floor primitive resolving conflict C-5: after rule application sell:= max(sell, floor).Show moreThe floor primitive resolving conflict C-5: after rule application sell:= max(sell, floor). SUPPLIER_SELL_FLOOR takes the offer's supplier-imposed floor; ABS is a tenant-policy floor in `value`. Floor enforcement is law — there is no flag to disable it.
      2 child attributes
      • kindstringRequired
        The floor to keep, the supplier's own sell floor or an absolute amount.
        • SUPPLIER_SELL_FLOOR
        • ABS
      • valueMoneyOptional
        Integer minor units + ISO-4217, never floats (platform law)
        5 child attributes
        • amountintegerRequired
          Minor units
        • currencystringRequired
          ISO-4217
        • fxAppliedbooleanOptional
          True when the amount was converted from the supplier's currency.
        • fxSnapshotIdstringOptional
          The exchange-rate snapshot the amount was converted with, fixed when the price was quoted.
        • breakdownarray of PriceBreakdownLineOptional
          Sell-side component lines summing to amount; the platform may send it empty.Show moreSell-side component lines summing to amount; the platform may send it empty. One line shape everywhere — the same PriceBreakdownLine the rule simulation answers. Never carries a supplier net.
    • priorityintegerRequired
      Higher wins within a layer at equal specificity

Responses

  • 200Published; the body is the new versionRuleSet
  • 400VALIDATION. details.reason names the rule that failed: INVALID_RULE, RULE_TIE, LAYER_AUTHORITY, CAP_EXCEEDED, or REASON_REQUIRED when negativeMarginOverride is true with no reason.ApiErrorResponse
  • 401
    UNAUTHENTICATED — missing or expired token.Show moreUNAUTHENTICATED — missing or expired token. Declared on every operation because `security` is declared globally at the document root: every route is authenticated, so every route can answer 401.
    ApiErrorResponse
  • 403
    AGENT_TIER_INSUFFICIENT, also 403, is a request whose agent tier does not allow the tool class; it carries nextAction verify_agent and details.tier, details.required, details.toolClass and…Show moreAGENT_TIER_INSUFFICIENT, also 403, is a request whose agent tier does not allow the tool class; it carries nextAction verify_agent and details.tier, details.required, details.toolClass and details.operationId. A ceiling only narrows an unverified caller and never widens a scope.
    ApiErrorResponse
  • 405
    VALIDATION — the public edge serves GET, POST, PUT, PATCH and DELETE only; any other method is refused before the platform sees it (details.reason METHOD_NOT_ALLOWED, details.source edge).Show moreVALIDATION — the public edge serves GET, POST, PUT, PATCH and DELETE only; any other method is refused before the platform sees it (details.reason METHOD_NOT_ALLOWED, details.source edge). Not retryable as sent.
    ApiErrorResponse
  • 409
    CONFLICT (stale baseVersion, no matching simulation, or a negative-margin simulation without an override — details.reason STALE_VERSION | SIMULATION_REQUIRED | NEGATIVE_MARGIN_OVERRIDE_REQUIRED) |…Show moreCONFLICT (stale baseVersion, no matching simulation, or a negative-margin simulation without an override — details.reason STALE_VERSION | SIMULATION_REQUIRED | NEGATIVE_MARGIN_OVERRIDE_REQUIRED) | IDEMPOTENCY_CONFLICT | IDEMPOTENCY_IN_PROGRESS
    ApiErrorResponse
  • 413
    VALIDATION — the request body is larger than the surface's limit.Show moreVALIDATION — the request body is larger than the surface's limit. Not retryable as sent: shrink the body. Declared on every operation that takes a request body. details carries exactly one key, maxBodyBytes (integer): the limit that applies to this surface, in bytes.
    ApiErrorResponse
  • 414
    VALIDATION — the request URI (path and query string) is longer than 8 KiB; the public edge refuses it before the platform sees it (details.reason URI_TOO_LONG, details.source edge).Show moreVALIDATION — the request URI (path and query string) is longer than 8 KiB; the public edge refuses it before the platform sees it (details.reason URI_TOO_LONG, details.source edge). Not retryable as sent: send long input in the body of a POST.
    ApiErrorResponse
  • 415
    VALIDATION — a request body that is not JSON (application/json or application/*+json; a form body only on the OAuth token routes).Show moreVALIDATION — a request body that is not JSON (application/json or application/*+json; a form body only on the OAuth token routes). The public edge refuses it before the platform sees it (details.reason UNSUPPORTED_MEDIA_TYPE, details.source edge). Not retryable as sent: send Content-Type application/json. Declared on every operation that takes a JSON request body.
    ApiErrorResponse
  • 500INTERNAL — a bug, and traceId is the support handle.ApiErrorResponse

Errors you should handle

Branch on code and honour retryable — never on the HTTP status alone.

400VALIDATION
Rules rule_tnt_htl_10pct and rule_tnt_htl_12pct tie at TENANT priority 100 with the same scope
not retryable
401UNAUTHENTICATED
The bearer token is expired. Re-authenticate and retry.
not retryable
403PERMISSION_DENIED
Role lacks the required scope: booking:write
not retryable
403TAB_DISABLED
Tenant acme-travel is not entitled to sell CRU
not retryable
403OUT_OF_SCOPE
The token's scope ladder does not reach this customer subtree
not retryable
403TENANT_MISMATCH
orderRef MO-8KD-2FQ-9XT does not belong to tenant acme-travel
not retryable
405VALIDATION
This method is not served.
not retryable
409CONFLICT
Simulation sim_9e31b4 priced 2 lines at a negative margin. Set negativeMarginOverride and give a reason to publish.
not retryable
409IDEMPOTENCY_CONFLICT
Idempotency-Key 7f0c33d1-9a1e-4d2c-9f77-1c0f2b3a4d55 was used with a different body; never executed
not retryable
409IDEMPOTENCY_IN_PROGRESS
A request with this Idempotency-Key is still executing
retryable
413VALIDATION
The request body is larger than this API accepts (262144 bytes).
not retryable
414VALIDATION
The request URI is longer than 8 KiB.
not retryable
415VALIDATION
Send application/json.
not retryable
500INTERNAL
An unexpected error occurred. Quote the traceId to support.
retryable