Attribute Types Reference

Version: 1.0.0

This document describes the seven attribute types supported by notifito, their wire formats, validation rules, and matching behavior.


Overview

notifito uses a closed set of seven attribute types. This set is shared by three consumers:

  1. Widget: Renders form inputs based on type
  2. Server-side validation: Validates submissions against type rules
  3. Matching engine: Compares subscription and event attributes

Adding an eighth type requires teaching all three consumers about it, so the set does not grow.


The Seven Types

1. enum

Single or multiple selection from a predefined list of options.

Wire Format (Scalar):

"42"

Wire Format (Multiple):

["41", "42"]

Definition:

{
    "key": "size",
    "label": "Size",
    "type": "enum",
    "options": ["40", "41", "42", "43"],
    "required": true,
    "matchable": true,
    "multiple": false
}

Validation Rules: - Must be one of the declared options - If multiple: true, must be an array of options - If multiple: false, must be a single string - Empty arrays are rejected

Matching Behavior: - Single: Exact equality - Multiple: Set intersection (at least one value matches)

Widget Rendering: - Single: <select> dropdown - Multiple: Multi-select or checkboxes

Examples:

// Single enum
{"size": "42"}

// Multiple enum
{"colors": ["red", "blue"]}

2. integer

Whole numbers with optional range constraints.

Wire Format (Scalar):

42

Wire Format (Interval):

{"min": 40, "max": 44}

Definition:

{
    "key": "guests",
    "label": "Number of Guests",
    "type": "integer",
    "required": true,
    "matchable": true
}

Validation Rules: - Must be a whole number (no decimals) - Strings are coerced to integers - Interval: min and max are optional (nullable) - Interval: min must not exceed max

Matching Behavior: - Scalar: Exact equality - Interval: Value falls within range (inclusive) - Open interval: {"min": null, "max": 4} matches anything ≤ 4 - Open interval: {"min": 2, "max": null} matches anything ≥ 2

Widget Rendering: - <input type="number" step="1">

Examples:

// Scalar
{"guests": 2}

// Interval
{"guests": {"min": 2, "max": 4}}

// Open interval
{"guests": {"min": null, "max": 4}}

3. decimal

Floating-point numbers with optional range constraints.

Wire Format (Scalar):

10.5

Wire Format (Interval):

{"min": 10.0, "max": 12.5}

Definition:

{
    "key": "price",
    "label": "Price",
    "type": "decimal",
    "required": true,
    "matchable": true
}

Validation Rules: - Must be numeric (integer or float) - Strings are coerced to floats - Interval: Same rules as integer

Matching Behavior: - Scalar: Exact equality - Interval: Value falls within range (inclusive)

Widget Rendering: - <input type="number" step="any">

Examples:

// Scalar
{"price": 10.5}

// Interval
{"price": {"min": 10.0, "max": 12.5}}

4. date

ISO 8601 date values.

Wire Format:

"2026-09-01"

Definition:

{
    "key": "appointment",
    "label": "Appointment Date",
    "type": "date",
    "required": true,
    "matchable": true
}

Validation Rules: - Must be ISO 8601 format: YYYY-MM-DD - Must be a valid date (e.g., 2026-02-30 is rejected) - Time component is not allowed

Matching Behavior: - Exact equality only - No range comparison (use date_range for ranges)

Widget Rendering: - <input type="date">

Examples:

{"appointment": "2026-09-01"}

5. date_range

Start and end dates representing a range.

Wire Format:

{
    "from": "2026-09-01",
    "to": "2026-09-05"
}

Definition:

{
    "key": "stay",
    "label": "Stay Dates",
    "type": "date_range",
    "required": true,
    "matchable": true
}

Validation Rules: - Both from and to must be ISO 8601 dates - from must not be after to - Either bound can be null (open-ended) - Bare date string is normalized to {"from": d, "to": d}

Matching Behavior: - Overlap: Ranges must overlap - Touching ranges (e.g., Sep 1-5 and Sep 5-10) match - Open-ended: {"from": null, "to": "2026-09-05"} matches anything ending before Sep 5

