> ## Documentation Index
> Fetch the complete documentation index at: https://developer.hellgate.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Create ruleset

> Creates a new DRAFT ruleset. Version is assigned automatically. Lifecycle: DRAFT → ACTIVE. The ruleset binds exactly one (schema, version) at creation; rules validate against the bound schema — unresolved field paths reject with 422, backend rules are only accepted in rulesets bound to the built-in transaction schema, and bindings naming a deprecated or unknown schema version reject.



## OpenAPI

````yaml /products/specter/openapi.yaml post /api/admin/rulesets
openapi: 3.1.0
info:
  contact:
    email: support@hellgate.io
    name: Starfish GmbH & Co. KG
    url: https://hellgate.io/cpa/specter
  description: Composable decision engine and fraud prevention service.
  license:
    name: Hellgate API Terms
    url: https://hellgate.io/terms-and-conditions
  title: Specter API
  version: '1.0'
servers:
  - description: Managed instance of Specter
    url: https://{instance}.{env}.on-hellgate.cloud
    variables:
      instance:
        default: my-instance
        description: Your unique instance slug, provided during onboarding.
      env:
        default: eu1
        description: Deployment environment (currently eu1).
security: []
tags:
  - description: Evaluate transactions and retrieve decision results.
    name: Decisions
  - description: Close decisions that were flagged for manual review.
    name: Resolutions
  - description: Report payment lifecycle events for a prior decision.
    name: Lifecycle Events
  - description: Manage rulesets and their activation lifecycle.
    name: Rulesets
  - description: Register and version custom decision-payload schemas.
    name: Schemas
  - description: Configure interceptors and intercept live payment requests.
    name: Interceptors
  - description: Subscribe to decision and event notifications.
    name: Webhooks
  - description: Manage blocked field values.
    name: Blacklist
paths:
  /api/admin/rulesets:
    post:
      tags:
        - Rulesets
      summary: Create ruleset
      description: >-
        Creates a new DRAFT ruleset. Version is assigned automatically.
        Lifecycle: DRAFT → ACTIVE. The ruleset binds exactly one (schema,
        version) at creation; rules validate against the bound schema —
        unresolved field paths reject with 422, backend rules are only accepted
        in rulesets bound to the built-in transaction schema, and bindings
        naming a deprecated or unknown schema version reject.
      operationId: admin_rulesets_create
      parameters: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateRulesetRequest'
        description: Ruleset attributes
        required: true
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Ruleset'
          description: Created ruleset
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Unauthorized'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Forbidden'
          description: Forbidden
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrors'
          description: Validation errors
      callbacks: {}
      security:
        - bearerAuth: []
