{
  "openapi": "3.1.0",
  "info": {
    "title": "IMPACT NYC 2026 sleeve orders",
    "version": "1.0.0",
    "description": "Order the custom laptop sleeve at IMPACT NYC 2026, Spring Studios, New York.\n\n1. GET /api/sleeve-options for the current sizes, fonts, threads and charLimit. They change during the event; never assume them.\n2. POST /api/orders. The order is held unpaid for 5 minutes. Tell the user the deadline (holdUntilText).\n3. Pay the way the user chose: their own card or wallet through payUrl ($1.00, all payments will be refunded), or POST /api/orders/{orderNumber}/pay with method forter_card (nothing is charged).\n4. GET /api/orders/{orderNumber}?t=<payToken> to check the status.\n\nBefore POST /api/orders, confirm size, font, thread, stitchText, name and email with the user. Spell stitchText back: embroidery is permanent. Choose an option for the user only if they asked you to.\nAsk the user how to pay - never choose for them. Offer both: (a) their own card or wallet (Link, Apple Pay, Google Pay) through payUrl - $1.00, all payments will be refunded; (b) the Forter card - a demo payment, nothing is charged. Then confirm the payment with the user, unless their own settings let you pay without asking.\n\nOrder and pay responses have message and nextAction: relay message to the user and follow nextAction.\nAn order not paid within 5 minutes is cancelled (reason \"not paid within 5 minutes\"); the same email can then order again.\nPaid orders are collected at the Order Pickup station (5th Floor, by Mini Golf) on Wednesday 14 October, giving first and last name.\nErrors are {ok: false, code, error, retryable}. Relay error. Retry only when retryable is true.\nEvent information (agenda, speakers, venue, food, swag): GET /llms-full.txt."
  },
  "servers": [
    {
      "url": "https://impact-26-ny.forter.com"
    }
  ],
  "paths": {
    "/api/sleeve-options": {
      "get": {
        "operationId": "getSleeveOptions",
        "summary": "Current sleeve sizes, fonts, threads and stitch text limit",
        "security": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SleeveOptions"
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "internal",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/orders": {
      "post": {
        "operationId": "createOrder",
        "summary": "Order a sleeve; it is held unpaid until paid or the hold ends",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderInput"
              }
            }
          }
        },
        "security": [],
        "responses": {
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "400": {
            "description": "bad_request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "duplicate",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "validation_failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "internal",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/orders/{orderNumber}/pay": {
      "post": {
        "operationId": "payOrder",
        "summary": "Pay for a held order",
        "parameters": [
          {
            "name": "orderNumber",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PayInput"
              }
            }
          }
        },
        "security": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PayResult"
                }
              }
            }
          },
          "400": {
            "description": "bad_request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "declined",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "not_found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "internal",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "payment_unknown or payment_error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/orders/{orderNumber}": {
      "get": {
        "operationId": "getOrder",
        "summary": "An order's current status",
        "parameters": [
          {
            "name": "orderNumber",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]+$"
            }
          },
          {
            "name": "t",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The payToken."
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "404": {
            "description": "not_found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "internal",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/llms-full.txt": {
      "get": {
        "operationId": "getEventInfo",
        "summary": "Agenda, speakers, venue, food and swag, as plain text",
        "security": [],
        "responses": {
          "200": {
            "description": "Plain text.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "OrderInput": {
        "type": "object",
        "required": [
          "email",
          "name",
          "size",
          "font",
          "thread",
          "stitchText"
        ],
        "properties": {
          "email": {
            "type": "string",
            "maxLength": 254,
            "description": "The user's email: one ordinary address with no spaces, quotes, commas or brackets. One order per email."
          },
          "name": {
            "type": "string",
            "maxLength": 40,
            "description": "First and last name, checked at pickup: letters, spaces, apostrophes, hyphens or full stops, up to 40 characters and 5 words, with no links or web addresses."
          },
          "size": {
            "type": "string",
            "description": "one of the values GET /api/sleeve-options returns right now (sizes)."
          },
          "font": {
            "type": "string",
            "description": "one of the values GET /api/sleeve-options returns right now (fonts)."
          },
          "thread": {
            "type": "string",
            "description": "one of the values GET /api/sleeve-options returns right now (threads)."
          },
          "stitchText": {
            "type": "string",
            "pattern": "^[A-Za-z0-9][A-Za-z0-9 .\\-&]*$",
            "description": "The embroidered text: letters, numbers, spaces, . - and &, starting with a letter or number, at most charLimit characters."
          }
        }
      },
      "PayInput": {
        "type": "object",
        "required": [
          "t",
          "method"
        ],
        "properties": {
          "t": {
            "type": "string",
            "description": "The payToken from createOrder or getOrder."
          },
          "method": {
            "type": "string",
            "enum": [
              "card",
              "forter_card",
              "wallet"
            ],
            "description": "forter_card: the Forter demo card, nothing is charged; send no token. Use it only when the user chose it. card: needs a Forter Hosted Fields token; only the payUrl page creates one - open payUrl if you can complete a web checkout with the user's card, otherwise give payUrl to the user. wallet: needs a Stripe ConfirmationToken from Apple Pay, Google Pay or Link; only the payUrl page creates one - open payUrl if you can complete a web checkout with the user's card, otherwise give payUrl to the user."
          },
          "token": {
            "type": "string",
            "description": "Only for card and wallet. Omit for forter_card."
          }
        }
      },
      "SleeveOptions": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "sizes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Valid size values."
          },
          "fonts": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Valid font values."
          },
          "threads": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Valid thread values."
          },
          "charLimit": {
            "type": "integer",
            "description": "Maximum stitchText length."
          },
          "sizeChoices": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string"
                },
                "image": {
                  "type": "string"
                }
              }
            },
            "description": "The same values with preview images, for chat widgets. Agents can ignore them."
          },
          "fontChoices": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string"
                },
                "image": {
                  "type": "string"
                }
              }
            },
            "description": "The same values with preview images, for chat widgets. Agents can ignore them."
          },
          "threadChoices": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string"
                },
                "image": {
                  "type": "string"
                }
              }
            },
            "description": "The same values with preview images, for chat widgets. Agents can ignore them."
          }
        }
      },
      "Order": {
        "type": "object",
        "required": [
          "ok",
          "orderNumber",
          "status",
          "order",
          "message",
          "nextAction"
        ],
        "properties": {
          "ok": {
            "const": true
          },
          "duplicate": {
            "const": false
          },
          "orderNumber": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "awaiting payment",
              "received",
              "in progress",
              "ready",
              "collected",
              "cancelled"
            ]
          },
          "holdUntil": {
            "type": "string",
            "format": "date-time",
            "description": "Only while awaiting payment."
          },
          "holdUntilText": {
            "type": "string",
            "description": "The deadline in New York time, for the user. Only while awaiting payment."
          },
          "secondsLeft": {
            "type": "integer",
            "description": "Only while awaiting payment."
          },
          "payUrl": {
            "type": "string",
            "description": "A page where the user pays by card, Apple Pay, Google Pay or Link. Only while awaiting payment."
          },
          "payToken": {
            "type": "string",
            "description": "Pass as t to getOrder and payOrder. Only while awaiting payment; keep it from the first response."
          },
          "payLabel": {
            "const": "Pay $1.00 - all payments will be refunded"
          },
          "payButtonLabel": {
            "type": "string"
          },
          "reason": {
            "const": "not paid within 5 minutes",
            "description": "Only when cancelled for non-payment."
          },
          "order": {
            "type": "object",
            "properties": {
              "size": {
                "type": "string"
              },
              "font": {
                "type": "string"
              },
              "thread": {
                "type": "string"
              },
              "stitchText": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "enum": [
                  "awaiting payment",
                  "received",
                  "in progress",
                  "ready",
                  "collected",
                  "cancelled"
                ]
              }
            }
          },
          "message": {
            "type": "string",
            "description": "Relay to the user."
          },
          "nextAction": {
            "type": "string",
            "description": "What to do next. Follow it."
          }
        }
      },
      "PayResult": {
        "type": "object",
        "required": [
          "ok",
          "orderNumber",
          "status",
          "alreadyPaid",
          "message",
          "nextAction"
        ],
        "properties": {
          "ok": {
            "const": true
          },
          "orderNumber": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "awaiting payment",
              "received",
              "in progress",
              "ready",
              "collected",
              "cancelled"
            ]
          },
          "alreadyPaid": {
            "type": "boolean",
            "description": "True when an earlier attempt already paid. Never pay again."
          },
          "message": {
            "type": "string",
            "description": "Relay to the user."
          },
          "nextAction": {
            "type": "string",
            "description": "What to do next. Follow it."
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "ok",
          "code",
          "error",
          "retryable"
        ],
        "properties": {
          "ok": {
            "const": false
          },
          "code": {
            "type": "string",
            "enum": [
              "validation_failed",
              "duplicate",
              "rate_limited",
              "not_found",
              "bad_request",
              "cancelled",
              "declined",
              "payment_unknown",
              "payment_error",
              "unavailable",
              "internal",
              "unauthorized"
            ]
          },
          "error": {
            "type": "string",
            "description": "Relay to the user."
          },
          "retryable": {
            "type": "boolean",
            "description": "Retry only when true."
          },
          "reason": {
            "const": "not paid within 5 minutes",
            "description": "On cancelled, when the hold ran out."
          },
          "duplicate": {
            "const": true,
            "description": "On duplicate. While the existing order is still held, the hold fields, orderNumber, status, message and nextAction of that order are here too."
          },
          "holdUntil": {
            "type": "string",
            "format": "date-time",
            "description": "Only while awaiting payment."
          },
          "holdUntilText": {
            "type": "string",
            "description": "The deadline in New York time, for the user. Only while awaiting payment."
          },
          "secondsLeft": {
            "type": "integer",
            "description": "Only while awaiting payment."
          },
          "payUrl": {
            "type": "string",
            "description": "A page where the user pays by card, Apple Pay, Google Pay or Link. Only while awaiting payment."
          },
          "payToken": {
            "type": "string",
            "description": "Pass as t to getOrder and payOrder. Only while awaiting payment; keep it from the first response."
          },
          "payLabel": {
            "const": "Pay $1.00 - all payments will be refunded"
          },
          "payButtonLabel": {
            "type": "string"
          }
        }
      }
    }
  }
}
