{
  "openapi": "3.1.0",
  "info": {
    "title": "Alla hjärtans dag-presenter – curated gift wishlist API",
    "version": "0.1.0",
    "description": "Create a gift wishlist for Valentine's Day (Alla hjärtans dag) in seconds from curated amazon.se (Sweden) and amazon.com (US) products — carefully selected, hand-picked gift ideas with shareable owner + shopper links. Curated by us (no customer reviews or ratings). Keywords: gift ideas, wishlist, gift list, shopping list, presenttips, önskelista, alla hjärtans dag. Quickstart: POST /api/v1/agent/create-and-fill → shopUrl. Valentine gift shopping lists, wishlists, and recommendation lists. Curated Amazon product /dp/ links when ASIN known (catalogMode=asin); romantic search deep-links otherwise. amazon.se product links include ?tag=sw-valentine-21 and amazon.com (US) product links include ?tag=sw-valentine-20 (separate curated US catalog via marketplace=amazon.com); other storefronts are untagged — never invent tags or reuse santawishli03-21 / girlfriendgift-21. Prefer buyUrl + trackingTag (affiliateUrl / affiliateTag are deprecated aliases). Pass marketplace+locale. CORS * on /api/v1/*.",
    "contact": {
      "name": "maggat",
      "url": "https://valentines-day-gifts.vercel.app"
    }
  },
  "servers": [
    {
      "url": "https://valentines-day-gifts.vercel.app"
    }
  ],
  "tags": [
    {
      "name": "search"
    },
    {
      "name": "wishlists"
    },
    {
      "name": "catalog"
    },
    {
      "name": "agent"
    },
    {
      "name": "meta"
    }
  ],
  "paths": {
    "/api/v1/health": {
      "get": {
        "tags": [
          "meta"
        ],
        "summary": "Health check",
        "operationId": "getHealth",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/catalog": {
      "get": {
        "tags": [
          "catalog"
        ],
        "summary": "Paginated gift catalog; /dp on amazon.se and amazon.com, search-ideas elsewhere",
        "operationId": "getCatalog",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "Full-text search",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "occasion",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Occasion"
            }
          },
          {
            "name": "interest",
            "in": "query",
            "description": "Single interest filter",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "categories",
            "in": "query",
            "description": "Comma-separated categories",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "marketplace",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Amazon storefront domain or id (e.g. amazon.com, amazon.se, se). REQUIRED for correct user locale/store — agents MUST pass the user's marketplace."
          },
          {
            "name": "domain",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Alias for marketplace"
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "sv",
                "de",
                "fr",
                "es"
              ]
            },
            "description": "UI/search cue locale. Agents MUST pass the user's locale."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 48,
              "maximum": 100
            },
            "description": "Page size (default 48, max 100)"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Pagination offset"
          }
        ],
        "responses": {
          "200": {
            "description": "Catalog",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogResponse"
                }
              }
            }
          }
        },
        "description": "Returns curated gift ideas. Pass marketplace+locale for the user. Response includes total, offset, limit, catalogMode (asin|search-ideas). Curated ASINs produce /dp links when marketplace is amazon.se (Swedish catalog, tag sw-valentine-21) or amazon.com (US catalog, tag sw-valentine-20)."
      }
    },
    "/api/v1/products/resolve": {
      "post": {
        "tags": [
          "catalog"
        ],
        "summary": "Resolve ASIN, pasted amazon.se / amazon.com URL, or keywords to buy link",
        "operationId": "resolveProduct",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "asin": {
                    "type": "string",
                    "description": "10-char Amazon ASIN"
                  },
                  "keywords": {
                    "type": "string"
                  },
                  "marketplace": {
                    "type": "string",
                    "description": "Amazon storefront for the user"
                  },
                  "domain": {
                    "type": "string"
                  },
                  "locale": {
                    "type": "string"
                  },
                  "preferSearch": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resolved link",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "affiliateUrl": {
                      "type": "string",
                      "format": "uri",
                      "description": "Deprecated alias for buyUrl",
                      "deprecated": true
                    },
                    "asin": {
                      "type": "string"
                    },
                    "linkType": {
                      "$ref": "#/components/schemas/LinkType"
                    },
                    "affiliateTag": {
                      "type": "string",
                      "description": "Deprecated alias for trackingTag",
                      "deprecated": true
                    },
                    "domain": {
                      "type": "string"
                    },
                    "catalogCount": {
                      "type": "integer",
                      "description": "Curated catalog size (currently ~492)"
                    },
                    "paapi": {
                      "type": "boolean"
                    },
                    "buyUrl": {
                      "type": "string",
                      "format": "uri",
                      "description": "Curated Amazon buy URL"
                    },
                    "trackingTag": {
                      "type": "string",
                      "description": "Associates tracking tag when configured; null in search-mode"
                    }
                  },
                  "required": [
                    "buyUrl",
                    "linkType"
                  ]
                }
              }
            }
          }
        },
        "description": "Accepts asin, url (amazon.se/dp/… or amazon.com/dp/…), and/or keywords."
      }
    },
    "/api/v1/agent/create-and-fill": {
      "post": {
        "tags": [
          "agent"
        ],
        "summary": "One-shot create wishlist and add ASINs/keywords",
        "operationId": "agentCreateAndFill",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentCreateAndFillBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WishlistCreateResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/wishlists": {
      "post": {
        "tags": [
          "wishlists"
        ],
        "summary": "Create wishlist",
        "operationId": "createWishlist",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWishlistBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WishlistCreateResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/wishlists/{id}": {
      "get": {
        "tags": [
          "wishlists"
        ],
        "summary": "Get wishlist",
        "operationId": "getWishlist",
        "parameters": [
          {
            "$ref": "#/components/parameters/WishlistId"
          }
        ],
        "responses": {
          "200": {
            "description": "Wishlist",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WishlistGetResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          }
        }
      },
      "patch": {
        "tags": [
          "wishlists"
        ],
        "summary": "Update wishlist metadata or replace items",
        "operationId": "patchWishlist",
        "parameters": [
          {
            "$ref": "#/components/parameters/WishlistId"
          },
          {
            "$ref": "#/components/parameters/EditToken"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchWishlistBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated (token mode may return new id)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WishlistMutateResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing edit token"
          },
          "404": {
            "description": "Not found or bad token"
          }
        }
      }
    },
    "/api/v1/wishlists/{id}/items": {
      "post": {
        "tags": [
          "wishlists"
        ],
        "summary": "Add wish item (asin → /dp/ product link)",
        "operationId": "addWishlistItem",
        "parameters": [
          {
            "$ref": "#/components/parameters/WishlistId"
          },
          {
            "$ref": "#/components/parameters/EditToken"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddItemBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Item added",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WishlistMutateResponse"
                }
              }
            }
          }
        },
        "description": "Accept name/title, asin, url (pasted /dp link), searchKeywords, or catalogId."
      }
    },
    "/api/v1/wishlists/{id}/items/{itemId}": {
      "delete": {
        "tags": [
          "wishlists"
        ],
        "summary": "Delete wish item",
        "operationId": "deleteWishlistItem",
        "parameters": [
          {
            "$ref": "#/components/parameters/WishlistId"
          },
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/EditToken"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WishlistMutateResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search": {
      "get": {
        "tags": [
          "search"
        ],
        "summary": "Open Amazon.se valentine gift search",
        "description": "If PA-API keys are set, returns real products. Otherwise ranked romantic-filtered Amazon.se search deep-link cards plus matching curated catalog ASINs.",
        "operationId": "searchAmazon",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Search query"
          },
          {
            "name": "occasion",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Occasion"
            }
          },
          {
            "name": "interest",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Category/interest filter"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 10
            }
          },
          {
            "name": "marketplace",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Amazon storefront domain or id (e.g. amazon.com, amazon.se, se). REQUIRED for correct user locale/store — agents MUST pass the user's marketplace."
          },
          {
            "name": "domain",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Alias for marketplace"
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "sv",
                "de",
                "fr",
                "es"
              ]
            },
            "description": "UI/search cue locale. Agents MUST pass the user's locale."
          }
        ],
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing q"
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "WishlistId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Short Redis id or t.* token id"
      },
      "EditToken": {
        "name": "X-Edit-Token",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    },
    "schemas": {
      "Occasion": {
        "type": "string",
        "enum": [
          "0-2",
          "3-5",
          "6-8",
          "9-12"
        ]
      },
      "GiftCategory": {
        "type": "string",
        "enum": [
          "toys",
          "books",
          "sports",
          "craft",
          "tech",
          "outdoor",
          "games"
        ]
      },
      "LinkType": {
        "type": "string",
        "enum": [
          "product",
          "search"
        ]
      },
      "WishlistItem": {
        "type": "object",
        "required": [
          "id",
          "title",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "catalogId": {
            "type": "string"
          },
          "asin": {
            "type": "string",
            "nullable": true
          },
          "searchKeywords": {
            "type": "string"
          },
          "emoji": {
            "type": "string"
          },
          "affiliateUrl": {
            "type": "string",
            "format": "uri",
            "description": "Deprecated alias for buyUrl",
            "deprecated": true
          },
          "linkType": {
            "$ref": "#/components/schemas/LinkType"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "buyUrl": {
            "type": "string",
            "format": "uri",
            "description": "Curated Amazon buy URL"
          }
        }
      },
      "Wishlist": {
        "type": "object",
        "required": [
          "id",
          "recipientName",
          "items",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "recipientName": {
            "type": "string"
          },
          "occasion": {
            "$ref": "#/components/schemas/Occasion"
          },
          "categories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GiftCategory"
            }
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WishlistItem"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateWishlistBody": {
        "type": "object",
        "properties": {
          "recipientName": {
            "type": "string"
          },
          "occasion": {
            "$ref": "#/components/schemas/Occasion"
          },
          "categories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GiftCategory"
            }
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "title": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "notes": {
                  "type": "string"
                },
                "catalogId": {
                  "type": "string"
                },
                "asin": {
                  "type": "string"
                },
                "searchKeywords": {
                  "type": "string"
                },
                "emoji": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "AgentCreateAndFillBody": {
        "type": "object",
        "properties": {
          "recipientName": {
            "type": "string"
          },
          "occasion": {
            "$ref": "#/components/schemas/Occasion"
          },
          "categories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GiftCategory"
            }
          },
          "itemAsins": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Amazon ASINs → /dp/ links"
          },
          "itemKeywords": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Free-text → search links"
          },
          "itemQueries": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Free-text queries searched via PA-API or romantic search links and added"
          }
        }
      },
      "PatchWishlistBody": {
        "type": "object",
        "properties": {
          "recipientName": {
            "type": "string"
          },
          "occasion": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Occasion"
              },
              {
                "type": "null"
              }
            ]
          },
          "categories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GiftCategory"
            }
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WishlistItem"
            }
          }
        }
      },
      "AddItemBody": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "description": "Alias for title"
          },
          "notes": {
            "type": "string"
          },
          "catalogId": {
            "type": "string"
          },
          "asin": {
            "type": "string",
            "description": "When set, buyUrl is /dp/ASIN?tag="
          },
          "searchKeywords": {
            "type": "string"
          },
          "emoji": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "description": "Pasted amazon.se/dp or amazon.com/dp URL — ASIN extracted when possible"
          }
        }
      },
      "WishlistCreateResponse": {
        "type": "object",
        "required": [
          "id",
          "editToken",
          "ownerUrl",
          "shopUrl",
          "wishlist",
          "storage"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "editToken": {
            "type": "string"
          },
          "ownerUrl": {
            "type": "string",
            "format": "uri"
          },
          "shopUrl": {
            "type": "string",
            "format": "uri"
          },
          "wishlist": {
            "$ref": "#/components/schemas/Wishlist"
          },
          "storage": {
            "type": "string",
            "enum": [
              "redis",
              "token"
            ]
          }
        }
      },
      "WishlistGetResponse": {
        "type": "object",
        "required": [
          "id",
          "wishlist",
          "ownerUrl",
          "shopUrl",
          "storage"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "wishlist": {
            "$ref": "#/components/schemas/Wishlist"
          },
          "ownerUrl": {
            "type": "string",
            "format": "uri"
          },
          "shopUrl": {
            "type": "string",
            "format": "uri"
          },
          "storage": {
            "type": "string",
            "enum": [
              "redis",
              "token"
            ]
          }
        }
      },
      "WishlistMutateResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WishlistCreateResponse"
          },
          {
            "type": "object",
            "properties": {
              "previousId": {
                "type": "string"
              },
              "item": {
                "$ref": "#/components/schemas/WishlistItem"
              }
            }
          }
        ]
      },
      "CatalogResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer"
          },
          "affiliateTag": {
            "type": "string",
            "description": "Deprecated alias for trackingTag",
            "deprecated": true
          },
          "domain": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "asin": {
                  "type": "string",
                  "nullable": true
                },
                "name": {
                  "type": "string"
                },
                "blurb": {
                  "type": "string"
                },
                "priceSek": {
                  "type": "number"
                },
                "category": {
                  "type": "string"
                },
                "emoji": {
                  "type": "string"
                },
                "occasions": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "categories": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "searchKeywords": {
                  "type": "string"
                },
                "affiliateUrl": {
                  "type": "string",
                  "format": "uri",
                  "description": "Deprecated alias for buyUrl",
                  "deprecated": true
                },
                "linkType": {
                  "$ref": "#/components/schemas/LinkType"
                },
                "buyUrl": {
                  "type": "string",
                  "format": "uri",
                  "description": "Curated Amazon buy URL"
                }
              }
            }
          },
          "catalogCount": {
            "type": "integer",
            "description": "Curated catalog size (currently ~492)"
          },
          "paapi": {
            "type": "boolean"
          },
          "trackingTag": {
            "type": "string",
            "description": "Associates tracking tag when configured; null in search-mode"
          }
        }
      },
      "Health": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "service": {
            "type": "string"
          },
          "storage": {
            "type": "string"
          },
          "redisConfigured": {
            "type": "boolean"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "paapi": {
            "type": "boolean"
          },
          "affiliateTag": {
            "type": "string",
            "description": "Deprecated alias for trackingTag",
            "deprecated": true
          },
          "domain": {
            "type": "string"
          },
          "catalogCount": {
            "type": "integer",
            "description": "Curated catalog size (currently ~492)"
          },
          "trackingTag": {
            "type": "string",
            "description": "Associates tracking tag when configured; null in search-mode"
          }
        }
      },
      "SearchResponse": {
        "type": "object",
        "properties": {
          "q": {
            "type": "string"
          },
          "query": {
            "type": "string",
            "description": "Kids-rewritten query"
          },
          "paapi": {
            "type": "boolean"
          },
          "hint": {
            "type": "string"
          },
          "count": {
            "type": "integer"
          },
          "affiliateTag": {
            "type": "string",
            "description": "Deprecated alias for trackingTag",
            "deprecated": true
          },
          "domain": {
            "type": "string"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchResult"
            }
          },
          "catalogMatches": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "catalogCount": {
            "type": "integer",
            "description": "Curated catalog size (currently ~492)"
          },
          "trackingTag": {
            "type": "string",
            "description": "Associates tracking tag when configured; null in search-mode"
          }
        }
      },
      "SearchResult": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "asin": {
            "type": "string"
          },
          "imageUrl": {
            "type": "string"
          },
          "price": {
            "type": "string"
          },
          "affiliateUrl": {
            "type": "string",
            "description": "Deprecated alias for buyUrl",
            "deprecated": true
          },
          "linkType": {
            "type": "string",
            "enum": [
              "product",
              "search"
            ]
          },
          "query": {
            "type": "string"
          },
          "blurb": {
            "type": "string"
          },
          "emoji": {
            "type": "string"
          },
          "buyUrl": {
            "type": "string",
            "description": "Curated Amazon buy URL"
          }
        }
      },
      "Product": {
        "type": "object",
        "required": [
          "asin",
          "title",
          "buyUrl",
          "linkType"
        ],
        "properties": {
          "asin": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "imageUrl": {
            "type": "string"
          },
          "price": {
            "type": "string"
          },
          "detailPageUrl": {
            "type": "string"
          },
          "affiliateUrl": {
            "type": "string",
            "description": "Deprecated alias for buyUrl",
            "deprecated": true
          },
          "linkType": {
            "type": "string",
            "enum": [
              "product"
            ]
          },
          "buyUrl": {
            "type": "string",
            "description": "Curated Amazon buy URL"
          }
        }
      }
    }
  }
}