{
  "openapi": "3.1.0",
  "info": {
    "title": "Zapiet Website API",
    "version": "1.0.0",
    "description": "Public API for the Zapiet.com marketing website. Use these endpoints for contact form submissions and newsletter signups. There is no machine-to-machine authentication; forms are protected with reCAPTCHA.\n\nZapiet's product APIs — the Widget API used inside a Shopify storefront and the Last Mile Delivery API for couriers — are documented separately; see `externalDocs`.\n\n## Versioning\n\nVersioning is by URL path: `https://zapiet.com/api/v1/<endpoint>`. A backwards-incompatible change to a request or response shape ships as a new path prefix (`/api/v2/`) and never mutates one already in use. Additive changes — a new optional field, a new error `code`, a new endpoint — can land within a version, so clients must ignore response fields they do not recognise rather than fail on them.\n\nThe unversioned paths (`/api/contact-form`, `/api/newsletter-signup`) are what this website's own forms post to. They are documented here and marked deprecated: they keep working indefinitely, but only the `/api/v1/` paths carry the compatibility promise above.\n\n## Deprecation policy\n\nA version being retired is signalled on the responses themselves, per RFC 8594 and RFC 9745:\n\n- `Deprecation` appears as soon as a version is deprecated.\n- `Sunset` gives the date after which the version stops responding.\n- `Link: <successor-url>; rel=\"successor-version\"` points at the replacement.\n\nA deprecated version keeps responding for at least 12 months after `Deprecation` first appears. No version has been deprecated to date, so no live response carries these headers.\n\n## Rate limits\n\n30 requests per 60 seconds per client IP per endpoint. Every response carries `RateLimit`, `RateLimit-Policy` and the discrete `RateLimit-Limit`/`-Remaining`/`-Reset` headers; a 429 adds `Retry-After`. Read `RateLimit-Remaining` and pace requests rather than retrying into a 429.\n\n## Errors\n\nEvery error — including 404 and 405 — returns the RFC 7807 `ProblemDetails` shape below, never an HTML page. Branch on the stable `code` field; `title`, `detail` and `hint` are human-readable and may change. Each `type` URI resolves to a description of that problem class.",
    "contact": {
      "name": "Zapiet support",
      "url": "https://zapiet.com/contact"
    }
  },
  "externalDocs": {
    "description": "Zapiet developer resources",
    "url": "https://zapiet.com/developers"
  },
  "servers": [
    {
      "url": "https://zapiet.com"
    }
  ],
  "tags": [
    {
      "name": "Contact",
      "description": "Contact form submissions"
    },
    {
      "name": "Newsletter",
      "description": "Newsletter signups"
    },
    {
      "name": "Discovery",
      "description": "API discovery documents"
    }
  ],
  "paths": {
    "/api/v1/contact-form": {
      "post": {
        "tags": [
          "Contact"
        ],
        "summary": "Submit the contact form",
        "description": "Creates or updates a contact in Zapiet's helpdesk and opens a support ticket from the message. Requires a reCAPTCHA v3 token for the `contact_form_submit` action, so it is intended for the form at /contact rather than for unattended clients. An agent wanting to reach a human should point the user at that page.",
        "operationId": "submitContactFormV1",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "firstName",
                  "lastName",
                  "message",
                  "helpWith",
                  "recaptchaToken"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "firstName": {
                    "type": "string",
                    "minLength": 1
                  },
                  "lastName": {
                    "type": "string",
                    "minLength": 1
                  },
                  "message": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The body of the enquiry."
                  },
                  "helpWith": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Enquiry topic, used as the ticket title."
                  },
                  "telephone": {
                    "type": "string",
                    "description": "Optional contact phone number, E.164 preferred."
                  },
                  "company": {
                    "type": "string",
                    "description": "Optional company name."
                  },
                  "recaptchaToken": {
                    "type": "string",
                    "description": "reCAPTCHA v3 token obtained in the browser for the `contact_form_submit` action."
                  },
                  "recaptchaAction": {
                    "type": "string",
                    "const": "contact_form_submit",
                    "description": "Optional. When present it must equal `contact_form_submit`."
                  }
                }
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "firstName",
                  "lastName",
                  "message",
                  "helpWith",
                  "recaptchaToken"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "firstName": {
                    "type": "string",
                    "minLength": 1
                  },
                  "lastName": {
                    "type": "string",
                    "minLength": 1
                  },
                  "message": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The body of the enquiry."
                  },
                  "helpWith": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Enquiry topic, used as the ticket title."
                  },
                  "telephone": {
                    "type": "string",
                    "description": "Optional contact phone number, E.164 preferred."
                  },
                  "company": {
                    "type": "string",
                    "description": "Optional company name."
                  },
                  "recaptchaToken": {
                    "type": "string",
                    "description": "reCAPTCHA v3 token obtained in the browser for the `contact_form_submit` action."
                  },
                  "recaptchaAction": {
                    "type": "string",
                    "const": "contact_form_submit",
                    "description": "Optional. When present it must equal `contact_form_submit`."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contact form submitted successfully",
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "message",
                    "contactId",
                    "ticketId"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "contactId": {
                      "type": "string"
                    },
                    "ticketId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "405": {
            "description": "Method Not Allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "Allow": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After` gives the seconds to wait.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              }
            }
          },
          "502": {
            "description": "Upstream Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/newsletter-signup": {
      "post": {
        "tags": [
          "Newsletter"
        ],
        "summary": "Subscribe to the newsletter",
        "description": "Adds the address to Zapiet's product and Shopify-fulfilment newsletter. Idempotent: submitting an address that is already subscribed succeeds without creating a duplicate. Only submit an address whose owner has asked to be subscribed.",
        "operationId": "subscribeNewsletterV1",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Address to subscribe. Must belong to someone who asked to be subscribed."
                  }
                }
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Address to subscribe. Must belong to someone who asked to be subscribed."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Newsletter subscription successful",
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "message",
                    "contactId"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "contactId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "405": {
            "description": "Method Not Allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "Allow": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After` gives the seconds to wait.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              }
            }
          },
          "502": {
            "description": "Upstream Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/contact-form": {
      "post": {
        "tags": [
          "Contact"
        ],
        "summary": "Submit the contact form",
        "description": "Creates or updates a contact in Zapiet's helpdesk and opens a support ticket from the message. Requires a reCAPTCHA v3 token for the `contact_form_submit` action, so it is intended for the form at /contact rather than for unattended clients. An agent wanting to reach a human should point the user at that page.",
        "operationId": "submitContactForm",
        "deprecated": true,
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "firstName",
                  "lastName",
                  "message",
                  "helpWith",
                  "recaptchaToken"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "firstName": {
                    "type": "string",
                    "minLength": 1
                  },
                  "lastName": {
                    "type": "string",
                    "minLength": 1
                  },
                  "message": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The body of the enquiry."
                  },
                  "helpWith": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Enquiry topic, used as the ticket title."
                  },
                  "telephone": {
                    "type": "string",
                    "description": "Optional contact phone number, E.164 preferred."
                  },
                  "company": {
                    "type": "string",
                    "description": "Optional company name."
                  },
                  "recaptchaToken": {
                    "type": "string",
                    "description": "reCAPTCHA v3 token obtained in the browser for the `contact_form_submit` action."
                  },
                  "recaptchaAction": {
                    "type": "string",
                    "const": "contact_form_submit",
                    "description": "Optional. When present it must equal `contact_form_submit`."
                  }
                }
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "firstName",
                  "lastName",
                  "message",
                  "helpWith",
                  "recaptchaToken"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "firstName": {
                    "type": "string",
                    "minLength": 1
                  },
                  "lastName": {
                    "type": "string",
                    "minLength": 1
                  },
                  "message": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The body of the enquiry."
                  },
                  "helpWith": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Enquiry topic, used as the ticket title."
                  },
                  "telephone": {
                    "type": "string",
                    "description": "Optional contact phone number, E.164 preferred."
                  },
                  "company": {
                    "type": "string",
                    "description": "Optional company name."
                  },
                  "recaptchaToken": {
                    "type": "string",
                    "description": "reCAPTCHA v3 token obtained in the browser for the `contact_form_submit` action."
                  },
                  "recaptchaAction": {
                    "type": "string",
                    "const": "contact_form_submit",
                    "description": "Optional. When present it must equal `contact_form_submit`."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contact form submitted successfully",
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "message",
                    "contactId",
                    "ticketId"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "contactId": {
                      "type": "string"
                    },
                    "ticketId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "405": {
            "description": "Method Not Allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "Allow": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After` gives the seconds to wait.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              }
            }
          },
          "502": {
            "description": "Upstream Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/newsletter-signup": {
      "post": {
        "tags": [
          "Newsletter"
        ],
        "summary": "Subscribe to the newsletter",
        "description": "Adds the address to Zapiet's product and Shopify-fulfilment newsletter. Idempotent: submitting an address that is already subscribed succeeds without creating a duplicate. Only submit an address whose owner has asked to be subscribed.",
        "operationId": "subscribeNewsletter",
        "deprecated": true,
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Address to subscribe. Must belong to someone who asked to be subscribed."
                  }
                }
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Address to subscribe. Must belong to someone who asked to be subscribed."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Newsletter subscription successful",
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "message",
                    "contactId"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "contactId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "405": {
            "description": "Method Not Allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "Allow": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After` gives the seconds to wait.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              }
            }
          },
          "502": {
            "description": "Upstream Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "tags": [
          "Discovery"
        ],
        "summary": "OpenAPI specification",
        "description": "This document. Returns the OpenAPI 3.1 description of every endpoint on this API, regenerated per request so the origin in `servers` matches the host you fetched it from.",
        "operationId": "openApiSpecification",
        "responses": {
          "200": {
            "description": "OpenAPI 3.1 document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "405": {
            "description": "Method Not Allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "Allow": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. `Retry-After` gives the seconds to wait.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "RateLimit": {
                "description": "Combined rate-limit state for this endpoint, e.g. `limit=30, remaining=29, reset=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "The advertised policy, `30;w=60`.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Requests permitted per window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the current window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "API-Version": {
                "description": "Version of the API surface that produced this response.",
                "schema": {
                  "type": "string",
                  "examples": [
                    "v1"
                  ]
                }
              }
            }
          },
          "502": {
            "description": "Upstream Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "tags": [
          "Discovery"
        ],
        "summary": "Model Context Protocol endpoint",
        "description": "Read-only MCP server over the Streamable HTTP transport, exposing Zapiet's app catalogue, published pricing and site content as tools. Speaks JSON-RPC 2.0 rather than REST, so the request and response bodies are described by the MCP specification rather than here; the manifest at /.well-known/mcp.json lists the available tools.",
        "operationId": "modelContextProtocolEndpoint",
        "requestBody": {
          "required": true,
          "description": "A single JSON-RPC 2.0 request object.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC 2.0 response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "202": {
            "description": "Notification accepted; no body returned."
          },
          "405": {
            "description": "GET is not supported: this server opens no SSE stream.",
            "headers": {
              "Allow": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ProblemDetails": {
        "type": "object",
        "description": "RFC 7807 Problem Details. Returned by every failing request on an /api path, whatever the status code.",
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code",
          "hint",
          "error",
          "success"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "URI identifying the problem class; resolves to a description of it."
          },
          "title": {
            "type": "string",
            "description": "Short, human-readable summary."
          },
          "status": {
            "type": "integer",
            "description": "Mirrors the HTTP status code."
          },
          "detail": {
            "type": "string",
            "description": "Human-readable explanation for this occurrence."
          },
          "code": {
            "type": "string",
            "enum": [
              "method_not_allowed",
              "validation_error",
              "unauthorized",
              "not_found",
              "not_configured",
              "upstream_error",
              "internal_error",
              "invalid_json",
              "rate_limited"
            ],
            "description": "Stable machine-readable cause. Branch on this, not on the prose fields."
          },
          "hint": {
            "type": "string",
            "description": "What to change to make the request succeed, or whether a retry is worthwhile."
          },
          "error": {
            "type": "string",
            "description": "Deprecated duplicate of `detail`, kept for older clients. Read `detail`.",
            "deprecated": true
          },
          "success": {
            "type": "boolean",
            "enum": [
              false
            ]
          }
        }
      }
    }
  }
}