Widget Rendering: - Two date pickers (from and to)

Examples:

// Closed range
{"stay": {"from": "2026-09-01", "to": "2026-09-05"}}

// Open-ended
{"stay": {"from": "2026-09-01", "to": null}}

// Bare date (normalized)
{"stay": "2026-09-01"}

6. boolean

True/false values.

Wire Format:

true

Definition:

{
    "key": "gift_wrap",
    "label": "Gift Wrap",
    "type": "boolean",
    "required": false,
    "matchable": true
}

Validation Rules: - Must be true or false - Strings like "yes", "1", "true" are rejected - null is treated as absent (not a value)

Matching Behavior: - Exact equality: true matches true, false matches false

Widget Rendering: - <input type="checkbox">

Examples:

{"gift_wrap": true}

7. text

Free-text values with a maximum length.

Wire Format:

"Leave at door"

Definition:

{
    "key": "notes",
    "label": "Special Notes",
    "type": "text",
    "required": false,
    "matchable": false
}

Validation Rules: - Must be a string - Maximum 500 characters - null is treated as absent

Matching Behavior: - Exact equality (case-sensitive) - Typically matchable: false for free-text notes

Widget Rendering: - <input type="text" maxlength="500">

Examples:

{"notes": "Leave at door"}

Wire Format Summary

Type Scalar Form Interval Form Nullable
enum "42" No
enum (multiple) ["41", "42"] No
integer 42 {"min": 40, "max": 44} Yes (bounds)
decimal 10.5 {"min": 10, "max": 12.5} Yes (bounds)
date "2026-09-01" No
date_range {"from": "...", "to": "..."} Yes (bounds)
boolean true No
text "hello" No

Validation Rules Summary

Type Rules
enum Must be one of declared options
integer Must be whole number
decimal Must be numeric
date Must be ISO 8601 format (YYYY-MM-DD)
date_range Must have from/to dates, from ≤ to
boolean Must be true/false
text Max 500 characters

Matching Behavior Summary

Type Matching Rule
enum Exact equality (single) or set intersection (multiple)
integer Exact equality or range containment
decimal Exact equality or range containment
date Exact equality
date_range Range overlap
boolean Exact equality
text Exact equality (case-sensitive)

Wildcard Rules

This ensures sellers never under-notify due to missing attributes.


Schema Definition

Attribute Definition Structure

{
    "key": "size",
    "label": "Size",
    "type": "enum",
    "options": ["40", "41", "42"],
    "required": true,
    "matchable": true,
    "multiple": false
}
Field Type Required Description
key string Yes Lowercase snake_case identifier
label string Yes Display label
type string Yes One of the seven types
options array Conditional Required for enum type
required boolean No Default: false
matchable boolean No Default: true
multiple boolean No Default: false (enum only)

Key Rules


Examples by Industry

E-commerce (Sneaker Store)

[
    {
        "key": "size",
        "label": "Size",
        "type": "enum",
        "options": ["40", "41", "42", "43"],
        "required": true,
        "matchable": true,
        "multiple": false
    },
    {
        "key": "color",
        "label": "Color",
        "type": "enum",
        "options": ["red", "blue", "black"],
        "required": false,
        "matchable": true,
        "multiple": false
    }
]

Hospitality (Hotel)

[
    {
        "key": "stay",
        "label": "Stay Dates",
        "type": "date_range",
        "required": true,
        "matchable": true
    },
    {
        "key": "guests",
        "label": "Number of Guests",
        "type": "integer",
        "required": true,
        "matchable": true
    }
]

Healthcare (Clinic)

[
    {
        "key": "appointment",
        "label": "Appointment Date",
        "type": "date",
        "required": true,
        "matchable": true
    },
    {
        "key": "practitioner",
        "label": "Practitioner",
        "type": "enum",
        "options": ["Dr Ng", "Dr Okafor", "Any"],
        "required": false,
        "matchable": true
    }
]

Related Documentation