components:
  schemas:
    CreateRulesetRequest:
      properties:
        context:
          description: Ruleset context key used for routing
          example: checkout
          type: string
        created_by:
          example: ops@example.com
          type: string
        description:
          example: Standard checkout rules
          type: string
        rules:
          description: Initial rule definitions (can also be added via PATCH while DRAFT)
          items:
            $ref: '#/components/schemas/RuleInput'
          type: array
        schema:
          $ref: '#/components/schemas/SchemaBinding'
      required:
        - context
        - schema
      title: CreateRulesetRequest
      type: object
    Ruleset:
      properties:
        id:
          example: 6c1f4e8b-9a2d-4c7e-b5f3-8d1a6e9c4b2f
          format: uuid
          type: string
        activated_at:
          example: '2026-05-15T08:00:00Z'
          format: date-time
          type:
            - string
            - 'null'
        context:
          example: checkout
          type: string
        created_at:
          example: '2026-05-14T16:20:00Z'
          format: date-time
          type: string
        created_by:
          example: ops@example.com
          type:
            - string
            - 'null'
        description:
          example: Block USD transactions over limit
          type:
            - string
            - 'null'
        rules:
          description: Rule definitions evaluated in array order
          items:
            $ref: '#/components/schemas/Rule'
          type: array
        schema:
          $ref: '#/components/schemas/SchemaBinding'
        status:
          enum:
            - DRAFT
            - ACTIVE
            - INACTIVE
          type: string
        version:
          example: 1
          type: integer
      title: Ruleset
      type: object
    Unauthorized:
      description: No valid authentication was provided.
      example:
        classifier: UNAUTHORIZED
        code: 401
        message: No valid means of authentication was provided
      properties:
        classifier:
          enum:
            - UNAUTHORIZED
          type: string
        code:
          enum:
            - 401
          type: integer
        message:
          type: string
      required:
        - classifier
        - code
        - message
      title: Unauthorized
      type: object
    Forbidden:
      description: The token lacks the scope required for this operation.
      example:
        classifier: FORBIDDEN
        code: 403
        message: Not allowed to access this resource or feature
      properties:
        classifier:
          enum:
            - FORBIDDEN
          type: string
        code:
          enum:
            - 403
          type: integer
        message:
          type: string
      required:
        - classifier
        - code
        - message
      title: Forbidden
      type: object
    ValidationErrors:
      description: Response shape for request validation failures
      example:
        classifier: VALIDATION_ERROR
        code: 422
        validation_errors:
          - message: must be a positive integer
            path: limit
      properties:
        classifier:
          example: VALIDATION_ERROR
          type: string
        code:
          example: 422
          type: integer
        validation_errors:
          items:
            properties:
              message:
                example: must be a positive integer
                type: string
              path:
                example: limit
                type: string
            type: object
          type: array
      required:
        - classifier
        - code
        - validation_errors
      title: ValidationErrors
      type: object
    RuleInput:
      properties:
        id:
          description: >-
            Client-assigned rule identifier. Used in triggered-rule and
            backend-result entries.
          example: r1
          type: string
        action:
          description: >-
            Required for condition rules. Backend rules derive their action from
            the adapter response.
          enum:
            - BLOCK
            - REVIEW
          type: string
        async:
          example: true
          description: >-
            When `true`, this backend or backend_group rule runs asynchronously
            after the synchronous response is returned. Only valid on `backend`
            and `backend_group` rules. A sync-phase ALLOW with async rules
            becomes PROVISIONAL until all async rules complete.
          type:
            - boolean
            - 'null'
        backend:
          description: >-
            Backend adapter key (backend rules only). Must match a configured
            adapter.
          example: vdm
          type: string
        condition:
          description: >-
            Condition expression tree (condition rules only). Logical: `{op:
            and|or, exprs: [...]}`, `{op: not, expr: {...}}`. Comparison: `{op:
            eq|neq|lt|lte|gt|gte, left: operand, right: operand}`. Set: `{op:
            in|not_in, left: operand, right: operand}`. Velocity: `{op:
            velocity, field: "$.path", threshold: N, window_seconds: N}`. Every
            operand is an object, never a bare string: a field reference is
            `{path: "$.…"}` (must start with `$.`), a literal is `{value: …}`.
            Either form is valid on either side, so field-to-field comparison
            works. The discriminated form `{type: "json_path", path: …}` /
            `{type: "const", value: …}` is also accepted and normalises to the
            short form on read. Derivation: `{op: hmac, fields: ["$.path |
            filter()", ...]}` — an ordered list of 1..16 filtered field
            references (soft-warn at 8), emitting a deterministic HMAC-SHA256
            fingerprint under the single per-instance secret; usable wherever a
            field reference is. The operator applies no canonicalization of its
            own — the author expresses it per input via filter pipes; identical
            (operator, ordered field list, filter chains) always produce
            identical fingerprints. HMAC outputs are any-scoped by definition.
            An empty fields list, more than 16 inputs, or any pci-sad-scoped
            input rejects at submission with 422. Field references are JSON path
            strings starting with `$.`, optionally followed by an inline filter
            pipe chain (`$.customer.email | trim() | downcase() | domain()`),
            valid wherever a field path appears in the grammar (comparison
            operands, velocity field, HMAC inputs). Closed v1 filter set:
            `downcase()`, `upcase()`, `trim()` (strips whitespace and trailing
            dots), `idn_ascii()` (IDN label to punycode ASCII; string input),
            and `domain()` (requires an email-typed input per the bound schema;
            emits the canonical registrable-domain form — eTLD+1 per the bundled
            Public Suffix List, lowercase, punycode A-label, no trailing dot;
            display-name and plus-addressed mailboxes parse, group syntax emits
            absent). Filter type constraints are checked at rule submission
            against the bound schema's declared field types and compose left to
            right (the output type of one filter is the input constraint of the
            next); mismatches reject with 422 naming the offending operand and
            its declared type. At decision time a filter receiving an absent or
            malformed value emits absent and the enclosing predicate abstains
            (absent-attribute fail-skip). Filtered values inherit the strictest
            scope marker of their chain's inputs. Scope constraints at
            submission — a pci-sad-scoped field cannot be the velocity field
            (nothing that persists a SAD derivative may reference one; HMAC
            inputs already reject pci-sad), and predicate references to
            pci-sad-scoped fields are accepted only on SAQ-D / RoC instances
            (sub-tier instances reject with 422), evaluating at decision time
            only. Array-typed fields (e.g. the credential schemes attribute)
            take membership via in — comparing a string operand against an
            array-typed field rejects at submission with 422 (type mismatch).
          type: object
        description:
          example: Escalate to the risk backend
          type:
            - string
            - 'null'
        enabled:
          example: true
          type: boolean
        name:
          example: Block USD
          type: string
        on_error:
          description: >-
            Required for backend rules. `block` — fail-closed (BLOCK on adapter
            error). `allow` — fail-open (continue evaluation).
          enum:
            - block
            - allow
          type: string
        type:
          description: >-
            `condition` — evaluated locally. `backend` — delegates to an
            external adapter.
          enum:
            - condition
            - backend
          type: string
      required:
        - type
      title: RuleInput
      type: object
    SchemaBinding:
      description: >-
        A ruleset's declared (schema, version) pair. name references a registry
        entry; version is required for custom schemas and absent for built-ins,
        whose version is implicit and advances only via Specter releases. Set at
        ruleset creation and immutable for the life of that ruleset version —
        rebinding a context means publishing a new ruleset version with the new
        binding and activating it. Rulesets that predate the registry surface
        the launch-backfilled transaction binding.
      properties:
        name:
          example: transaction
          type: string
        version:
          description: Registry version for custom schemas. Absent for built-in schemas.
          example: 1
          type:
            - integer
            - 'null'
      required:
        - name
      title: SchemaBinding
      type: object
    Rule:
      properties:
        id:
          example: r1
          type:
            - string
            - 'null'
        action:
          description: >-
            Required for condition rules. Backend rules derive their action from
            the adapter response.
          enum:
            - BLOCK
            - REVIEW
          type: string
        async:
          example: true
          description: >-
            When `true`, this backend or backend_group rule is executed
            asynchronously after the synchronous response is returned. Only
            applies to `backend` and `backend_group` rule types. A sync-phase
            ALLOW with async rules present is returned as PROVISIONAL.
          type:
            - boolean
            - 'null'
        backend:
          description: >-
            Backend adapter key (backend rules only). Must match a configured
            adapter.
          example: vdm
          type: string
        condition:
          description: >-
            Condition expression tree (condition rules only). Logical: `{op:
            and|or, exprs: [...]}`, `{op: not, expr: {...}}`. Comparison: `{op:
            eq|neq|lt|lte|gt|gte, left: operand, right: operand}`. Set: `{op:
            in|not_in, left: operand, right: operand}`. Velocity: `{op:
            velocity, field: "$.path", threshold: N, window_seconds: N}`. Every
            operand is an object, never a bare string: a field reference is
            `{path: "$.…"}` (must start with `$.`), a literal is `{value: …}`.
            Either form is valid on either side, so field-to-field comparison
            works. The discriminated form `{type: "json_path", path: …}` /
            `{type: "const", value: …}` is also accepted and normalises to the
            short form on read. Derivation: `{op: hmac, fields: ["$.path |
            filter()", ...]}` — an ordered list of 1..16 filtered field
            references (soft-warn at 8), emitting a deterministic HMAC-SHA256
            fingerprint under the single per-instance secret; usable wherever a
            field reference is. The operator applies no canonicalization of its
            own — the author expresses it per input via filter pipes; identical
            (operator, ordered field list, filter chains) always produce
            identical fingerprints. HMAC outputs are any-scoped by definition.
            An empty fields list, more than 16 inputs, or any pci-sad-scoped
            input rejects at submission with 422. Field references are JSON path
            strings starting with `$.`, optionally followed by an inline filter
            pipe chain (`$.customer.email | trim() | downcase() | domain()`),
            valid wherever a field path appears in the grammar (comparison
            operands, velocity field, HMAC inputs). Closed v1 filter set:
            `downcase()`, `upcase()`, `trim()` (strips whitespace and trailing
            dots), `idn_ascii()` (IDN label to punycode ASCII; string input),
            and `domain()` (requires an email-typed input per the bound schema;
            emits the canonical registrable-domain form — eTLD+1 per the bundled
            Public Suffix List, lowercase, punycode A-label, no trailing dot;
            display-name and plus-addressed mailboxes parse, group syntax emits
            absent). Filter type constraints are checked at rule submission
            against the bound schema's declared field types and compose left to
            right (the output type of one filter is the input constraint of the
            next); mismatches reject with 422 naming the offending operand and
            its declared type. At decision time a filter receiving an absent or
            malformed value emits absent and the enclosing predicate abstains
            (absent-attribute fail-skip). Filtered values inherit the strictest
            scope marker of their chain's inputs. Scope constraints at
            submission — a pci-sad-scoped field cannot be the velocity field
            (nothing that persists a SAD derivative may reference one; HMAC
            inputs already reject pci-sad), and predicate references to
            pci-sad-scoped fields are accepted only on SAQ-D / RoC instances
            (sub-tier instances reject with 422), evaluating at decision time
            only. Array-typed fields (e.g. the credential schemes attribute)
            take membership via in — comparing a string operand against an
            array-typed field rejects at submission with 422 (type mismatch).
          type: object
        description:
          example: Escalate to the risk backend
          type:
            - string
            - 'null'
        enabled:
          example: true
          type: boolean
        fields:
          example:
            - $.device.ip
          description: >-
            JSON path fields to match against the blacklist (blacklist rules
            only). All fields must match for a BLOCK to be triggered.
          items:
            type: string
          type:
            - array
            - 'null'
        live:
          example: true
          description: >-
            Whether the backend runs live (true) or in shadow mode (false).
            Present on backend rules and on backend_group members.
          type:
            - boolean
            - 'null'
        members:
          example:
            - vdm
          description: Backend members of the group (backend_group rules only).
          items:
            properties:
              backend:
                example: vdm
                type: string
              live:
                example: true
                type: boolean
              weight:
                description: Relative weight for the split strategy.
                example: 60
                type: integer
            type: object
          type:
            - array
            - 'null'
        merge:
          description: How parallel member decisions are merged (backend_group rules only).
          enum:
            - strictest
            - most_lenient
            - consensus
          type:
            - string
            - 'null'
        name:
          example: Block USD
          type:
            - string
            - 'null'
        on_error:
          description: >-
            Error policy for backend and backend_group rules. `allow` —
            fail-open (continue evaluation). `block` — fail-closed (BLOCK on
            error). `review` — REVIEW on error.
          enum:
            - allow
            - block
            - review
          type: string
        populate_on:
          example:
            - fraud_report
            - chargeback
          description: >-
            Event types that trigger blacklist population for this rule.
            Defaults to `["fraud_report"]` if omitted.
          items:
            enum:
              - fraud_report
              - chargeback
              - failed
            type: string
          type:
            - array
            - 'null'
        strategy:
          description: >-
            Member execution strategy (backend_group rules only). `fallback` —
            try members in order until one succeeds. `parallel` — run all
            members and merge. `split` — weighted A/B routing.
          enum:
            - fallback
            - parallel
            - split
          type:
            - string
            - 'null'
        ttl_seconds:
          example: 86400
          description: >-
            TTL in seconds for blacklist entries created by this rule. If
            omitted, entries never expire.
          type:
            - integer
            - 'null'
        type:
          description: >-
            `condition` — evaluated locally. `backend` — delegates to an
            external adapter. `blacklist` — blocks if all specified fields match
            an active blacklist entry. `backend_group` — runs several backends
            together under a strategy.
          enum:
            - condition
            - backend
            - blacklist
            - backend_group
          type: string
      required:
        - enabled
        - type
      title: Rule
      type: object
  securitySchemes:
    bearerAuth:
      bearerFormat: JWT
      description: >-
        HS256-signed JWT bearer token, obtained via the OAuth2
        client-credentials grant (see Authentication).
      scheme: bearer
      type: http

````