{
  "components": {
    "headers": {
      "Deprecation": {
        "description": "Present only when this API version is deprecated. RFC 9745 structured field Date: seconds since the epoch, prefixed with @.",
        "example": "@1767225600",
        "schema": {
          "type": "string"
        }
      },
      "RateLimitLimit": {
        "description": "Requests allowed in the current window.",
        "example": 300,
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitPolicy": {
        "description": "The policy in force, as quota;w=window-in-seconds.",
        "example": "300;w=60",
        "schema": {
          "type": "string"
        }
      },
      "RateLimitRemaining": {
        "description": "Requests still allowed in the current window.",
        "example": 297,
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitReset": {
        "description": "Seconds until the current window resets.",
        "example": 41,
        "schema": {
          "type": "integer"
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying.",
        "example": 41,
        "schema": {
          "type": "integer"
        }
      },
      "Sunset": {
        "description": "Present only when this API version has a retirement date. RFC 8594 HTTP-date, after which the version returns 410.",
        "example": "Fri, 01 Jan 2027 00:00:00 GMT",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "RateLimited": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "description": "Rate limit exceeded. Wait for Retry-After seconds and retry.",
        "headers": {
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimitPolicy"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          },
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        }
      },
      "VersionSunset": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "description": "This API version was retired and no longer serves requests. Move to the current version.",
        "headers": {
          "Deprecation": {
            "$ref": "#/components/headers/Deprecation"
          },
          "Sunset": {
            "$ref": "#/components/headers/Sunset"
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "additionalProperties": true,
        "description": "A JSON error payload. Agents should read `error` for a human readable summary and `errors` for per field validation messages when present.",
        "properties": {
          "error": {
            "description": "Human readable description of what went wrong.",
            "type": "string"
          },
          "errors": {
            "description": "Validation messages, either a list of strings or an object keyed by field name.",
            "oneOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "additionalProperties": {
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                },
                "type": "object"
              }
            ]
          }
        },
        "title": "Error",
        "type": "object"
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "description": "API token from https://app.tryleal.dev/api_tokens, sent as `Authorization: Bearer <token>`.",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "externalDocs": {
    "description": "Human readable API documentation",
    "url": "https://app.tryleal.dev/docs/api.html"
  },
  "info": {
    "contact": {
      "name": "Leal support",
      "url": "https://www.tryleal.dev/contact"
    },
    "description": "Leal is a wallet based loyalty platform for local businesses. This API manages stores (accounts), loyalty stamp cards, rewards, customers, customer cards, locations and signup posters.\n\nAuthenticate with an API token issued at https://app.tryleal.dev/api_tokens, sent as `Authorization: Bearer <token>`. Request and response bodies are JSON, and so are errors: every failure carries an `error` message, and validation failures add an `errors` object keyed by field name.\n\nEvery response carries `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset` and `RateLimit-Policy`. The limit is 300 requests per minute per API token, counted per IP address for unauthenticated requests. Exceeding it returns 429 with `Retry-After` in seconds. `GET /api/v1/status` is public and needs no token, so you can read the headers before you authenticate.\n\nThe version is in the URL and `v1` is current. A version that is being retired sends the `Deprecation` (RFC 9745) and `Sunset` (RFC 8594) headers on every response, with at least 12 months between them, and returns 410 once the sunset date passes.\n\nSee https://www.tryleal.dev/developers for the full developer guide, and https://www.tryleal.dev/developers#versioning for the versioning and deprecation policy.",
    "license": {
      "name": "Proprietary",
      "url": "https://www.tryleal.dev/terms"
    },
    "termsOfService": "https://www.tryleal.dev/terms",
    "title": "Leal API",
    "version": "v1",
    "x-copyright": null
  },
  "openapi": "3.0.3",
  "paths": {
    "/api/v1/accounts": {
      "get": {
        "description": "Returns every store the authenticated user has access to, including summary counts for locations, cards, customers, and posters.",
        "operationId": "get_api_v1_accounts",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "additionalProperties": false,
                    "properties": {
                      "cards_count": {
                        "description": "Number of loyalty card templates",
                        "type": "integer"
                      },
                      "created_at": {
                        "description": "ISO 8601 creation timestamp",
                        "type": "string"
                      },
                      "customers_count": {
                        "description": "Number of enrolled customers",
                        "type": "integer"
                      },
                      "display_store_name": {
                        "description": "Resolved display name (store_name if present, otherwise name)",
                        "type": "string"
                      },
                      "id": {
                        "description": "Unique store ID",
                        "type": "integer"
                      },
                      "locations_count": {
                        "description": "Number of physical locations",
                        "type": "integer"
                      },
                      "name": {
                        "description": "Internal account name",
                        "type": "string"
                      },
                      "personal": {
                        "description": "Whether this is the user's personal account",
                        "type": "boolean"
                      },
                      "posters_count": {
                        "description": "Number of QR signup posters",
                        "type": "integer"
                      },
                      "store_name": {
                        "description": "Public-facing store name",
                        "type": "string"
                      },
                      "updated_at": {
                        "description": "ISO 8601 last-update timestamp",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "name",
                      "store_name",
                      "display_store_name",
                      "personal",
                      "locations_count",
                      "cards_count",
                      "customers_count",
                      "posters_count",
                      "created_at",
                      "updated_at"
                    ],
                    "type": "object"
                  },
                  "type": "array"
                }
              }
            },
            "description": "An array of store objects",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "List all stores",
        "tags": [
          "Stores"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/cards": {
      "get": {
        "description": "Returns loyalty card templates for the specified store. By default, only\nactive (unarchived) cards are returned. Use the `scope` parameter to include\narchived cards.\n",
        "operationId": "get_api_v1_accounts_account_id_cards",
        "parameters": [
          {
            "description": "Parent store ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Filter cards by archive status. Default: active only.",
            "in": "query",
            "name": "scope",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "additionalProperties": false,
                    "properties": {
                      "archived_at": {
                        "description": "ISO 8601 timestamp when the card was archived, or null if active",
                        "type": "string"
                      },
                      "auxiliary_fields": {
                        "description": "Up to two extra front-of-pass fields",
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      "card_color": {
                        "description": "Hex colour for the card background (e.g. '#6B4226')",
                        "type": "string"
                      },
                      "created_at": {
                        "description": "ISO 8601 creation timestamp",
                        "type": "string"
                      },
                      "customer_cards_count": {
                        "description": "Number of customer card instances issued",
                        "type": "integer"
                      },
                      "expires_at": {
                        "description": "ISO 8601 timestamp when the card expires, or null if it does not expire",
                        "type": "string"
                      },
                      "header_text": {
                        "description": "Optional header text displayed on the card",
                        "type": "string"
                      },
                      "id": {
                        "description": "Unique card ID",
                        "type": "integer"
                      },
                      "initial_stamps": {
                        "description": "Number of stamps pre-filled on new customer cards (0 to stamps_required - 1)",
                        "type": "integer"
                      },
                      "name": {
                        "description": "Card name (e.g. 'Coffee Loyalty Card')",
                        "type": "string"
                      },
                      "rewards_count": {
                        "description": "Number of rewards defined for this card",
                        "type": "integer"
                      },
                      "show_member_field": {
                        "description": "Whether wallet passes show the member name field",
                        "type": "boolean"
                      },
                      "show_stamps_to_reward_field": {
                        "description": "Whether wallet passes show the stamps-to-reward field",
                        "type": "boolean"
                      },
                      "stamp_background_color": {
                        "description": "Hex colour for stamp backgrounds",
                        "type": "string"
                      },
                      "stamp_color": {
                        "description": "Hex colour for stamp icons",
                        "type": "string"
                      },
                      "stamp_icon": {
                        "description": "Icon used for stamps (e.g. 'coffee', 'heart', 'star')",
                        "type": "string"
                      },
                      "stamps_required": {
                        "description": "Number of stamps needed to complete the card (1–21)",
                        "type": "integer"
                      },
                      "strip_color": {
                        "description": "Hex colour for the strip (when strip_type is 'color')",
                        "type": "string"
                      },
                      "strip_opacity": {
                        "description": "Opacity (0–100) of the strip background over the card colour, for a colour, an uploaded image or a preset alike. 100 renders the colour or image exactly as supplied; lower values let the card colour show through",
                        "type": "number"
                      },
                      "strip_preset": {
                        "description": "Preset strip image identifier (when strip_type is 'preset')",
                        "type": "string"
                      },
                      "strip_type": {
                        "description": "Strip image type: 'color', 'image', or 'preset'",
                        "type": "string"
                      },
                      "text_color": {
                        "description": "Hex colour for card text",
                        "type": "string"
                      },
                      "updated_at": {
                        "description": "ISO 8601 last-update timestamp",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "name",
                      "card_color",
                      "text_color",
                      "stamp_icon",
                      "stamp_color",
                      "stamp_background_color",
                      "stamps_required",
                      "initial_stamps",
                      "show_member_field",
                      "show_stamps_to_reward_field",
                      "auxiliary_fields",
                      "strip_type",
                      "strip_color",
                      "strip_opacity",
                      "strip_preset",
                      "header_text",
                      "expires_at",
                      "archived_at",
                      "rewards_count",
                      "customer_cards_count",
                      "created_at",
                      "updated_at"
                    ],
                    "type": "object"
                  },
                  "type": "array"
                }
              }
            },
            "description": "An array of card objects",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store not found or not accessible"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "List loyalty cards",
        "tags": [
          "Cards"
        ]
      },
      "post": {
        "description": "Creates a new loyalty stamp card template for the store. The card defines the\nvisual design (colours, icon, strip) and program rules (stamps required,\ninitial stamps).\n",
        "operationId": "post_api_v1_accounts_account_id_cards",
        "parameters": [
          {
            "description": "Parent store ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "card": {
                    "additionalProperties": false,
                    "properties": {
                      "auxiliary_fields": {
                        "description": "Up to two extra front-of-pass fields. Blank values are ignored.",
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      "card_color": {
                        "description": "Hex colour for the card background (e.g. '#6B4226')",
                        "type": "string"
                      },
                      "expires_at": {
                        "description": "Card expiry timestamp (ISO 8601)",
                        "type": "string"
                      },
                      "header_text": {
                        "description": "Optional header text displayed on the card",
                        "type": "string"
                      },
                      "initial_stamps": {
                        "description": "Number of stamps pre-filled on new customer cards (must be >= 0 and < stamps_required)",
                        "type": "integer"
                      },
                      "name": {
                        "description": "Card name (e.g. 'Coffee Loyalty Card')",
                        "type": "string"
                      },
                      "show_member_field": {
                        "description": "Whether wallet passes show the member name field",
                        "type": "boolean"
                      },
                      "show_stamps_to_reward_field": {
                        "description": "Whether wallet passes show the stamps-to-reward field",
                        "type": "boolean"
                      },
                      "stamp_background_color": {
                        "description": "Hex colour for stamp backgrounds",
                        "type": "string"
                      },
                      "stamp_color": {
                        "description": "Hex colour for stamp icons",
                        "type": "string"
                      },
                      "stamp_icon": {
                        "description": "Stamp icon identifier",
                        "type": "string"
                      },
                      "stamps_required": {
                        "description": "Number of stamps needed to complete the card (1–21)",
                        "type": "integer"
                      },
                      "strip_color": {
                        "description": "Hex colour for the strip (used when strip_type is 'color')",
                        "type": "string"
                      },
                      "strip_opacity": {
                        "description": "Opacity (0–100) of the strip background over the card colour. Defaults to 100, which renders the colour or image exactly as supplied",
                        "type": "number"
                      },
                      "strip_preset": {
                        "description": "Preset strip image identifier (used when strip_type is 'preset')",
                        "type": "string"
                      },
                      "strip_type": {
                        "description": "Strip image type",
                        "type": "string"
                      },
                      "text_color": {
                        "description": "Hex colour for card text",
                        "type": "string"
                      }
                    },
                    "required": [
                      "name"
                    ],
                    "type": "object"
                  }
                },
                "required": [
                  "card"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "archived_at": {
                      "description": "ISO 8601 timestamp when the card was archived, or null if active",
                      "type": "string"
                    },
                    "auxiliary_fields": {
                      "description": "Up to two extra front-of-pass fields",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "card_color": {
                      "description": "Hex colour for the card background (e.g. '#6B4226')",
                      "type": "string"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "customer_cards_count": {
                      "description": "Number of customer card instances issued",
                      "type": "integer"
                    },
                    "expires_at": {
                      "description": "ISO 8601 timestamp when the card expires, or null if it does not expire",
                      "type": "string"
                    },
                    "header_text": {
                      "description": "Optional header text displayed on the card",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique card ID",
                      "type": "integer"
                    },
                    "initial_stamps": {
                      "description": "Number of stamps pre-filled on new customer cards (0 to stamps_required - 1)",
                      "type": "integer"
                    },
                    "name": {
                      "description": "Card name (e.g. 'Coffee Loyalty Card')",
                      "type": "string"
                    },
                    "rewards_count": {
                      "description": "Number of rewards defined for this card",
                      "type": "integer"
                    },
                    "show_member_field": {
                      "description": "Whether wallet passes show the member name field",
                      "type": "boolean"
                    },
                    "show_stamps_to_reward_field": {
                      "description": "Whether wallet passes show the stamps-to-reward field",
                      "type": "boolean"
                    },
                    "stamp_background_color": {
                      "description": "Hex colour for stamp backgrounds",
                      "type": "string"
                    },
                    "stamp_color": {
                      "description": "Hex colour for stamp icons",
                      "type": "string"
                    },
                    "stamp_icon": {
                      "description": "Icon used for stamps (e.g. 'coffee', 'heart', 'star')",
                      "type": "string"
                    },
                    "stamps_required": {
                      "description": "Number of stamps needed to complete the card (1–21)",
                      "type": "integer"
                    },
                    "strip_color": {
                      "description": "Hex colour for the strip (when strip_type is 'color')",
                      "type": "string"
                    },
                    "strip_opacity": {
                      "description": "Opacity (0–100) of the strip background over the card colour, for a colour, an uploaded image or a preset alike. 100 renders the colour or image exactly as supplied; lower values let the card colour show through",
                      "type": "number"
                    },
                    "strip_preset": {
                      "description": "Preset strip image identifier (when strip_type is 'preset')",
                      "type": "string"
                    },
                    "strip_type": {
                      "description": "Strip image type: 'color', 'image', or 'preset'",
                      "type": "string"
                    },
                    "text_color": {
                      "description": "Hex colour for card text",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "card_color",
                    "text_color",
                    "stamp_icon",
                    "stamp_color",
                    "stamp_background_color",
                    "stamps_required",
                    "initial_stamps",
                    "show_member_field",
                    "show_stamps_to_reward_field",
                    "auxiliary_fields",
                    "strip_type",
                    "strip_color",
                    "strip_opacity",
                    "strip_preset",
                    "header_text",
                    "expires_at",
                    "archived_at",
                    "rewards_count",
                    "customer_cards_count",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The newly created card object",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store not found or not accessible"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Validation failed – check the `errors` object for details"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Create a loyalty card",
        "tags": [
          "Cards"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/cards/{id}": {
      "get": {
        "description": "Returns a single loyalty card template by ID, including reward and customer card counts.",
        "operationId": "get_api_v1_accounts_account_id_cards_id",
        "parameters": [
          {
            "description": "Parent store ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Card ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "archived_at": {
                      "description": "ISO 8601 timestamp when the card was archived, or null if active",
                      "type": "string"
                    },
                    "auxiliary_fields": {
                      "description": "Up to two extra front-of-pass fields",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "card_color": {
                      "description": "Hex colour for the card background (e.g. '#6B4226')",
                      "type": "string"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "customer_cards_count": {
                      "description": "Number of customer card instances issued",
                      "type": "integer"
                    },
                    "expires_at": {
                      "description": "ISO 8601 timestamp when the card expires, or null if it does not expire",
                      "type": "string"
                    },
                    "header_text": {
                      "description": "Optional header text displayed on the card",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique card ID",
                      "type": "integer"
                    },
                    "initial_stamps": {
                      "description": "Number of stamps pre-filled on new customer cards (0 to stamps_required - 1)",
                      "type": "integer"
                    },
                    "name": {
                      "description": "Card name (e.g. 'Coffee Loyalty Card')",
                      "type": "string"
                    },
                    "rewards_count": {
                      "description": "Number of rewards defined for this card",
                      "type": "integer"
                    },
                    "show_member_field": {
                      "description": "Whether wallet passes show the member name field",
                      "type": "boolean"
                    },
                    "show_stamps_to_reward_field": {
                      "description": "Whether wallet passes show the stamps-to-reward field",
                      "type": "boolean"
                    },
                    "stamp_background_color": {
                      "description": "Hex colour for stamp backgrounds",
                      "type": "string"
                    },
                    "stamp_color": {
                      "description": "Hex colour for stamp icons",
                      "type": "string"
                    },
                    "stamp_icon": {
                      "description": "Icon used for stamps (e.g. 'coffee', 'heart', 'star')",
                      "type": "string"
                    },
                    "stamps_required": {
                      "description": "Number of stamps needed to complete the card (1–21)",
                      "type": "integer"
                    },
                    "strip_color": {
                      "description": "Hex colour for the strip (when strip_type is 'color')",
                      "type": "string"
                    },
                    "strip_opacity": {
                      "description": "Opacity (0–100) of the strip background over the card colour, for a colour, an uploaded image or a preset alike. 100 renders the colour or image exactly as supplied; lower values let the card colour show through",
                      "type": "number"
                    },
                    "strip_preset": {
                      "description": "Preset strip image identifier (when strip_type is 'preset')",
                      "type": "string"
                    },
                    "strip_type": {
                      "description": "Strip image type: 'color', 'image', or 'preset'",
                      "type": "string"
                    },
                    "text_color": {
                      "description": "Hex colour for card text",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "card_color",
                    "text_color",
                    "stamp_icon",
                    "stamp_color",
                    "stamp_background_color",
                    "stamps_required",
                    "initial_stamps",
                    "show_member_field",
                    "show_stamps_to_reward_field",
                    "auxiliary_fields",
                    "strip_type",
                    "strip_color",
                    "strip_opacity",
                    "strip_preset",
                    "header_text",
                    "expires_at",
                    "archived_at",
                    "rewards_count",
                    "customer_cards_count",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A card object",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Card not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Show a loyalty card",
        "tags": [
          "Cards"
        ]
      },
      "patch": {
        "description": "Updates an existing loyalty card template. Only the provided attributes are changed.",
        "operationId": "patch_api_v1_accounts_account_id_cards_id",
        "parameters": [
          {
            "description": "Parent store ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Card ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "card": {
                    "additionalProperties": false,
                    "properties": {
                      "auxiliary_fields": {
                        "description": "Up to two extra front-of-pass fields. Blank values are ignored.",
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      "card_color": {
                        "description": "Hex colour for the card background",
                        "type": "string"
                      },
                      "expires_at": {
                        "description": "Card expiry timestamp (ISO 8601)",
                        "type": "string"
                      },
                      "header_text": {
                        "description": "Optional header text displayed on the card",
                        "type": "string"
                      },
                      "initial_stamps": {
                        "description": "Pre-filled stamps (must be >= 0 and < stamps_required)",
                        "type": "integer"
                      },
                      "name": {
                        "description": "Card name",
                        "type": "string"
                      },
                      "show_member_field": {
                        "description": "Whether wallet passes show the member name field",
                        "type": "boolean"
                      },
                      "show_stamps_to_reward_field": {
                        "description": "Whether wallet passes show the stamps-to-reward field",
                        "type": "boolean"
                      },
                      "stamp_background_color": {
                        "description": "Hex colour for stamp backgrounds",
                        "type": "string"
                      },
                      "stamp_color": {
                        "description": "Hex colour for stamp icons",
                        "type": "string"
                      },
                      "stamp_icon": {
                        "description": "Stamp icon identifier",
                        "type": "string"
                      },
                      "stamps_required": {
                        "description": "Number of stamps needed (1–21)",
                        "type": "integer"
                      },
                      "strip_color": {
                        "description": "Hex colour for the strip",
                        "type": "string"
                      },
                      "strip_opacity": {
                        "description": "Opacity (0–100) of the strip background over the card colour. 100 renders the colour or image exactly as supplied",
                        "type": "number"
                      },
                      "strip_preset": {
                        "description": "Preset strip image identifier",
                        "type": "string"
                      },
                      "strip_type": {
                        "description": "Strip image type",
                        "type": "string"
                      },
                      "text_color": {
                        "description": "Hex colour for card text",
                        "type": "string"
                      }
                    },
                    "type": "object"
                  }
                },
                "required": [
                  "card"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "archived_at": {
                      "description": "ISO 8601 timestamp when the card was archived, or null if active",
                      "type": "string"
                    },
                    "auxiliary_fields": {
                      "description": "Up to two extra front-of-pass fields",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "card_color": {
                      "description": "Hex colour for the card background (e.g. '#6B4226')",
                      "type": "string"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "customer_cards_count": {
                      "description": "Number of customer card instances issued",
                      "type": "integer"
                    },
                    "expires_at": {
                      "description": "ISO 8601 timestamp when the card expires, or null if it does not expire",
                      "type": "string"
                    },
                    "header_text": {
                      "description": "Optional header text displayed on the card",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique card ID",
                      "type": "integer"
                    },
                    "initial_stamps": {
                      "description": "Number of stamps pre-filled on new customer cards (0 to stamps_required - 1)",
                      "type": "integer"
                    },
                    "name": {
                      "description": "Card name (e.g. 'Coffee Loyalty Card')",
                      "type": "string"
                    },
                    "rewards_count": {
                      "description": "Number of rewards defined for this card",
                      "type": "integer"
                    },
                    "show_member_field": {
                      "description": "Whether wallet passes show the member name field",
                      "type": "boolean"
                    },
                    "show_stamps_to_reward_field": {
                      "description": "Whether wallet passes show the stamps-to-reward field",
                      "type": "boolean"
                    },
                    "stamp_background_color": {
                      "description": "Hex colour for stamp backgrounds",
                      "type": "string"
                    },
                    "stamp_color": {
                      "description": "Hex colour for stamp icons",
                      "type": "string"
                    },
                    "stamp_icon": {
                      "description": "Icon used for stamps (e.g. 'coffee', 'heart', 'star')",
                      "type": "string"
                    },
                    "stamps_required": {
                      "description": "Number of stamps needed to complete the card (1–21)",
                      "type": "integer"
                    },
                    "strip_color": {
                      "description": "Hex colour for the strip (when strip_type is 'color')",
                      "type": "string"
                    },
                    "strip_opacity": {
                      "description": "Opacity (0–100) of the strip background over the card colour, for a colour, an uploaded image or a preset alike. 100 renders the colour or image exactly as supplied; lower values let the card colour show through",
                      "type": "number"
                    },
                    "strip_preset": {
                      "description": "Preset strip image identifier (when strip_type is 'preset')",
                      "type": "string"
                    },
                    "strip_type": {
                      "description": "Strip image type: 'color', 'image', or 'preset'",
                      "type": "string"
                    },
                    "text_color": {
                      "description": "Hex colour for card text",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "card_color",
                    "text_color",
                    "stamp_icon",
                    "stamp_color",
                    "stamp_background_color",
                    "stamps_required",
                    "initial_stamps",
                    "show_member_field",
                    "show_stamps_to_reward_field",
                    "auxiliary_fields",
                    "strip_type",
                    "strip_color",
                    "strip_opacity",
                    "strip_preset",
                    "header_text",
                    "expires_at",
                    "archived_at",
                    "rewards_count",
                    "customer_cards_count",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The updated card object",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Card not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Validation failed – check the `errors` object for details"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Update a loyalty card",
        "tags": [
          "Cards"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/customers": {
      "get": {
        "description": "Returns a paginated list of customers for the store. Use the `search` parameter to filter\nby name, email, phone, card code (barcode), or external reference ID. Alternatively, pass\n`source` AND `external_id` together to perform an exact lookup by an external reference -\nthe response will contain at most one customer.\n",
        "operationId": "get_api_v1_accounts_account_id_customers",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Search query to filter customers by name, email, phone, card code (barcode), or external reference ID",
            "in": "query",
            "name": "search",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "External system slug (e.g. `square`, `shopify`). When combined with `external_id`, performs an exact lookup.",
            "in": "query",
            "name": "source",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "External system's identifier for the customer. Must be combined with `source`.",
            "in": "query",
            "name": "external_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Page number (defaults to 1)",
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Number of items per page",
            "in": "query",
            "name": "items",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "customers": {
                      "description": "The customers on this page",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "pagination": {
                      "additionalProperties": false,
                      "properties": {
                        "count": {
                          "description": "Total customers matching the query",
                          "type": "integer"
                        },
                        "items": {
                          "description": "Customers per page",
                          "type": "integer"
                        },
                        "page": {
                          "description": "Current page number",
                          "type": "integer"
                        },
                        "pages": {
                          "description": "Total number of pages",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "page",
                        "items",
                        "count",
                        "pages"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "customers",
                    "pagination"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A page of customers, with pagination metadata",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "List or look up customers",
        "tags": [
          "Customers"
        ]
      },
      "post": {
        "description": "Creates a new customer for the store. Requires `first_name` and at least one of `email` or `phone`.\nOptionally enroll the customer in a loyalty card by passing `card_id`, and trigger delivery of\ncard links (email/SMS) by passing `send_card_links`. When a card with initial stamps is assigned,\nthose stamps are automatically applied as a welcome bonus.\n\nPass `metadata` to attach arbitrary key/value data, and `external_references` to link the\ncustomer to records in other systems (e.g. Square, Shopify). External references are upserted\nby `(source, external_id)` so this endpoint is safe to call with the same references twice.\n",
        "operationId": "post_api_v1_accounts_account_id_customers",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "card_id": {
                    "description": "Loyalty card ID to auto-enroll the customer in",
                    "type": "integer"
                  },
                  "customer": {
                    "additionalProperties": false,
                    "properties": {
                      "birthday": {
                        "description": "Customer's birthday (YYYY-MM-DD)",
                        "type": "string"
                      },
                      "email": {
                        "description": "Customer's email address (unique per store; required if phone is blank)",
                        "type": "string"
                      },
                      "external_references": {
                        "description": "Array of `{source, external_id, metadata}` objects linking this customer to records in external systems",
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      "first_name": {
                        "description": "Customer's first name",
                        "type": "string"
                      },
                      "last_name": {
                        "description": "Customer's last name",
                        "type": "string"
                      },
                      "metadata": {
                        "additionalProperties": true,
                        "description": "Free-form JSON object of additional per-customer attributes",
                        "type": "object"
                      },
                      "phone": {
                        "description": "Customer's phone number (unique per store; required if email is blank)",
                        "type": "string"
                      }
                    },
                    "required": [
                      "first_name"
                    ],
                    "type": "object"
                  },
                  "send_card_links": {
                    "description": "When true, sends the card links to the customer via email/SMS after enrollment. Note: even without this flag, the response includes `apple_wallet_url` and `google_wallet_url` in each customer card object so you can deliver them yourself.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "customer"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "birthday": {
                      "description": "Birthday as YYYY-MM-DD",
                      "type": "string"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "customer_cards": {
                      "description": "Cards this customer is enrolled on",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "email": {
                      "description": "Email address, unique per store",
                      "type": "string"
                    },
                    "external_references": {
                      "description": "Links to records in other systems",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "first_name": {
                      "description": "First name",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique customer ID",
                      "type": "integer"
                    },
                    "last_name": {
                      "description": "Last name",
                      "type": "string"
                    },
                    "metadata": {
                      "additionalProperties": true,
                      "description": "Free form per customer data",
                      "type": "object"
                    },
                    "phone": {
                      "description": "Phone number, unique per store",
                      "type": "string"
                    },
                    "stamp_count": {
                      "description": "Total stamps across every card",
                      "type": "integer"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "first_name",
                    "last_name",
                    "email",
                    "phone",
                    "birthday",
                    "stamp_count",
                    "metadata",
                    "external_references",
                    "customer_cards",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The newly created customer. Includes a customer_card object when card_id was supplied.",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Validation failed – check `errors` for details"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Create a customer",
        "tags": [
          "Customers"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/customers/{customer_id}/customer_cards": {
      "get": {
        "description": "Returns all loyalty cards enrolled for a specific customer, including stamp progress,\nstatus, wallet pass installation state, and wallet pass URLs (`apple_wallet_url` and\n`google_wallet_url`) that you can use to let customers add their loyalty card to\nApple Wallet or Google Wallet from your own app or website.\n",
        "operationId": "get_api_v1_accounts_account_id_customers_customer_id_customer_cards",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Customer ID",
            "in": "path",
            "name": "customer_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "additionalProperties": false,
                    "properties": {
                      "apple_wallet_url": {
                        "description": "Link to add or view the pass in Apple Wallet",
                        "type": "string"
                      },
                      "card_id": {
                        "description": "Loyalty card template ID",
                        "type": "integer"
                      },
                      "card_name": {
                        "description": "Name of the loyalty card",
                        "type": "string"
                      },
                      "created_at": {
                        "description": "ISO 8601 creation timestamp",
                        "type": "string"
                      },
                      "google_wallet_url": {
                        "description": "Link to add or view the pass in Google Wallet",
                        "type": "string"
                      },
                      "id": {
                        "description": "Customer card ID",
                        "type": "integer"
                      },
                      "issued_at": {
                        "description": "ISO 8601 timestamp the card was issued",
                        "type": "string"
                      },
                      "pass_installed": {
                        "description": "Whether the wallet pass has been installed",
                        "type": "boolean"
                      },
                      "progress_percentage": {
                        "description": "Completion towards the next reward, 0 to 100",
                        "type": "number"
                      },
                      "stamps_count": {
                        "description": "Stamps collected so far",
                        "type": "integer"
                      },
                      "stamps_remaining": {
                        "description": "Stamps still needed to complete the card",
                        "type": "integer"
                      },
                      "status": {
                        "description": "Current state of the customer card",
                        "type": "string"
                      },
                      "updated_at": {
                        "description": "ISO 8601 last-update timestamp",
                        "type": "string"
                      },
                      "uuid": {
                        "description": "Public identifier used in wallet pass URLs",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "card_id",
                      "card_name",
                      "stamps_count",
                      "stamps_remaining",
                      "status",
                      "uuid",
                      "progress_percentage",
                      "pass_installed",
                      "apple_wallet_url",
                      "google_wallet_url",
                      "issued_at",
                      "created_at",
                      "updated_at"
                    ],
                    "type": "object"
                  },
                  "type": "array"
                }
              }
            },
            "description": "An array of the customer's loyalty cards",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store or customer not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "List customer cards",
        "tags": [
          "Customer Cards"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/customers/{customer_id}/customer_cards/{id}": {
      "get": {
        "description": "Returns detailed information about a specific customer card, including stamp progress,\na list of rewards the customer has earned enough stamps to redeem, and wallet pass URLs\n(`apple_wallet_url` and `google_wallet_url`) for adding the card to Apple Wallet or\nGoogle Wallet.\n",
        "operationId": "get_api_v1_accounts_account_id_customers_customer_id_customer_cards_id",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Customer ID",
            "in": "path",
            "name": "customer_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Customer card ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "apple_wallet_url": {
                      "description": "Link to add or view the pass in Apple Wallet",
                      "type": "string"
                    },
                    "available_rewards": {
                      "description": "Rewards this customer can redeem right now",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "card_id": {
                      "description": "Loyalty card template ID",
                      "type": "integer"
                    },
                    "card_name": {
                      "description": "Name of the loyalty card",
                      "type": "string"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "customer_id": {
                      "description": "Owning customer ID",
                      "type": "integer"
                    },
                    "google_wallet_url": {
                      "description": "Link to add or view the pass in Google Wallet",
                      "type": "string"
                    },
                    "id": {
                      "description": "Customer card ID",
                      "type": "integer"
                    },
                    "issued_at": {
                      "description": "ISO 8601 timestamp the card was issued",
                      "type": "string"
                    },
                    "pass_installed": {
                      "description": "Whether the wallet pass has been installed",
                      "type": "boolean"
                    },
                    "progress_percentage": {
                      "description": "Completion towards the next reward, 0 to 100",
                      "type": "number"
                    },
                    "stamps_count": {
                      "description": "Stamps collected so far",
                      "type": "integer"
                    },
                    "stamps_remaining": {
                      "description": "Stamps still needed to complete the card",
                      "type": "integer"
                    },
                    "status": {
                      "description": "Current state of the customer card",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    },
                    "uuid": {
                      "description": "Public identifier used in wallet pass URLs",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "card_id",
                    "card_name",
                    "stamps_count",
                    "stamps_remaining",
                    "status",
                    "uuid",
                    "progress_percentage",
                    "pass_installed",
                    "apple_wallet_url",
                    "google_wallet_url",
                    "issued_at",
                    "created_at",
                    "updated_at",
                    "customer_id",
                    "account_id",
                    "available_rewards"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A customer card, with its available rewards",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store, customer, or customer card not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Show a customer card",
        "tags": [
          "Customer Cards"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/customers/{customer_id}/customer_cards/{id}/redeem": {
      "post": {
        "description": "Redeems a reward for a customer, deducting the required stamps from their card.\nThe customer must have enough stamps on this card to cover the reward's cost.\nTriggers wallet pass updates and push notifications.\n",
        "operationId": "post_api_v1_accounts_account_id_customers_customer_id_customer_cards_id_redeem",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Customer ID",
            "in": "path",
            "name": "customer_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Customer card ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "reward_id": {
                    "description": "Reward ID to redeem",
                    "type": "integer"
                  }
                },
                "required": [
                  "reward_id"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "redemption": {
                      "additionalProperties": false,
                      "properties": {
                        "id": {
                          "description": "Redemption ID",
                          "type": "integer"
                        },
                        "redeemed_at": {
                          "description": "ISO 8601 timestamp of the redemption",
                          "type": "string"
                        },
                        "reward_id": {
                          "description": "Reward that was redeemed",
                          "type": "integer"
                        },
                        "reward_name": {
                          "description": "Display name of the reward",
                          "type": "string"
                        },
                        "stamps_remaining": {
                          "description": "Stamps left on the card afterwards",
                          "type": "integer"
                        },
                        "stamps_spent": {
                          "description": "Stamps deducted from the card",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "id",
                        "reward_id",
                        "reward_name",
                        "stamps_spent",
                        "stamps_remaining",
                        "redeemed_at"
                      ],
                      "type": "object"
                    },
                    "success": {
                      "description": "True when the reward was redeemed",
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "success",
                    "redemption"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The redemption that was recorded",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store, customer, customer card, or reward not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Redemption failed – not enough stamps or reward inactive"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Redeem a reward",
        "tags": [
          "Customer Cards"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/customers/{customer_id}/customer_cards/{id}/stamp": {
      "post": {
        "description": "Adds stamps to a customer's loyalty card. Triggers ledger entries, wallet pass updates,\nand push notifications. Pass `skip_notifications` to stamp silently.\n",
        "operationId": "post_api_v1_accounts_account_id_customers_customer_id_customer_cards_id_stamp",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Customer ID",
            "in": "path",
            "name": "customer_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Customer card ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "skip_notifications": {
                    "description": "When true, stamp changes bypass notifications",
                    "type": "boolean"
                  },
                  "stamps": {
                    "description": "Number of stamps to add (e.g. 1, 3)",
                    "type": "integer"
                  }
                },
                "required": [
                  "stamps"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "apple_wallet_url": {
                      "description": "Link to add or view the pass in Apple Wallet",
                      "type": "string"
                    },
                    "available_rewards": {
                      "description": "Rewards this customer can redeem right now",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "card_id": {
                      "description": "Loyalty card template ID",
                      "type": "integer"
                    },
                    "card_name": {
                      "description": "Name of the loyalty card",
                      "type": "string"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "customer_id": {
                      "description": "Owning customer ID",
                      "type": "integer"
                    },
                    "google_wallet_url": {
                      "description": "Link to add or view the pass in Google Wallet",
                      "type": "string"
                    },
                    "id": {
                      "description": "Customer card ID",
                      "type": "integer"
                    },
                    "issued_at": {
                      "description": "ISO 8601 timestamp the card was issued",
                      "type": "string"
                    },
                    "pass_installed": {
                      "description": "Whether the wallet pass has been installed",
                      "type": "boolean"
                    },
                    "progress_percentage": {
                      "description": "Completion towards the next reward, 0 to 100",
                      "type": "number"
                    },
                    "stamps_count": {
                      "description": "Stamps collected so far",
                      "type": "integer"
                    },
                    "stamps_remaining": {
                      "description": "Stamps still needed to complete the card",
                      "type": "integer"
                    },
                    "status": {
                      "description": "Current state of the customer card",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    },
                    "uuid": {
                      "description": "Public identifier used in wallet pass URLs",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "card_id",
                    "card_name",
                    "stamps_count",
                    "stamps_remaining",
                    "status",
                    "uuid",
                    "progress_percentage",
                    "pass_installed",
                    "apple_wallet_url",
                    "google_wallet_url",
                    "issued_at",
                    "created_at",
                    "updated_at",
                    "customer_id",
                    "account_id",
                    "available_rewards"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The updated customer card, with its available rewards",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store, customer, or customer card not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Validation failed – check `errors` for details"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Add stamps",
        "tags": [
          "Customer Cards"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/customers/{id}": {
      "get": {
        "description": "Returns detailed information about a single customer, including all of their\nenrolled loyalty cards with stamp progress and wallet pass URLs (`apple_wallet_url`\nand `google_wallet_url`) for each card. Also includes `metadata` and\n`external_references` so you can sync state with external systems.\n",
        "operationId": "get_api_v1_accounts_account_id_customers_id",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Customer ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "birthday": {
                      "description": "Birthday as YYYY-MM-DD",
                      "type": "string"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "customer_cards": {
                      "description": "Cards this customer is enrolled on",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "email": {
                      "description": "Email address, unique per store",
                      "type": "string"
                    },
                    "external_references": {
                      "description": "Links to records in other systems",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "first_name": {
                      "description": "First name",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique customer ID",
                      "type": "integer"
                    },
                    "last_name": {
                      "description": "Last name",
                      "type": "string"
                    },
                    "metadata": {
                      "additionalProperties": true,
                      "description": "Free form per customer data",
                      "type": "object"
                    },
                    "phone": {
                      "description": "Phone number, unique per store",
                      "type": "string"
                    },
                    "stamp_count": {
                      "description": "Total stamps across every card",
                      "type": "integer"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "first_name",
                    "last_name",
                    "email",
                    "phone",
                    "birthday",
                    "stamp_count",
                    "metadata",
                    "external_references",
                    "customer_cards",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A customer, including their enrolled loyalty cards",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store or customer not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Show a customer",
        "tags": [
          "Customers"
        ]
      },
      "patch": {
        "description": "Updates an existing customer's details. To add stamps or redeem rewards, use the\ncustomer cards endpoints instead.\n\n`metadata` is shallow-merged into the existing metadata. `external_references` are upserted\nby `(source, external_id)` - to remove a reference, omit it from subsequent calls and use\na separate `DELETE` workflow (not yet exposed via API; manage in dashboard for now).\n",
        "operationId": "patch_api_v1_accounts_account_id_customers_id",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Customer ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "customer": {
                    "additionalProperties": false,
                    "properties": {
                      "birthday": {
                        "description": "Customer's birthday (YYYY-MM-DD)",
                        "type": "string"
                      },
                      "email": {
                        "description": "Customer's email address (unique per store)",
                        "type": "string"
                      },
                      "external_references": {
                        "description": "Array of `{source, external_id, metadata}` objects to upsert",
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      "first_name": {
                        "description": "Customer's first name",
                        "type": "string"
                      },
                      "last_name": {
                        "description": "Customer's last name",
                        "type": "string"
                      },
                      "metadata": {
                        "additionalProperties": true,
                        "description": "Shallow-merged into existing metadata",
                        "type": "object"
                      },
                      "phone": {
                        "description": "Customer's phone number (unique per store)",
                        "type": "string"
                      }
                    },
                    "type": "object"
                  }
                },
                "required": [
                  "customer"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "birthday": {
                      "description": "Birthday as YYYY-MM-DD",
                      "type": "string"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "customer_cards": {
                      "description": "Cards this customer is enrolled on",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "email": {
                      "description": "Email address, unique per store",
                      "type": "string"
                    },
                    "external_references": {
                      "description": "Links to records in other systems",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "first_name": {
                      "description": "First name",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique customer ID",
                      "type": "integer"
                    },
                    "last_name": {
                      "description": "Last name",
                      "type": "string"
                    },
                    "metadata": {
                      "additionalProperties": true,
                      "description": "Free form per customer data",
                      "type": "object"
                    },
                    "phone": {
                      "description": "Phone number, unique per store",
                      "type": "string"
                    },
                    "stamp_count": {
                      "description": "Total stamps across every card",
                      "type": "integer"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "first_name",
                    "last_name",
                    "email",
                    "phone",
                    "birthday",
                    "stamp_count",
                    "metadata",
                    "external_references",
                    "customer_cards",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The updated customer",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store or customer not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Validation failed – check `errors` for details"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Update a customer",
        "tags": [
          "Customers"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/locations": {
      "get": {
        "description": "Returns every physical location belonging to the specified store.",
        "operationId": "get_api_v1_accounts_account_id_locations",
        "parameters": [
          {
            "description": "Parent store ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "additionalProperties": false,
                    "properties": {
                      "account_id": {
                        "description": "Parent store ID",
                        "type": "integer"
                      },
                      "address": {
                        "description": "Full street address",
                        "type": "string"
                      },
                      "created_at": {
                        "description": "ISO 8601 creation timestamp",
                        "type": "string"
                      },
                      "id": {
                        "description": "Unique location ID",
                        "type": "integer"
                      },
                      "latitude": {
                        "description": "Geocoded latitude (auto-derived from address)",
                        "type": "number"
                      },
                      "longitude": {
                        "description": "Geocoded longitude (auto-derived from address)",
                        "type": "number"
                      },
                      "name": {
                        "description": "Location name (e.g. 'Downtown Branch')",
                        "type": "string"
                      },
                      "updated_at": {
                        "description": "ISO 8601 last-update timestamp",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "account_id",
                      "name",
                      "address",
                      "latitude",
                      "longitude",
                      "created_at",
                      "updated_at"
                    ],
                    "type": "object"
                  },
                  "type": "array"
                }
              }
            },
            "description": "An array of location objects",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store not found or not accessible"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "List all locations",
        "tags": [
          "Locations"
        ]
      },
      "post": {
        "description": "Creates a new physical location for the store. The provided address is\nautomatically geocoded to latitude and longitude coordinates in the background.\n",
        "operationId": "post_api_v1_accounts_account_id_locations",
        "parameters": [
          {
            "description": "Parent store ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "location": {
                    "additionalProperties": false,
                    "properties": {
                      "address": {
                        "description": "Full street address – automatically geocoded to lat/lng",
                        "type": "string"
                      },
                      "name": {
                        "description": "Location name (e.g. 'High Street Branch')",
                        "type": "string"
                      }
                    },
                    "required": [
                      "name",
                      "address"
                    ],
                    "type": "object"
                  }
                },
                "required": [
                  "location"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "address": {
                      "description": "Full street address",
                      "type": "string"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique location ID",
                      "type": "integer"
                    },
                    "latitude": {
                      "description": "Geocoded latitude (auto-derived from address)",
                      "type": "number"
                    },
                    "longitude": {
                      "description": "Geocoded longitude (auto-derived from address)",
                      "type": "number"
                    },
                    "name": {
                      "description": "Location name (e.g. 'Downtown Branch')",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "name",
                    "address",
                    "latitude",
                    "longitude",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The newly created location object",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store not found or not accessible"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Validation failed – check the `errors` object for details"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Create a location",
        "tags": [
          "Locations"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/locations/{id}": {
      "delete": {
        "description": "Permanently deletes a location. This action cannot be undone.",
        "operationId": "delete_api_v1_accounts_account_id_locations_id",
        "parameters": [
          {
            "description": "Parent store ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Location ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No content – location successfully deleted",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Location not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Delete a location",
        "tags": [
          "Locations"
        ]
      },
      "get": {
        "description": "Returns a single location by ID.",
        "operationId": "get_api_v1_accounts_account_id_locations_id",
        "parameters": [
          {
            "description": "Parent store ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Location ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "address": {
                      "description": "Full street address",
                      "type": "string"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique location ID",
                      "type": "integer"
                    },
                    "latitude": {
                      "description": "Geocoded latitude (auto-derived from address)",
                      "type": "number"
                    },
                    "longitude": {
                      "description": "Geocoded longitude (auto-derived from address)",
                      "type": "number"
                    },
                    "name": {
                      "description": "Location name (e.g. 'Downtown Branch')",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "name",
                    "address",
                    "latitude",
                    "longitude",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A location object",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Location not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Show a location",
        "tags": [
          "Locations"
        ]
      },
      "patch": {
        "description": "Updates an existing location. If the address is changed, it will be re-geocoded automatically.",
        "operationId": "patch_api_v1_accounts_account_id_locations_id",
        "parameters": [
          {
            "description": "Parent store ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Location ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "location": {
                    "additionalProperties": false,
                    "properties": {
                      "address": {
                        "description": "Full street address – automatically geocoded to lat/lng",
                        "type": "string"
                      },
                      "name": {
                        "description": "Location name",
                        "type": "string"
                      }
                    },
                    "type": "object"
                  }
                },
                "required": [
                  "location"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "address": {
                      "description": "Full street address",
                      "type": "string"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique location ID",
                      "type": "integer"
                    },
                    "latitude": {
                      "description": "Geocoded latitude (auto-derived from address)",
                      "type": "number"
                    },
                    "longitude": {
                      "description": "Geocoded longitude (auto-derived from address)",
                      "type": "number"
                    },
                    "name": {
                      "description": "Location name (e.g. 'Downtown Branch')",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "name",
                    "address",
                    "latitude",
                    "longitude",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The updated location object",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Location not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Validation failed – check the `errors` object for details"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Update a location",
        "tags": [
          "Locations"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/posters": {
      "get": {
        "description": "Returns all posters for the store. Optionally filter by card or active status.",
        "operationId": "get_api_v1_accounts_account_id_posters",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Filter posters belonging to a specific card",
            "in": "query",
            "name": "card_id",
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "When present, return only active posters",
            "in": "query",
            "name": "active",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "additionalProperties": false,
                    "properties": {
                      "account_id": {
                        "description": "Parent store ID",
                        "type": "integer"
                      },
                      "active": {
                        "description": "Whether the public signup URL is live",
                        "type": "boolean"
                      },
                      "card_id": {
                        "description": "Loyalty card customers are signed up to",
                        "type": "integer"
                      },
                      "collect_email": {
                        "description": "Whether the public signup form collects email",
                        "type": "boolean"
                      },
                      "collect_phone": {
                        "description": "Whether the public signup form collects phone number",
                        "type": "boolean"
                      },
                      "contact_collection_mode": {
                        "description": "Which contact fields appear on the public signup form: 'email_and_phone', 'email_only', or 'phone_only'",
                        "type": "string"
                      },
                      "created_at": {
                        "description": "ISO 8601 creation timestamp",
                        "type": "string"
                      },
                      "display_url": {
                        "description": "URL of the on screen version of the poster",
                        "type": "string"
                      },
                      "id": {
                        "description": "Unique poster ID",
                        "type": "integer"
                      },
                      "minimum_age": {
                        "description": "Minimum customer age required for signup",
                        "type": "number"
                      },
                      "paper_size": {
                        "description": "Paper size the poster is laid out for",
                        "type": "string"
                      },
                      "primary_color": {
                        "description": "Hex colour for the poster background",
                        "type": "string"
                      },
                      "qr_code_url": {
                        "description": "URL encoded in the QR code",
                        "type": "string"
                      },
                      "require_birthday": {
                        "description": "Whether date of birth is required on the public signup form",
                        "type": "boolean"
                      },
                      "require_email": {
                        "description": "Whether email is required when it is collected",
                        "type": "boolean"
                      },
                      "require_phone": {
                        "description": "Whether phone number is required when it is collected",
                        "type": "boolean"
                      },
                      "secondary_color": {
                        "description": "Hex accent colour",
                        "type": "string"
                      },
                      "signup_url": {
                        "description": "Public URL the QR code points at",
                        "type": "string"
                      },
                      "text_color": {
                        "description": "Hex colour for poster text",
                        "type": "string"
                      },
                      "title": {
                        "description": "Heading printed on the poster",
                        "type": "string"
                      },
                      "updated_at": {
                        "description": "ISO 8601 last-update timestamp",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "account_id",
                      "card_id",
                      "title",
                      "paper_size",
                      "primary_color",
                      "secondary_color",
                      "text_color",
                      "contact_collection_mode",
                      "collect_email",
                      "collect_phone",
                      "require_email",
                      "require_phone",
                      "require_birthday",
                      "minimum_age",
                      "active",
                      "signup_url",
                      "display_url",
                      "qr_code_url",
                      "created_at",
                      "updated_at"
                    ],
                    "type": "object"
                  },
                  "type": "array"
                }
              }
            },
            "description": "An array of poster objects",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "List posters",
        "tags": [
          "Posters"
        ]
      },
      "post": {
        "description": "Creates a new printable QR code poster for customer signup. The poster will automatically\ngenerate a unique public signup URL and QR code. The `card_id` is required on create to\nassociate the poster with a loyalty card.\n",
        "operationId": "post_api_v1_accounts_account_id_posters",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "poster": {
                    "additionalProperties": false,
                    "properties": {
                      "active": {
                        "description": "Whether the poster is active (defaults to true)",
                        "type": "boolean"
                      },
                      "card_id": {
                        "description": "ID of the loyalty card this poster links to",
                        "type": "integer"
                      },
                      "contact_collection_mode": {
                        "description": "Which contact fields appear on the public signup form",
                        "type": "string"
                      },
                      "minimum_age": {
                        "description": "Minimum customer age required for signup. Requires require_birthday to be true.",
                        "type": "number"
                      },
                      "paper_size": {
                        "description": "Print size – one of: a4, a5, a6, letter",
                        "type": "string"
                      },
                      "primary_color": {
                        "description": "Primary brand color as a hex string (e.g. '#FF5733')",
                        "type": "string"
                      },
                      "require_birthday": {
                        "description": "Whether date of birth is required on the public signup form",
                        "type": "boolean"
                      },
                      "require_email": {
                        "description": "Whether email is required when it is collected",
                        "type": "boolean"
                      },
                      "require_phone": {
                        "description": "Whether phone number is required when it is collected",
                        "type": "boolean"
                      },
                      "secondary_color": {
                        "description": "Secondary brand color as a hex string",
                        "type": "string"
                      },
                      "text_color": {
                        "description": "Text color as a hex string",
                        "type": "string"
                      },
                      "title": {
                        "description": "Headline text displayed on the poster",
                        "type": "string"
                      }
                    },
                    "required": [
                      "card_id"
                    ],
                    "type": "object"
                  }
                },
                "required": [
                  "poster"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "active": {
                      "description": "Whether the public signup URL is live",
                      "type": "boolean"
                    },
                    "card_id": {
                      "description": "Loyalty card customers are signed up to",
                      "type": "integer"
                    },
                    "collect_email": {
                      "description": "Whether the public signup form collects email",
                      "type": "boolean"
                    },
                    "collect_phone": {
                      "description": "Whether the public signup form collects phone number",
                      "type": "boolean"
                    },
                    "contact_collection_mode": {
                      "description": "Which contact fields appear on the public signup form: 'email_and_phone', 'email_only', or 'phone_only'",
                      "type": "string"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "display_url": {
                      "description": "URL of the on screen version of the poster",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique poster ID",
                      "type": "integer"
                    },
                    "minimum_age": {
                      "description": "Minimum customer age required for signup",
                      "type": "number"
                    },
                    "paper_size": {
                      "description": "Paper size the poster is laid out for",
                      "type": "string"
                    },
                    "primary_color": {
                      "description": "Hex colour for the poster background",
                      "type": "string"
                    },
                    "qr_code_url": {
                      "description": "URL encoded in the QR code",
                      "type": "string"
                    },
                    "require_birthday": {
                      "description": "Whether date of birth is required on the public signup form",
                      "type": "boolean"
                    },
                    "require_email": {
                      "description": "Whether email is required when it is collected",
                      "type": "boolean"
                    },
                    "require_phone": {
                      "description": "Whether phone number is required when it is collected",
                      "type": "boolean"
                    },
                    "secondary_color": {
                      "description": "Hex accent colour",
                      "type": "string"
                    },
                    "signup_url": {
                      "description": "Public URL the QR code points at",
                      "type": "string"
                    },
                    "text_color": {
                      "description": "Hex colour for poster text",
                      "type": "string"
                    },
                    "title": {
                      "description": "Heading printed on the poster",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "card_id",
                    "title",
                    "paper_size",
                    "primary_color",
                    "secondary_color",
                    "text_color",
                    "contact_collection_mode",
                    "collect_email",
                    "collect_phone",
                    "require_email",
                    "require_phone",
                    "require_birthday",
                    "minimum_age",
                    "active",
                    "signup_url",
                    "display_url",
                    "qr_code_url",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The newly created poster object",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Validation failed – check `errors` for details"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Create a poster",
        "tags": [
          "Posters"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/posters/{id}": {
      "delete": {
        "description": "Permanently deletes a poster. The public signup URL will stop working.",
        "operationId": "delete_api_v1_accounts_account_id_posters_id",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Poster ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No content. The poster was deleted and its signup URL deactivated.",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store or poster not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Poster could not be deleted"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Delete a poster",
        "tags": [
          "Posters"
        ]
      },
      "get": {
        "description": "Returns a single poster by ID, including generated signup and display URLs.",
        "operationId": "get_api_v1_accounts_account_id_posters_id",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Poster ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "active": {
                      "description": "Whether the public signup URL is live",
                      "type": "boolean"
                    },
                    "card_id": {
                      "description": "Loyalty card customers are signed up to",
                      "type": "integer"
                    },
                    "collect_email": {
                      "description": "Whether the public signup form collects email",
                      "type": "boolean"
                    },
                    "collect_phone": {
                      "description": "Whether the public signup form collects phone number",
                      "type": "boolean"
                    },
                    "contact_collection_mode": {
                      "description": "Which contact fields appear on the public signup form: 'email_and_phone', 'email_only', or 'phone_only'",
                      "type": "string"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "display_url": {
                      "description": "URL of the on screen version of the poster",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique poster ID",
                      "type": "integer"
                    },
                    "minimum_age": {
                      "description": "Minimum customer age required for signup",
                      "type": "number"
                    },
                    "paper_size": {
                      "description": "Paper size the poster is laid out for",
                      "type": "string"
                    },
                    "primary_color": {
                      "description": "Hex colour for the poster background",
                      "type": "string"
                    },
                    "qr_code_url": {
                      "description": "URL encoded in the QR code",
                      "type": "string"
                    },
                    "require_birthday": {
                      "description": "Whether date of birth is required on the public signup form",
                      "type": "boolean"
                    },
                    "require_email": {
                      "description": "Whether email is required when it is collected",
                      "type": "boolean"
                    },
                    "require_phone": {
                      "description": "Whether phone number is required when it is collected",
                      "type": "boolean"
                    },
                    "secondary_color": {
                      "description": "Hex accent colour",
                      "type": "string"
                    },
                    "signup_url": {
                      "description": "Public URL the QR code points at",
                      "type": "string"
                    },
                    "text_color": {
                      "description": "Hex colour for poster text",
                      "type": "string"
                    },
                    "title": {
                      "description": "Heading printed on the poster",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "card_id",
                    "title",
                    "paper_size",
                    "primary_color",
                    "secondary_color",
                    "text_color",
                    "contact_collection_mode",
                    "collect_email",
                    "collect_phone",
                    "require_email",
                    "require_phone",
                    "require_birthday",
                    "minimum_age",
                    "active",
                    "signup_url",
                    "display_url",
                    "qr_code_url",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A poster object",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store or poster not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Show a poster",
        "tags": [
          "Posters"
        ]
      },
      "patch": {
        "description": "Updates an existing poster. The `card_id` cannot be changed after creation.",
        "operationId": "patch_api_v1_accounts_account_id_posters_id",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Poster ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "poster": {
                    "additionalProperties": false,
                    "properties": {
                      "active": {
                        "description": "Whether the poster is active",
                        "type": "boolean"
                      },
                      "contact_collection_mode": {
                        "description": "Which contact fields appear on the public signup form",
                        "type": "string"
                      },
                      "minimum_age": {
                        "description": "Minimum customer age required for signup. Requires require_birthday to be true.",
                        "type": "number"
                      },
                      "paper_size": {
                        "description": "Print size – one of: a4, a5, a6, letter",
                        "type": "string"
                      },
                      "primary_color": {
                        "description": "Primary brand color as a hex string",
                        "type": "string"
                      },
                      "require_birthday": {
                        "description": "Whether date of birth is required on the public signup form",
                        "type": "boolean"
                      },
                      "require_email": {
                        "description": "Whether email is required when it is collected",
                        "type": "boolean"
                      },
                      "require_phone": {
                        "description": "Whether phone number is required when it is collected",
                        "type": "boolean"
                      },
                      "secondary_color": {
                        "description": "Secondary brand color as a hex string",
                        "type": "string"
                      },
                      "text_color": {
                        "description": "Text color as a hex string",
                        "type": "string"
                      },
                      "title": {
                        "description": "Headline text displayed on the poster",
                        "type": "string"
                      }
                    },
                    "type": "object"
                  }
                },
                "required": [
                  "poster"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "active": {
                      "description": "Whether the public signup URL is live",
                      "type": "boolean"
                    },
                    "card_id": {
                      "description": "Loyalty card customers are signed up to",
                      "type": "integer"
                    },
                    "collect_email": {
                      "description": "Whether the public signup form collects email",
                      "type": "boolean"
                    },
                    "collect_phone": {
                      "description": "Whether the public signup form collects phone number",
                      "type": "boolean"
                    },
                    "contact_collection_mode": {
                      "description": "Which contact fields appear on the public signup form: 'email_and_phone', 'email_only', or 'phone_only'",
                      "type": "string"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "display_url": {
                      "description": "URL of the on screen version of the poster",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique poster ID",
                      "type": "integer"
                    },
                    "minimum_age": {
                      "description": "Minimum customer age required for signup",
                      "type": "number"
                    },
                    "paper_size": {
                      "description": "Paper size the poster is laid out for",
                      "type": "string"
                    },
                    "primary_color": {
                      "description": "Hex colour for the poster background",
                      "type": "string"
                    },
                    "qr_code_url": {
                      "description": "URL encoded in the QR code",
                      "type": "string"
                    },
                    "require_birthday": {
                      "description": "Whether date of birth is required on the public signup form",
                      "type": "boolean"
                    },
                    "require_email": {
                      "description": "Whether email is required when it is collected",
                      "type": "boolean"
                    },
                    "require_phone": {
                      "description": "Whether phone number is required when it is collected",
                      "type": "boolean"
                    },
                    "secondary_color": {
                      "description": "Hex accent colour",
                      "type": "string"
                    },
                    "signup_url": {
                      "description": "Public URL the QR code points at",
                      "type": "string"
                    },
                    "text_color": {
                      "description": "Hex colour for poster text",
                      "type": "string"
                    },
                    "title": {
                      "description": "Heading printed on the poster",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "card_id",
                    "title",
                    "paper_size",
                    "primary_color",
                    "secondary_color",
                    "text_color",
                    "contact_collection_mode",
                    "collect_email",
                    "collect_phone",
                    "require_email",
                    "require_phone",
                    "require_birthday",
                    "minimum_age",
                    "active",
                    "signup_url",
                    "display_url",
                    "qr_code_url",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The updated poster object",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store or poster not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Validation failed – check `errors` for details"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Update a poster",
        "tags": [
          "Posters"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/rewards": {
      "get": {
        "description": "Returns all rewards for the store. Optionally filter by card or active status.",
        "operationId": "get_api_v1_accounts_account_id_rewards",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Filter rewards belonging to a specific card",
            "in": "query",
            "name": "card_id",
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "When present, return only active rewards",
            "in": "query",
            "name": "active",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "additionalProperties": false,
                    "properties": {
                      "account_id": {
                        "description": "Parent store ID",
                        "type": "integer"
                      },
                      "active": {
                        "description": "Whether the reward can currently be redeemed",
                        "type": "boolean"
                      },
                      "card_id": {
                        "description": "ID of the loyalty card this reward belongs to",
                        "type": "integer"
                      },
                      "created_at": {
                        "description": "ISO 8601 creation timestamp",
                        "type": "string"
                      },
                      "description": {
                        "description": "Longer description of the reward",
                        "type": "string"
                      },
                      "id": {
                        "description": "Unique reward ID",
                        "type": "integer"
                      },
                      "name": {
                        "description": "Display name of the reward",
                        "type": "string"
                      },
                      "position": {
                        "description": "Display order",
                        "type": "integer"
                      },
                      "stamps_required": {
                        "description": "Stamps needed before the reward can be redeemed",
                        "type": "integer"
                      },
                      "updated_at": {
                        "description": "ISO 8601 last-update timestamp",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "account_id",
                      "card_id",
                      "name",
                      "description",
                      "stamps_required",
                      "position",
                      "active",
                      "created_at",
                      "updated_at"
                    ],
                    "type": "object"
                  },
                  "type": "array"
                }
              }
            },
            "description": "An array of reward objects",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "List rewards",
        "tags": [
          "Rewards"
        ]
      },
      "post": {
        "description": "Creates a new reward for a loyalty card. The card must belong to the same store.\nThe `card_id` is required on create but cannot be changed afterwards.\n",
        "operationId": "post_api_v1_accounts_account_id_rewards",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "reward": {
                    "additionalProperties": false,
                    "properties": {
                      "active": {
                        "description": "Whether the reward is active and redeemable (defaults to true)",
                        "type": "boolean"
                      },
                      "card_id": {
                        "description": "ID of the loyalty card this reward belongs to",
                        "type": "integer"
                      },
                      "description": {
                        "description": "Detailed description of the reward",
                        "type": "string"
                      },
                      "name": {
                        "description": "Display name of the reward (e.g. 'Free Coffee')",
                        "type": "string"
                      },
                      "position": {
                        "description": "Display order position (lower numbers appear first)",
                        "type": "integer"
                      },
                      "stamps_required": {
                        "description": "Number of stamps needed to unlock this reward (must be > 0)",
                        "type": "integer"
                      }
                    },
                    "required": [
                      "card_id",
                      "name",
                      "stamps_required"
                    ],
                    "type": "object"
                  }
                },
                "required": [
                  "reward"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "active": {
                      "description": "Whether the reward can currently be redeemed",
                      "type": "boolean"
                    },
                    "card_id": {
                      "description": "ID of the loyalty card this reward belongs to",
                      "type": "integer"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "description": {
                      "description": "Longer description of the reward",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique reward ID",
                      "type": "integer"
                    },
                    "name": {
                      "description": "Display name of the reward",
                      "type": "string"
                    },
                    "position": {
                      "description": "Display order",
                      "type": "integer"
                    },
                    "stamps_required": {
                      "description": "Stamps needed before the reward can be redeemed",
                      "type": "integer"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "card_id",
                    "name",
                    "description",
                    "stamps_required",
                    "position",
                    "active",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The newly created reward object",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store or card not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Validation failed – check `errors` for details"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Create a reward",
        "tags": [
          "Rewards"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/rewards/{id}": {
      "delete": {
        "description": "Permanently deletes a reward. This cannot be undone.",
        "operationId": "delete_api_v1_accounts_account_id_rewards_id",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Reward ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No content. The reward was deleted.",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store or reward not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Reward could not be deleted"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Delete a reward",
        "tags": [
          "Rewards"
        ]
      },
      "get": {
        "description": "Returns a single reward by ID.",
        "operationId": "get_api_v1_accounts_account_id_rewards_id",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Reward ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "active": {
                      "description": "Whether the reward can currently be redeemed",
                      "type": "boolean"
                    },
                    "card_id": {
                      "description": "ID of the loyalty card this reward belongs to",
                      "type": "integer"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "description": {
                      "description": "Longer description of the reward",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique reward ID",
                      "type": "integer"
                    },
                    "name": {
                      "description": "Display name of the reward",
                      "type": "string"
                    },
                    "position": {
                      "description": "Display order",
                      "type": "integer"
                    },
                    "stamps_required": {
                      "description": "Stamps needed before the reward can be redeemed",
                      "type": "integer"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "card_id",
                    "name",
                    "description",
                    "stamps_required",
                    "position",
                    "active",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A reward object",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store or reward not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Show a reward",
        "tags": [
          "Rewards"
        ]
      },
      "patch": {
        "description": "Updates an existing reward. The `card_id` cannot be changed after creation.",
        "operationId": "patch_api_v1_accounts_account_id_rewards_id",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Reward ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "reward": {
                    "additionalProperties": false,
                    "properties": {
                      "active": {
                        "description": "Whether the reward is active and redeemable",
                        "type": "boolean"
                      },
                      "description": {
                        "description": "Detailed description of the reward",
                        "type": "string"
                      },
                      "name": {
                        "description": "Display name of the reward",
                        "type": "string"
                      },
                      "position": {
                        "description": "Display order position",
                        "type": "integer"
                      },
                      "stamps_required": {
                        "description": "Number of stamps needed to unlock this reward (must be > 0)",
                        "type": "integer"
                      }
                    },
                    "type": "object"
                  }
                },
                "required": [
                  "reward"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "active": {
                      "description": "Whether the reward can currently be redeemed",
                      "type": "boolean"
                    },
                    "card_id": {
                      "description": "ID of the loyalty card this reward belongs to",
                      "type": "integer"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "description": {
                      "description": "Longer description of the reward",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique reward ID",
                      "type": "integer"
                    },
                    "name": {
                      "description": "Display name of the reward",
                      "type": "string"
                    },
                    "position": {
                      "description": "Display order",
                      "type": "integer"
                    },
                    "stamps_required": {
                      "description": "Stamps needed before the reward can be redeemed",
                      "type": "integer"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "card_id",
                    "name",
                    "description",
                    "stamps_required",
                    "position",
                    "active",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The updated reward object",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store or reward not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Validation failed – check `errors` for details"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Update a reward",
        "tags": [
          "Rewards"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/webhook_subscriptions": {
      "get": {
        "description": "Returns every webhook subscription for the store, oldest first. Signing secrets are not included; fetch a single subscription to read its secret.",
        "operationId": "get_api_v1_accounts_account_id_webhook_subscriptions",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Only return subscriptions that list this event (or `*`)",
            "in": "query",
            "name": "event",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "additionalProperties": false,
                    "properties": {
                      "account_id": {
                        "description": "Parent store ID",
                        "type": "integer"
                      },
                      "created_at": {
                        "description": "ISO 8601 creation timestamp",
                        "type": "string"
                      },
                      "description": {
                        "description": "Your own label for the subscription",
                        "type": "string"
                      },
                      "disabled_at": {
                        "description": "ISO 8601 time the subscription was disabled",
                        "type": "string"
                      },
                      "disabled_reason": {
                        "description": "`disabled_by_user`, `failing` or `blocked_address`",
                        "type": "string"
                      },
                      "enabled": {
                        "description": "Whether events are being delivered",
                        "type": "boolean"
                      },
                      "event": {
                        "description": "The event, when there is exactly one (kept for older integrations)",
                        "type": "string"
                      },
                      "events": {
                        "description": "Events delivered to this URL, or `[\"*\"]` for every event",
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      "id": {
                        "description": "Unique subscription ID",
                        "type": "integer"
                      },
                      "last_delivery_at": {
                        "description": "ISO 8601 time of the most recent delivery attempt",
                        "type": "string"
                      },
                      "last_delivery_error": {
                        "description": "Why the most recent attempt failed",
                        "type": "string"
                      },
                      "last_delivery_status": {
                        "description": "HTTP status your URL returned on the most recent attempt",
                        "type": "number"
                      },
                      "payload_format": {
                        "description": "`envelope` (default) or `flat` (the bare data object, used by Zapier)",
                        "type": "string"
                      },
                      "target_url": {
                        "description": "URL that receives the POST requests",
                        "type": "string"
                      },
                      "updated_at": {
                        "description": "ISO 8601 last-update timestamp",
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "account_id",
                      "events",
                      "event",
                      "target_url",
                      "description",
                      "payload_format",
                      "enabled",
                      "disabled_at",
                      "disabled_reason",
                      "last_delivery_at",
                      "last_delivery_status",
                      "last_delivery_error",
                      "created_at",
                      "updated_at"
                    ],
                    "type": "object"
                  },
                  "type": "array"
                }
              }
            },
            "description": "An array of webhook subscriptions",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "List webhook subscriptions",
        "tags": [
          "Webhook Subscriptions"
        ]
      },
      "post": {
        "description": "Subscribes a URL to one or more events. The response includes the signing `secret`; store it to\nverify deliveries. The URL must be publicly reachable over https.\n\nEvents: `customer.created`, `customer.updated`, `customer_card.created`, `stamp.earned`, `stamp.removed`, `reward.unlocked`, `reward.redeemed`, or `*` for all of them.\n",
        "operationId": "post_api_v1_accounts_account_id_webhook_subscriptions",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "description": {
                    "description": "Your own label, up to 255 characters",
                    "type": "string"
                  },
                  "enabled": {
                    "description": "Create the subscription disabled by passing false (defaults to true)",
                    "type": "boolean"
                  },
                  "event": {
                    "description": "A single event to subscribe to. Same as `events` with one entry",
                    "type": "string"
                  },
                  "events": {
                    "description": "Events to subscribe to, or `[\"*\"]` for every event. Required unless `event` is given",
                    "items": {
                      "type": "string"
                    },
                    "type": "array"
                  },
                  "payload_format": {
                    "description": "`envelope` (default) or `flat`. `flat` sends the bare data object and cannot be combined with `*`",
                    "type": "string"
                  },
                  "target_url": {
                    "description": "Public https URL that will receive the POST requests",
                    "type": "string"
                  }
                },
                "required": [
                  "target_url"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "description": {
                      "description": "Your own label for the subscription",
                      "type": "string"
                    },
                    "disabled_at": {
                      "description": "ISO 8601 time the subscription was disabled",
                      "type": "string"
                    },
                    "disabled_reason": {
                      "description": "`disabled_by_user`, `failing` or `blocked_address`",
                      "type": "string"
                    },
                    "enabled": {
                      "description": "Whether events are being delivered",
                      "type": "boolean"
                    },
                    "event": {
                      "description": "The event, when there is exactly one (kept for older integrations)",
                      "type": "string"
                    },
                    "events": {
                      "description": "Events delivered to this URL, or `[\"*\"]` for every event",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "id": {
                      "description": "Unique subscription ID",
                      "type": "integer"
                    },
                    "last_delivery_at": {
                      "description": "ISO 8601 time of the most recent delivery attempt",
                      "type": "string"
                    },
                    "last_delivery_error": {
                      "description": "Why the most recent attempt failed",
                      "type": "string"
                    },
                    "last_delivery_status": {
                      "description": "HTTP status your URL returned on the most recent attempt",
                      "type": "number"
                    },
                    "payload_format": {
                      "description": "`envelope` (default) or `flat` (the bare data object, used by Zapier)",
                      "type": "string"
                    },
                    "secret": {
                      "description": "Signing secret (`whsec_...`). Use it to verify the `webhook-signature` header.",
                      "type": "string"
                    },
                    "target_url": {
                      "description": "URL that receives the POST requests",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "events",
                    "event",
                    "target_url",
                    "description",
                    "payload_format",
                    "enabled",
                    "disabled_at",
                    "disabled_reason",
                    "last_delivery_at",
                    "last_delivery_status",
                    "last_delivery_error",
                    "created_at",
                    "updated_at",
                    "secret"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The new webhook subscription, with its secret",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Validation failed – check `errors` for details"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Create a webhook subscription",
        "tags": [
          "Webhook Subscriptions"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/webhook_subscriptions/{id}": {
      "delete": {
        "description": "Stops deliveries and deletes the subscription. This cannot be undone.",
        "operationId": "delete_api_v1_accounts_account_id_webhook_subscriptions_id",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Webhook subscription ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No content. The subscription was deleted.",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store or subscription not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Delete a webhook subscription",
        "tags": [
          "Webhook Subscriptions"
        ]
      },
      "get": {
        "description": "Returns a single subscription, including its signing secret and the result of the most recent delivery.",
        "operationId": "get_api_v1_accounts_account_id_webhook_subscriptions_id",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Webhook subscription ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "description": {
                      "description": "Your own label for the subscription",
                      "type": "string"
                    },
                    "disabled_at": {
                      "description": "ISO 8601 time the subscription was disabled",
                      "type": "string"
                    },
                    "disabled_reason": {
                      "description": "`disabled_by_user`, `failing` or `blocked_address`",
                      "type": "string"
                    },
                    "enabled": {
                      "description": "Whether events are being delivered",
                      "type": "boolean"
                    },
                    "event": {
                      "description": "The event, when there is exactly one (kept for older integrations)",
                      "type": "string"
                    },
                    "events": {
                      "description": "Events delivered to this URL, or `[\"*\"]` for every event",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "id": {
                      "description": "Unique subscription ID",
                      "type": "integer"
                    },
                    "last_delivery_at": {
                      "description": "ISO 8601 time of the most recent delivery attempt",
                      "type": "string"
                    },
                    "last_delivery_error": {
                      "description": "Why the most recent attempt failed",
                      "type": "string"
                    },
                    "last_delivery_status": {
                      "description": "HTTP status your URL returned on the most recent attempt",
                      "type": "number"
                    },
                    "payload_format": {
                      "description": "`envelope` (default) or `flat` (the bare data object, used by Zapier)",
                      "type": "string"
                    },
                    "secret": {
                      "description": "Signing secret (`whsec_...`). Use it to verify the `webhook-signature` header.",
                      "type": "string"
                    },
                    "target_url": {
                      "description": "URL that receives the POST requests",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "events",
                    "event",
                    "target_url",
                    "description",
                    "payload_format",
                    "enabled",
                    "disabled_at",
                    "disabled_reason",
                    "last_delivery_at",
                    "last_delivery_status",
                    "last_delivery_error",
                    "created_at",
                    "updated_at",
                    "secret"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A webhook subscription, with its secret",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store or subscription not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Show a webhook subscription",
        "tags": [
          "Webhook Subscriptions"
        ]
      },
      "patch": {
        "description": "Changes the URL, events, label or payload format, or turns the subscription off and on. Re-enabling a subscription that was disabled for failing clears its failure state.",
        "operationId": "patch_api_v1_accounts_account_id_webhook_subscriptions_id",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Webhook subscription ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "description": {
                    "description": "Your own label, up to 255 characters",
                    "type": "string"
                  },
                  "enabled": {
                    "description": "false to pause deliveries, true to resume them",
                    "type": "boolean"
                  },
                  "event": {
                    "description": "A single event. Same as `events` with one entry",
                    "type": "string"
                  },
                  "events": {
                    "description": "Replaces the list of events, or `[\"*\"]` for every event",
                    "items": {
                      "type": "string"
                    },
                    "type": "array"
                  },
                  "payload_format": {
                    "description": "`envelope` or `flat`",
                    "type": "string"
                  },
                  "target_url": {
                    "description": "Public https URL that will receive the POST requests",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "description": {
                      "description": "Your own label for the subscription",
                      "type": "string"
                    },
                    "disabled_at": {
                      "description": "ISO 8601 time the subscription was disabled",
                      "type": "string"
                    },
                    "disabled_reason": {
                      "description": "`disabled_by_user`, `failing` or `blocked_address`",
                      "type": "string"
                    },
                    "enabled": {
                      "description": "Whether events are being delivered",
                      "type": "boolean"
                    },
                    "event": {
                      "description": "The event, when there is exactly one (kept for older integrations)",
                      "type": "string"
                    },
                    "events": {
                      "description": "Events delivered to this URL, or `[\"*\"]` for every event",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "id": {
                      "description": "Unique subscription ID",
                      "type": "integer"
                    },
                    "last_delivery_at": {
                      "description": "ISO 8601 time of the most recent delivery attempt",
                      "type": "string"
                    },
                    "last_delivery_error": {
                      "description": "Why the most recent attempt failed",
                      "type": "string"
                    },
                    "last_delivery_status": {
                      "description": "HTTP status your URL returned on the most recent attempt",
                      "type": "number"
                    },
                    "payload_format": {
                      "description": "`envelope` (default) or `flat` (the bare data object, used by Zapier)",
                      "type": "string"
                    },
                    "target_url": {
                      "description": "URL that receives the POST requests",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "events",
                    "event",
                    "target_url",
                    "description",
                    "payload_format",
                    "enabled",
                    "disabled_at",
                    "disabled_reason",
                    "last_delivery_at",
                    "last_delivery_status",
                    "last_delivery_error",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The updated webhook subscription",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store or subscription not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Validation failed – check `errors` for details"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Update a webhook subscription",
        "tags": [
          "Webhook Subscriptions"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/webhook_subscriptions/{id}/rotate_secret": {
      "post": {
        "description": "Replaces the subscription's signing secret. Deliveries are signed with the new secret straight away, so update your receiver at the same time.",
        "operationId": "post_api_v1_accounts_account_id_webhook_subscriptions_id_rotate_secret",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Webhook subscription ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "account_id": {
                      "description": "Parent store ID",
                      "type": "integer"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "description": {
                      "description": "Your own label for the subscription",
                      "type": "string"
                    },
                    "disabled_at": {
                      "description": "ISO 8601 time the subscription was disabled",
                      "type": "string"
                    },
                    "disabled_reason": {
                      "description": "`disabled_by_user`, `failing` or `blocked_address`",
                      "type": "string"
                    },
                    "enabled": {
                      "description": "Whether events are being delivered",
                      "type": "boolean"
                    },
                    "event": {
                      "description": "The event, when there is exactly one (kept for older integrations)",
                      "type": "string"
                    },
                    "events": {
                      "description": "Events delivered to this URL, or `[\"*\"]` for every event",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "id": {
                      "description": "Unique subscription ID",
                      "type": "integer"
                    },
                    "last_delivery_at": {
                      "description": "ISO 8601 time of the most recent delivery attempt",
                      "type": "string"
                    },
                    "last_delivery_error": {
                      "description": "Why the most recent attempt failed",
                      "type": "string"
                    },
                    "last_delivery_status": {
                      "description": "HTTP status your URL returned on the most recent attempt",
                      "type": "number"
                    },
                    "payload_format": {
                      "description": "`envelope` (default) or `flat` (the bare data object, used by Zapier)",
                      "type": "string"
                    },
                    "secret": {
                      "description": "Signing secret (`whsec_...`). Use it to verify the `webhook-signature` header.",
                      "type": "string"
                    },
                    "target_url": {
                      "description": "URL that receives the POST requests",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "account_id",
                    "events",
                    "event",
                    "target_url",
                    "description",
                    "payload_format",
                    "enabled",
                    "disabled_at",
                    "disabled_reason",
                    "last_delivery_at",
                    "last_delivery_status",
                    "last_delivery_error",
                    "created_at",
                    "updated_at",
                    "secret"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The webhook subscription, with its new secret",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store or subscription not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Rotate the signing secret",
        "tags": [
          "Webhook Subscriptions"
        ]
      }
    },
    "/api/v1/accounts/{account_id}/webhook_subscriptions/{id}/test": {
      "post": {
        "description": "Immediately sends a signed `webhook.test` event to the subscription's URL and reports what\nhappened, so you can check your endpoint and signature verification without waiting for real\nactivity. Test events are not retried and do not count towards disabling the subscription.\n",
        "operationId": "post_api_v1_accounts_account_id_webhook_subscriptions_id_test",
        "parameters": [
          {
            "description": "Store (account) ID",
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "Webhook subscription ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "delivered": {
                      "description": "True when your URL responded with a 2xx status",
                      "type": "boolean"
                    },
                    "error": {
                      "description": "Why the delivery failed",
                      "type": "string"
                    },
                    "event_id": {
                      "description": "The `webhook-id` of the test event",
                      "type": "string"
                    },
                    "status": {
                      "description": "HTTP status your URL returned",
                      "type": "number"
                    }
                  },
                  "required": [
                    "delivered",
                    "status",
                    "event_id",
                    "error"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The outcome of the test delivery",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store or subscription not found"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Send a test event",
        "tags": [
          "Webhook Subscriptions"
        ]
      }
    },
    "/api/v1/accounts/{id}": {
      "get": {
        "description": "Returns detailed information for a single store, including summary counts for its associated resources.",
        "operationId": "get_api_v1_accounts_id",
        "parameters": [
          {
            "description": "Store ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "cards_count": {
                      "description": "Number of loyalty card templates",
                      "type": "integer"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "customers_count": {
                      "description": "Number of enrolled customers",
                      "type": "integer"
                    },
                    "display_store_name": {
                      "description": "Resolved display name (store_name if present, otherwise name)",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique store ID",
                      "type": "integer"
                    },
                    "locations_count": {
                      "description": "Number of physical locations",
                      "type": "integer"
                    },
                    "name": {
                      "description": "Internal account name",
                      "type": "string"
                    },
                    "personal": {
                      "description": "Whether this is the user's personal account",
                      "type": "boolean"
                    },
                    "posters_count": {
                      "description": "Number of QR signup posters",
                      "type": "integer"
                    },
                    "store_name": {
                      "description": "Public-facing store name",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "store_name",
                    "display_store_name",
                    "personal",
                    "locations_count",
                    "cards_count",
                    "customers_count",
                    "posters_count",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "A store object",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store not found – the authenticated user does not have access to this store"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Show a store",
        "tags": [
          "Stores"
        ]
      },
      "patch": {
        "description": "Updates the store's name or store_name. Use `store_name` for the public-facing name displayed to customers.",
        "operationId": "patch_api_v1_accounts_id",
        "parameters": [
          {
            "description": "Store ID",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": false,
                "properties": {
                  "account": {
                    "additionalProperties": false,
                    "properties": {
                      "name": {
                        "description": "Internal account name",
                        "type": "string"
                      },
                      "store_name": {
                        "description": "Public-facing store name shown to customers",
                        "type": "string"
                      }
                    },
                    "type": "object"
                  }
                },
                "required": [
                  "account"
                ],
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "cards_count": {
                      "description": "Number of loyalty card templates",
                      "type": "integer"
                    },
                    "created_at": {
                      "description": "ISO 8601 creation timestamp",
                      "type": "string"
                    },
                    "customers_count": {
                      "description": "Number of enrolled customers",
                      "type": "integer"
                    },
                    "display_store_name": {
                      "description": "Resolved display name (store_name if present, otherwise name)",
                      "type": "string"
                    },
                    "id": {
                      "description": "Unique store ID",
                      "type": "integer"
                    },
                    "locations_count": {
                      "description": "Number of physical locations",
                      "type": "integer"
                    },
                    "name": {
                      "description": "Internal account name",
                      "type": "string"
                    },
                    "personal": {
                      "description": "Whether this is the user's personal account",
                      "type": "boolean"
                    },
                    "posters_count": {
                      "description": "Number of QR signup posters",
                      "type": "integer"
                    },
                    "store_name": {
                      "description": "Public-facing store name",
                      "type": "string"
                    },
                    "updated_at": {
                      "description": "ISO 8601 last-update timestamp",
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "store_name",
                    "display_store_name",
                    "personal",
                    "locations_count",
                    "cards_count",
                    "customers_count",
                    "posters_count",
                    "created_at",
                    "updated_at"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The updated store object",
            "headers": {}
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unauthorized – invalid or missing API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Store not found – the authenticated user does not have access to this store"
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Validation failed – check the `errors` object for details"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Update a store",
        "tags": [
          "Stores"
        ]
      }
    },
    "/api/v1/status": {
      "get": {
        "description": "Returns the status of the API. No authentication required.\n\nEvery response from this API, including this one, carries `RateLimit-Limit`,\n`RateLimit-Remaining`, `RateLimit-Reset` and `RateLimit-Policy`. Exceeding\nthe limit returns 429 with `Retry-After` in seconds.\n",
        "operationId": "get_api_v1_status",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": false,
                  "properties": {
                    "api_version": {
                      "description": "Current API version",
                      "type": "string"
                    },
                    "authentication": {
                      "description": "How to authenticate a request",
                      "type": "string"
                    },
                    "developer_portal_url": {
                      "description": "Developer portal: quickstart, auth, webhooks",
                      "type": "string"
                    },
                    "documentation_url": {
                      "description": "Human readable API reference",
                      "type": "string"
                    },
                    "openapi_url": {
                      "description": "OpenAPI description of this API",
                      "type": "string"
                    },
                    "rate_limit": {
                      "additionalProperties": false,
                      "properties": {
                        "limit": {
                          "description": "Requests allowed per window",
                          "type": "integer"
                        },
                        "scope": {
                          "description": "What the limit is counted against",
                          "type": "string"
                        },
                        "window_seconds": {
                          "description": "Length of the window in seconds",
                          "type": "integer"
                        }
                      },
                      "required": [
                        "limit",
                        "window_seconds",
                        "scope"
                      ],
                      "type": "object"
                    },
                    "status": {
                      "description": "'ok' while the API is serving requests",
                      "type": "string"
                    },
                    "versioning": {
                      "additionalProperties": false,
                      "properties": {
                        "current": {
                          "description": "The version to build against",
                          "type": "string"
                        },
                        "deprecated": {
                          "description": "Versions that are deprecated but still serving",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "policy_url": {
                          "description": "The published versioning and deprecation policy",
                          "type": "string"
                        },
                        "signalling": {
                          "description": "The headers a deprecated version sends",
                          "type": "string"
                        },
                        "supported": {
                          "description": "Every version still serving requests",
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        }
                      },
                      "required": [
                        "current",
                        "supported",
                        "deprecated",
                        "policy_url",
                        "signalling"
                      ],
                      "type": "object"
                    }
                  },
                  "required": [
                    "status",
                    "api_version",
                    "documentation_url",
                    "openapi_url",
                    "developer_portal_url",
                    "authentication",
                    "rate_limit",
                    "versioning"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The service status",
            "headers": {}
          },
          "410": {
            "$ref": "#/components/responses/VersionSunset"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "summary": "Service status",
        "tags": [
          "Status"
        ]
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "servers": [
    {
      "description": "Production",
      "url": "https://app.tryleal.dev"
    }
  ],
  "tags": [
    {
      "description": "In this API, every Account represents a Store. Stores are the top-level tenant\nobject that owns locations, loyalty cards, customers, and posters.\n\nEach authenticated user may belong to one or more stores. Use these endpoints\nto list the stores you have access to, view store details (including summary\ncounts), and update store settings.\n",
      "name": "Stores"
    },
    {
      "description": "Cards are loyalty stamp card templates that define the look, feel, and rules\nfor a store's loyalty program. Each card specifies how many stamps are required,\nwhich icon to use, the colour scheme, and the strip image style.\n\nCustomers receive individual instances of a card (CustomerCards) and collect\nstamps toward rewards. A store may have multiple active card templates\n(e.g. a coffee card and a haircut card).\n\nCards can be archived to hide them from the default listing without deleting\nhistorical data. Use the `scope` query parameter on the index endpoint to\ncontrol which cards are returned.\n\nAll card endpoints are scoped to a store via the `:account_id` URL parameter.\n",
      "name": "Cards"
    },
    {
      "description": "Customer cards represent a customer's instance of a loyalty card template. They track\nstamp progress, status, and wallet pass installation. Use these endpoints to view a\ncustomer's enrolled loyalty cards and their current progress toward rewards.\n",
      "name": "Customer Cards"
    },
    {
      "description": "Customers represent the people who visit your store and participate in your loyalty program.\nEach customer requires a `first_name` and at least one of `email` or `phone`. Both `email`\nand `phone` are unique within a store. Customers can be enrolled in loyalty cards and have\ntheir stamp counts managed through this API.\n\nExternal references and metadata\n\nEvery customer can carry two kinds of integration-friendly data so you can match them up with\nrecords in other systems (Square, Shopify, Mailchimp, your own POS, etc.) without depending on\nemail or phone:\n\n`external_references`: a list of `source`/`external_id` pairs. `source` is a free-form\nlowercase slug that identifies the foreign system (e.g. `square`, `shopify`,\n`mailchimp`, `hubspot`, or anything custom like `my_pos`). Each\n`source`/`external_id` pair is unique per store, indexed for fast lookups, and can be used\nto find or upsert a customer.\n\n`metadata`: a free-form JSON object for any other per-customer data you want to attach\n(preferred drink, segment tags, \"last seen at counter\", etc.). Not indexed; not unique;\nmerged on update.\n\nUse `GET /customers?source=...&external_id=...` to look up a customer by an external\nreference.\n",
      "name": "Customers"
    },
    {
      "description": "Locations represent the physical addresses of a store. Each store can have\nmultiple locations (e.g. branches, pop-ups).\n\nWhen you create or update a location with an address, the address is\nautomatically geocoded to latitude/longitude coordinates. These coordinates\nare used for Apple Wallet relevance - customers receive lock-screen\nnotifications when they are near one of your locations.\n\nAll location endpoints are scoped to a store via the `:account_id` URL\nparameter. You must have access to the parent store.\n",
      "name": "Locations"
    },
    {
      "description": "Posters are printable QR code signup sheets that customers scan to join your loyalty program.\nEach poster is tied to a loyalty card and generates a unique public signup URL. Posters can be\ncustomized with colors, titles, and paper sizes to match your store branding.\n",
      "name": "Posters"
    },
    {
      "description": "Rewards are redeemable milestones tied to a loyalty card. When a customer reaches the\nrequired number of stamps, they become eligible to redeem the reward. Each reward belongs\nto a specific card.\n",
      "name": "Rewards"
    },
    {
      "description": "A single unauthenticated endpoint. Use it to check that the API is\nreachable, to discover the documentation and the OpenAPI description, and\nto read the rate limit headers before you start making authenticated\ncalls.\n",
      "name": "Status"
    },
    {
      "description": "A webhook subscription tells Leal to POST a JSON payload to your URL whenever an event\nhappens in the store, so you don't have to poll. Subscribe to a list of `events`, or to\n`[\"*\"]` for every event (including ones added later). The full guide, with payload examples and\nsignature verification code, is at https://www.tryleal.dev/developers/webhooks.\n\nEvents\n\n- `customer.created`: A customer joined the loyalty program.\n- `customer.updated`: A customer's name, email, phone, birthday, metadata or marketing and SMS consent changed.\n- `customer_card.created`: A customer was issued a loyalty card. Includes the Apple Wallet and Google Wallet links.\n- `stamp.earned`: Stamps were added to a customer's card, from a scan, the API or an adjustment.\n- `stamp.removed`: Stamps were taken off a customer's card by an adjustment. Redeeming a reward sends reward.redeemed instead.\n- `reward.unlocked`: A customer now has enough stamps to redeem a reward. Sent once per reward, when the threshold is crossed.\n- `reward.redeemed`: A customer redeemed a reward.\n\nPayload\n\nEach delivery is an envelope: `{\"id\": \"evt_...\", \"type\": \"stamp.earned\", \"timestamp\": \"...\",\n\"account_id\": 1, \"data\": {...}}`. `id` is unique per event and stays the same across\nretries, so use it to ignore duplicates. `customer.updated` also carries\n`previous_attributes` with the old values of the fields that changed.\n\nSubscriptions created from Zapier (and all subscriptions created before signing was\nintroduced) use `payload_format: \"flat\"`, which sends the `data` object on its own. The\nevent name is still available in the `Leal-Event` header. A flat subscription has exactly\none event.\n\nOlder integrations send and read a single `event` string. That still works: `event` sets\n`events` to that one event, and responses include `event` whenever there is exactly one.\n\nVerifying requests\n\nEvery delivery is signed using the Standard Webhooks scheme (https://www.standardwebhooks.com)\nwith the subscription's `secret`, via the `webhook-id`, `webhook-timestamp` and\n`webhook-signature` headers. Any Standard Webhooks library can verify it.\n\nRetries\n\nRespond with any 2xx status within 10 seconds. Anything else, or no response, is retried\nwith increasing delays, up to 10 attempts over about four hours.\nResponding `410 Gone` deletes the subscription. A subscription that has not had a\nsuccessful delivery for 3 days is disabled\n(`enabled: false`, `disabled_reason: \"failing\"`); re-enable it with `PATCH` once fixed.\n",
      "name": "Webhook Subscriptions"
    }
  ]
}
