{
    "openapi": "3.0.0",
    "info": {
        "title": "The Satsback.com API",
        "description": "Connect your applications to Satsback.com.<br /><br /><b>Use 'Bearer &lt;token&gt;' to Authorize.</b>",
        "contact": {
            "email": "api@satsback.com"
        },
        "version": "0.1.0"
    },
    "servers": [
        {
            "url": "https://satsback.com",
            "description": "The Satsback.com API"
        }
    ],
    "paths": {
        "/api/advertiser/click/create": {
            "post": {
                "tags": [
                    "Affiliates"
                ],
                "summary": "Advertiser - Confirm incoming click",
                "operationId": "clicks",
                "parameters": [
                    {
                        "name": "id",
                        "in": "query",
                        "description": "ID",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {}
                        }
                    },
                    "401": {
                        "description": "Unauthenticated"
                    },
                    "400": {
                        "description": "Bad Request"
                    },
                    "404": {
                        "description": "Not found"
                    },
                    "403": {
                        "description": "Forbidden"
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/advertiser/transaction/create": {
            "post": {
                "tags": [
                    "Affiliates"
                ],
                "summary": "Advertiser - Create new transaction",
                "operationId": "transactionsCreate",
                "parameters": [
                    {
                        "name": "id",
                        "in": "query",
                        "description": "ID",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "commission_sats",
                        "in": "query",
                        "description": "Enable commission in sats",
                        "required": false,
                        "schema": {
                            "type": "boolean"
                        }
                    },
                    {
                        "name": "commission",
                        "in": "query",
                        "description": "Commission in EUR cents or sats",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "order_amount",
                        "in": "query",
                        "description": "Order amount in EUR cents",
                        "required": false,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "transaction_id",
                        "in": "query",
                        "description": "Internal advertiser transaction ID",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "description": "Transaction status (pending, accepted or rejected)",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {}
                        }
                    },
                    "401": {
                        "description": "Unauthenticated"
                    },
                    "400": {
                        "description": "Bad Request"
                    },
                    "404": {
                        "description": "Not found"
                    },
                    "403": {
                        "description": "Forbidden"
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/advertiser/transaction/update": {
            "post": {
                "tags": [
                    "Affiliates"
                ],
                "summary": "Advertiser - Update existing transaction",
                "operationId": "transactionsUpdate",
                "parameters": [
                    {
                        "name": "id",
                        "in": "query",
                        "description": "ID",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "description": "Transaction status (pending, accepted or rejected)",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {}
                        }
                    },
                    "401": {
                        "description": "Unauthenticated"
                    },
                    "400": {
                        "description": "Bad Request"
                    },
                    "404": {
                        "description": "Not found"
                    },
                    "403": {
                        "description": "Forbidden"
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/advertiser/check_public_id": {
            "post": {
                "tags": [
                    "Affiliates"
                ],
                "summary": "Advertiser - Check if Public ID is valid",
                "operationId": "transactions",
                "parameters": [
                    {
                        "name": "id",
                        "in": "query",
                        "description": "Satsback.com Public ID",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {}
                        }
                    },
                    "401": {
                        "description": "Unauthenticated"
                    },
                    "400": {
                        "description": "Bad Request"
                    },
                    "404": {
                        "description": "Not found"
                    },
                    "403": {
                        "description": "Forbidden"
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/agent/account": {
            "delete": {
                "tags": [
                    "Agent Account"
                ],
                "summary": "Delete agent account",
                "description": "Permanently deletes the authenticated agent account. Revokes all tokens, removes auth methods and payout types, and soft-deletes the user. This action is irreversible.",
                "operationId": "f859f8a774d1f90e3fcd26e0ef1636c0",
                "responses": {
                    "200": {
                        "description": "Account deleted",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Account deleted successfully"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthorized"
                    },
                    "500": {
                        "description": "Internal error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Failed to delete account"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/agent/stores": {
            "get": {
                "tags": [
                    "Agents"
                ],
                "summary": "Get store catalog for an agent (authenticated user's country)",
                "description": "Get all stores visible to an agent, optionally filtered by country.\n\nIf no country slug is provided, the authenticated user's country is used.",
                "operationId": "14d8488bab86eaf9a1d7f689f75fbef2",
                "parameters": [
                    {
                        "name": "q",
                        "in": "query",
                        "description": "Search query to filter stores by name (e.g. \"hema\", \"bol\").",
                        "required": false,
                        "schema": {
                            "type": "string"
                        },
                        "example": "hema"
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Maximum number of stores to return (1–500). Omit to return all.",
                        "required": false,
                        "schema": {
                            "type": "integer"
                        },
                        "example": 25
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/AgentStore"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthenticated"
                    },
                    "422": {
                        "description": "Country could not be resolved"
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/agent/stores/{country}": {
            "get": {
                "tags": [
                    "Agents"
                ],
                "summary": "Get store catalog for an agent",
                "operationId": "f436cf4b7c94fe1cb9486822641e9cd8",
                "parameters": [
                    {
                        "name": "country",
                        "in": "path",
                        "description": "Country slug (e.g. netherlands) or ISO code (e.g. NL). Omit the whole segment (GET /api/v2/agent/stores) to fall back to the authenticated user's country.",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "netherlands"
                    },
                    {
                        "name": "q",
                        "in": "query",
                        "description": "Search query to filter stores by name (e.g. \"hema\", \"bol\").",
                        "required": false,
                        "schema": {
                            "type": "string"
                        },
                        "example": "hema"
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "Maximum number of stores to return (1–500). Omit to return all.",
                        "required": false,
                        "schema": {
                            "type": "integer"
                        },
                        "example": 25
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/AgentStore"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthenticated"
                    },
                    "422": {
                        "description": "Country could not be resolved"
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/agent/store/{slug}": {
            "get": {
                "tags": [
                    "Agents"
                ],
                "summary": "Get store details by slug",
                "description": "Get a single store's details by slug.",
                "operationId": "43e76cfe06bda352519de780cb66abb6",
                "parameters": [
                    {
                        "name": "slug",
                        "in": "path",
                        "description": "Store slug (e.g. hema, bol-com)",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "hema"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Store details",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/AgentStore"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Store not found"
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/agent/store/{slug}/visit": {
            "get": {
                "tags": [
                    "Agents"
                ],
                "summary": "Generate a cashback click for a store",
                "description": "Generate a cashback click for a store. Returns the affiliate redirect URL.",
                "operationId": "a91f8dfb0bd7505785a99a571f442035",
                "parameters": [
                    {
                        "name": "slug",
                        "in": "path",
                        "description": "Store slug (e.g. hema, bol-com)",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "hema"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Click created — follow redirect_url to activate affiliate tracking",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "store_id": {
                                            "description": "Hashids-encoded store id, matches the stores endpoint",
                                            "type": "string",
                                            "example": "g2Mkb1aoMLDGXZzq"
                                        },
                                        "store_name": {
                                            "type": "string",
                                            "example": "HEMA"
                                        },
                                        "cashback_type": {
                                            "type": "string",
                                            "example": "percent",
                                            "enum": [
                                                "percent",
                                                "fixed_sats",
                                                "discount_code"
                                            ]
                                        },
                                        "cashback_code": {
                                            "description": "Checkout code for discount_code stores, null otherwise",
                                            "type": "string",
                                            "example": null,
                                            "nullable": true
                                        },
                                        "click_id": {
                                            "type": "string",
                                            "example": "jZqkrnR"
                                        },
                                        "redirect_url": {
                                            "type": "string",
                                            "format": "uri",
                                            "example": "https://satsback.com/api/v2/store/redirect/jZqkrnR?signature=..."
                                        },
                                        "tracking_tips": {
                                            "description": "Tips/optimisations that improve the odds of the click being credited. Not hard requirements.",
                                            "type": "array",
                                            "items": {
                                                "type": "string"
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Store not found"
                    },
                    "422": {
                        "description": "Link could not be generated"
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/countries": {
            "get": {
                "tags": [
                    "Main"
                ],
                "summary": "Get all available countries",
                "description": "Get all available countries",
                "operationId": "6a97a6da304de5b7d409f8a5be4b5c85",
                "responses": {
                    "200": {
                        "description": "List of all available countries",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "AF": {
                                            "type": "string",
                                            "example": "afghanistan"
                                        },
                                        "NL": {
                                            "type": "string",
                                            "example": "netherlands"
                                        },
                                        "US": {
                                            "type": "string",
                                            "example": "united-states"
                                        },
                                        "GB": {
                                            "type": "string",
                                            "example": "united-kingdom"
                                        },
                                        "DE": {
                                            "type": "string",
                                            "example": "germany"
                                        },
                                        "FR": {
                                            "type": "string",
                                            "example": "france"
                                        },
                                        "ES": {
                                            "type": "string",
                                            "example": "spain"
                                        },
                                        "IT": {
                                            "type": "string",
                                            "example": "italy"
                                        },
                                        "CA": {
                                            "type": "string",
                                            "example": "canada"
                                        },
                                        "AU": {
                                            "type": "string",
                                            "example": "australia"
                                        }
                                    },
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "Failed to retrieve countries"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v2/stores/{country}/overview": {
            "get": {
                "tags": [
                    "Stores"
                ],
                "summary": "Get all featured and essentials stores for a country",
                "description": "Get all featured, essentials and new stores for a country",
                "operationId": "f10c2cf6b5953dfbab49cef53f6d8ccb",
                "parameters": [
                    {
                        "name": "country",
                        "in": "path",
                        "description": "Country",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "netherlands"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "country": {
                                            "type": "string",
                                            "example": "netherlands"
                                        },
                                        "featuredShops": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/StoreDetail"
                                            }
                                        },
                                        "essentials": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/StoreDetail"
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v2/stores/{country}/all": {
            "get": {
                "tags": [
                    "Stores"
                ],
                "summary": "Get all stores for a country",
                "description": "Get all stores for a country",
                "operationId": "c025ef53c992254e31854a792f28e954",
                "parameters": [
                    {
                        "name": "country",
                        "in": "path",
                        "description": "Country",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "netherlands"
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "Page",
                        "required": false,
                        "schema": {
                            "type": "integer"
                        },
                        "example": "1"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/StoreDetail"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v2/store/{store}": {
            "get": {
                "tags": [
                    "Stores"
                ],
                "summary": "Get a store by slug",
                "description": "Get a store by slug",
                "operationId": "616f700f4e129eb7e09703de13de561f",
                "parameters": [
                    {
                        "name": "store",
                        "in": "path",
                        "description": "Store slug",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "store-slug"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoreDetail"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Store not found"
                    }
                }
            }
        },
        "/api/v2/user/clicks": {
            "get": {
                "tags": [
                    "User Account"
                ],
                "summary": "Get the user's clicks",
                "description": "Get the user's clicks",
                "operationId": "79cabb31d694867ca2d355932b544171",
                "responses": {
                    "200": {
                        "description": "User clicks",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "example": "Z58dxM4"
                                                    },
                                                    "store_name": {
                                                        "type": "string",
                                                        "example": "Thuisbezorgd.nl"
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "example": "2025-08-14T13:17:33.000000Z"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "Invalid user credentials"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/user/history": {
            "get": {
                "tags": [
                    "User Account"
                ],
                "summary": "Get the user's history",
                "description": "Get the user's history",
                "operationId": "6c38893b7f201345fd9f8a479de1ceef",
                "responses": {
                    "200": {
                        "description": "User history",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "example": "G4YNyZr"
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "example": "shopping"
                                                    },
                                                    "amount": {
                                                        "type": "integer",
                                                        "example": 932
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "example": "rejected"
                                                    },
                                                    "store_name": {
                                                        "type": "string",
                                                        "example": "Lidl.nl"
                                                    },
                                                    "order_value": {
                                                        "type": "string",
                                                        "example": ""
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "example": "2025-07-29T13:30:00.000000Z"
                                                    },
                                                    "updated_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "example": "2025-07-29T13:30:02.000000Z"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "Invalid user credentials"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/user/history/{hashedId}": {
            "get": {
                "tags": [
                    "User Account"
                ],
                "summary": "Get a single history record",
                "description": "Get a single history record by hashed ID",
                "operationId": "a6e36bd95a7bdafc088923b5e315fe9f",
                "parameters": [
                    {
                        "name": "hashedId",
                        "in": "path",
                        "description": "The hashed ID of the history record",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "example": "G4YNyZr"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Single history record",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "example": "G4YNyZr"
                                                },
                                                "type": {
                                                    "type": "string",
                                                    "example": "shopping"
                                                },
                                                "amount": {
                                                    "type": "integer",
                                                    "example": 932
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "example": "rejected"
                                                },
                                                "store_name": {
                                                    "type": "string",
                                                    "example": "Lidl.nl"
                                                },
                                                "order_value": {
                                                    "type": "string",
                                                    "example": ""
                                                },
                                                "created_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "example": "2025-07-29T13:30:00.000000Z"
                                                },
                                                "updated_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "example": "2025-07-29T13:30:02.000000Z"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "Invalid user credentials"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "History record not found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "History record not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/user/payouts": {
            "get": {
                "tags": [
                    "User Account"
                ],
                "summary": "Get the user's payouts",
                "description": "Get the user's payouts",
                "operationId": "06f6af364f1c0a83b8be90f19368debf",
                "responses": {
                    "200": {
                        "description": "User payouts",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "example": "nXqLdM4"
                                                    },
                                                    "payout_type": {
                                                        "type": "string",
                                                        "example": "Automatic Payout"
                                                    },
                                                    "amount": {
                                                        "type": "string",
                                                        "example": "21"
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "example": "Paid"
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "example": "2022-03-18T13:47:30.000000Z"
                                                    },
                                                    "updated_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "example": "2023-12-01T15:07:24.000000Z"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "Invalid user credentials"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/user/country": {
            "patch": {
                "tags": [
                    "User Account"
                ],
                "summary": "Update the user's country",
                "description": "Update the authenticated user's country.",
                "operationId": "077972213b114da331131e215e508fa9",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "country"
                                ],
                                "properties": {
                                    "country": {
                                        "type": "string",
                                        "example": "netherlands"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Country updated"
                    },
                    "404": {
                        "description": "Country not found"
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/user/lightning-address": {
            "patch": {
                "tags": [
                    "User Account"
                ],
                "summary": "Update the user's lightning address",
                "description": "Update the authenticated user's lightning address.",
                "operationId": "b08909c34da78e3478fdc00f97e52414",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "address"
                                ],
                                "properties": {
                                    "address": {
                                        "type": "string",
                                        "example": "agent@getalby.com"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Lightning address updated"
                    },
                    "422": {
                        "description": "Invalid or unreachable lightning address"
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/user/notifications": {
            "patch": {
                "tags": [
                    "User Account"
                ],
                "summary": "Update the user's notification channel",
                "description": "Update the authenticated user's notification channel.",
                "operationId": "800b9f6dae867d9fa264a4d074ec3acf",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "channel"
                                ],
                                "properties": {
                                    "channel": {
                                        "type": "string",
                                        "example": "nostr",
                                        "enum": [
                                            "mail",
                                            "nostr",
                                            "none"
                                        ]
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Notification channel updated"
                    },
                    "400": {
                        "description": "Nostr auth method required"
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/l402/payment-request": {
            "post": {
                "tags": [
                    "Agents"
                ],
                "summary": "l402.org payment-request endpoint",
                "description": "Companion endpoint to `POST /api/v2/l402/register` for clients following the\n[l402.org](https://docs.l402.org/) JSON protocol.\n\nClients that prefer the Lightning L402 header flow (`WWW-Authenticate: L402 ...`)\ncan ignore this endpoint — the Lightning invoice is already in the `WWW-Authenticate`\nheader of the original 402 response.\n\nThis endpoint returns the same Lightning invoice that was minted in Phase A; it does\nnot create a new invoice. Safe to retry.",
                "operationId": "72b4c6258a6009807c50a9bb8acc50df",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "offer_id",
                                    "payment_method",
                                    "payment_context_token"
                                ],
                                "properties": {
                                    "offer_id": {
                                        "type": "string",
                                        "example": "agent-registration"
                                    },
                                    "payment_method": {
                                        "type": "string",
                                        "example": "lightning"
                                    },
                                    "payment_context_token": {
                                        "description": "The `payment_context_token` from the 402 response (equal to `payment_hash`).",
                                        "type": "string"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Payment request returned",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "version": {
                                            "type": "string",
                                            "example": "0.2.2"
                                        },
                                        "payment_request": {
                                            "properties": {
                                                "lightning_invoice": {
                                                    "type": "string",
                                                    "example": "lnbc210n1..."
                                                }
                                            },
                                            "type": "object"
                                        },
                                        "expires_at": {
                                            "type": "string",
                                            "format": "date-time"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Unknown offer_id or payment_method"
                    },
                    "404": {
                        "description": "payment_context_token not found"
                    },
                    "409": {
                        "description": "Registration already completed"
                    },
                    "410": {
                        "description": "Registration expired"
                    },
                    "422": {
                        "description": "Validation failed"
                    },
                    "429": {
                        "description": "Too Many Requests"
                    }
                }
            }
        },
        "/api/v2/l402/register": {
            "get": {
                "tags": [
                    "Agents"
                ],
                "summary": "Request the L402 challenge over GET (Phase A only)",
                "description": "The same Phase A as the POST operation, for probers and clients that ask for the\n402 with GET or HEAD first (ngx-l402's onboarding flow, directory health checks).\nReturns HTTP 402 with the Lightning invoice and macaroon in the `WWW-Authenticate`\nheader and the l402.org JSON body; HEAD returns the header without the body.\nPhase B is a POST: pay the invoice, then POST with\n`Authorization: L402 {base64_macaroon}:{hex_preimage}` and the registration body as\ndescribed there. A GET or HEAD that carries L402 credentials is refused with 405 before\nany registration work; the `Allow` header names the Phase B verb, not the resource's\nfull method set, and the macaroon and preimage stay valid.",
                "operationId": "29d328c21cf0abcb851aaab1b8da05f0",
                "responses": {
                    "402": {
                        "description": "Phase A: Payment Required. Same response as the POST operation: Lightning L402 `WWW-Authenticate` header and l402.org JSON body (version 0.2.2).",
                        "headers": {
                            "WWW-Authenticate": {
                                "description": "Lightning L402 challenge: `L402 macaroon=\"...\", invoice=\"...\"`",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "405": {
                        "description": "L402 credentials sent with a GET or HEAD: Phase B is a POST. Retry as a POST with the registration body; the macaroon + preimage stay valid. Carries `Allow: POST`, the Phase B verb."
                    },
                    "429": {
                        "description": "Too Many Requests"
                    },
                    "503": {
                        "description": "Service misconfigured: a lifetime is not positive (Phase A refused before minting) or the macaroon secret is missing in production (both phases). Nothing to pay; retry later, operator action required."
                    }
                }
            },
            "post": {
                "tags": [
                    "Agents"
                ],
                "summary": "Register via L402 (one Lightning payment for an account)",
                "description": "Two-phase registration endpoint for AI agents (standard L402 dance, ENG-576 shape).\n\n## Phase A — Request the challenge\nPOST without an `Authorization` header. The body may be empty — the challenge is\nbody-independent. Returns HTTP 402 with a Lightning invoice and macaroon in the\n`WWW-Authenticate` header (plus the l402.org JSON body). If you DO send a non-empty\nbody, it is validated as a courtesy first: an invalid body gets a 422 with actionable\nerrors and no invoice is minted, so you never pay for a doomed registration.\n\n## Phase B — Complete registration\nPay the invoice, then POST again with\n`Authorization: L402 {base64_macaroon}:{hex_preimage}` and the registration JSON body:\n`country`, `lightning_address`, optional `nostr_pubkey` + `nostr_proof`,\n`notifications`, `referrer_id`. **The Phase B body is authoritative** — whatever you\nsend with the paid request is what gets registered. A validation failure returns 400\nand the same macaroon + preimage stay valid for a corrected retry (the challenge\noutlives the invoice for exactly this reason). Success returns a Bearer token\n(sliding TTL: every authenticated call extends it; the response carries\nthe exact `expires_at`).\n\n### Optional: self-sovereign identity (recovery + notifications)\nProvide `nostr_pubkey` together with `nostr_proof` in the Phase B body: a signed\nNostr event (kind 27236) whose `content` is exactly the `payment_hash` of this\nregistration. A valid proof binds the key to the new account, enabling free recovery\nvia `POST /api/v2/auth/nostr` and NIP-17 DM notifications (`notifications: true`).\nNotifications need a published kind-10050 inbox relay list; without one the\nregistration still succeeds and the response carries a warning instead.\n\n### Optional: referrer\nSet `referrer_id` to a referrer public_id to credit a referrer. Invalid,\ninactive, or ineligible referrers cause a 400 error — no silent fallback.",
                "operationId": "1e85f80728f1929848ff272478025951",
                "parameters": [
                    {
                        "name": "Authorization",
                        "in": "header",
                        "description": "Phase B only: `L402 {base64_macaroon}:{hex_preimage}`",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "oneOf": [
                                    {
                                        "title": "Registration body (authoritative at Phase B; optional courtesy pre-check at Phase A)",
                                        "required": [
                                            "country",
                                            "lightning_address"
                                        ],
                                        "properties": {
                                            "country": {
                                                "description": "ISO-2 country code",
                                                "type": "string",
                                                "example": "NL"
                                            },
                                            "lightning_address": {
                                                "description": "Cashback payouts go here",
                                                "type": "string",
                                                "example": "agent@getalby.com"
                                            },
                                            "nostr_pubkey": {
                                                "description": "Optional 64-hex Nostr pubkey — enables recovery + notifications; requires nostr_proof at Phase B",
                                                "type": "string",
                                                "nullable": true
                                            },
                                            "nostr_proof": {
                                                "description": "Required with nostr_pubkey at Phase B: signed Nostr event (kind 27236) whose content is exactly the payment_hash of this registration — proves key possession. Cannot be pre-validated at Phase A (the payment_hash does not exist yet).",
                                                "properties": {
                                                    "kind": {
                                                        "type": "integer",
                                                        "example": 27236
                                                    },
                                                    "created_at": {
                                                        "type": "integer",
                                                        "example": 1774000000
                                                    },
                                                    "content": {
                                                        "description": "Must equal the payment_hash from the 402 challenge",
                                                        "type": "string"
                                                    },
                                                    "pubkey": {
                                                        "description": "Must equal nostr_pubkey",
                                                        "type": "string"
                                                    },
                                                    "sig": {
                                                        "type": "string"
                                                    },
                                                    "tags": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    }
                                                },
                                                "type": "object",
                                                "nullable": true
                                            },
                                            "notifications": {
                                                "description": "NIP-17 DM notifications; requires nostr_pubkey + nostr_proof. Soft-fails: no reachable relay list means the registration still succeeds with a warning.",
                                                "type": "boolean",
                                                "nullable": true
                                            },
                                            "referrer_id": {
                                                "type": "string",
                                                "nullable": true
                                            }
                                        },
                                        "type": "object"
                                    },
                                    {
                                        "title": "Signed Nostr event (legacy, backwards compat)",
                                        "required": [
                                            "event"
                                        ],
                                        "properties": {
                                            "event": {
                                                "description": "Signed Nostr event (kind 27236) with country/lightning_address tags — superseded by the plain registration shape",
                                                "required": [
                                                    "kind",
                                                    "created_at",
                                                    "content",
                                                    "pubkey",
                                                    "sig",
                                                    "tags"
                                                ],
                                                "properties": {
                                                    "kind": {
                                                        "type": "integer",
                                                        "example": 27236
                                                    },
                                                    "created_at": {
                                                        "type": "integer",
                                                        "example": 1774000000
                                                    },
                                                    "content": {
                                                        "type": "string",
                                                        "example": "register"
                                                    },
                                                    "pubkey": {
                                                        "type": "string",
                                                        "example": "abcd177be3ddd26b..."
                                                    },
                                                    "sig": {
                                                        "type": "string",
                                                        "example": "e5d4f3..."
                                                    },
                                                    "tags": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "string"
                                                            }
                                                        },
                                                        "example": [
                                                            [
                                                                "country",
                                                                "NL"
                                                            ],
                                                            [
                                                                "lightning_address",
                                                                "user@wallet.com"
                                                            ],
                                                            [
                                                                "referrer_id",
                                                                "abc123"
                                                            ]
                                                        ]
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object",
                                        "deprecated": true
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "402": {
                        "description": "Phase A: Payment Required. Returns Lightning L402 `WWW-Authenticate` header AND l402.org JSON body (version 0.2.2). Clients may follow either flow.",
                        "headers": {
                            "WWW-Authenticate": {
                                "description": "Lightning L402 challenge: `L402 macaroon=\"...\", invoice=\"...\"`",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "version": {
                                            "description": "l402.org protocol version",
                                            "type": "string",
                                            "example": "0.2.2"
                                        },
                                        "payment_request_url": {
                                            "type": "string",
                                            "example": "https://satsback.com/api/v2/l402/payment-request"
                                        },
                                        "payment_context_token": {
                                            "description": "Session token (equal to payment_hash) — pass back to payment-request endpoint",
                                            "type": "string"
                                        },
                                        "offers": {
                                            "type": "array",
                                            "items": {
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "example": "agent-registration"
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "example": "one-time"
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "example": "Satsback Agent Registration"
                                                    },
                                                    "amount": {
                                                        "type": "integer",
                                                        "example": 21
                                                    },
                                                    "currency": {
                                                        "type": "string",
                                                        "example": "SAT"
                                                    },
                                                    "payment_methods": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "string"
                                                        },
                                                        "example": [
                                                            "lightning"
                                                        ]
                                                    },
                                                    "description": {
                                                        "type": "string"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "payment_hash": {
                                            "description": "BOLT11 payment hash — also the commitment target for the optional nostr_proof at Phase B",
                                            "type": "string"
                                        },
                                        "amount_sats": {
                                            "type": "integer",
                                            "example": 21
                                        },
                                        "expires_at": {
                                            "description": "Challenge deadline: pay AND complete before this moment (the invoice itself expires sooner)",
                                            "type": "string",
                                            "format": "date-time"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "200": {
                        "description": "Phase B: Registration complete. May carry a `warnings` array (e.g. notifications requested but no kind-10050 relay list found)."
                    },
                    "400": {
                        "description": "Bad Request. At Phase A (and the 404/409 rejections there): the body carries a stable `reason` code next to `message`, e.g. `event.expired`, `lightning_address.rejected`. At Phase B: the body was rejected — the macaroon + preimage stay valid, retry with a corrected body."
                    },
                    "401": {
                        "description": "Phase B: Invalid macaroon or preimage"
                    },
                    "409": {
                        "description": "Pubkey already registered / registration already completed"
                    },
                    "429": {
                        "description": "Too Many Requests"
                    },
                    "503": {
                        "description": "Service misconfigured: a lifetime is not positive (Phase A refused before minting) or the macaroon secret is missing in production (both phases). Nothing to pay; retry later, operator action required."
                    }
                }
            }
        },
        "/api/v2/partner/auth/nostr": {
            "post": {
                "tags": [
                    "Partner Auth"
                ],
                "summary": "Create a new Nostr user",
                "description": "Create a new Nostr user",
                "operationId": "83c09565d9079964aff1d4d7271cba4c",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "event": {
                                        "description": "Nostr event (kind 27236) with tags partner, country, payout_address",
                                        "type": "object"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Nostr user created successfully"
                                        },
                                        "satsback_user_id": {
                                            "type": "string",
                                            "example": "1234567890"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Invalid signature"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Conflict",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "This Nostr key is already linked to an account"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Partner not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Failed to create Nostr user"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v2/partner/auth/nostr/token": {
            "post": {
                "tags": [
                    "Partner Auth"
                ],
                "summary": "Get a Nostr token for a partner",
                "description": "Get a Nostr token for a partner",
                "operationId": "75500bfcb9dbba1b4b19968fdbd83551",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "event": {
                                        "description": "Nostr event (kind 27237) with content get-token",
                                        "type": "object"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "token": {
                                            "type": "string",
                                            "example": "1234567890"
                                        },
                                        "user": {
                                            "type": "string",
                                            "example": "1234567890"
                                        },
                                        "satsback_user_id": {
                                            "type": "string",
                                            "example": "1234567890"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Invalid signature"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Nostr key not linked to an account"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Failed to get Nostr token"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v2/{partner}/stores/{country}": {
            "get": {
                "tags": [
                    "Partner Stores"
                ],
                "summary": "Get the stores for a partner (popularity-ranked top-N when enabled)",
                "description": "Get the stores for a partner. When the popularity ranking is enabled (ENG-381),\nthe ALL/ACTIVE listing modes return a popularity-ranked top-N (best first) instead\nof the full alphabetical list; the SPECIFIED whitelist is always returned complete.",
                "operationId": "7acc6fafb7d0b9dbcd775369ac19c163",
                "parameters": [
                    {
                        "name": "partner",
                        "in": "path",
                        "description": "Partner slug",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "acme"
                    },
                    {
                        "name": "country",
                        "in": "path",
                        "description": "Country",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "netherlands"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "properties": {
                                            "name": {
                                                "type": "string",
                                                "example": "AliExpress"
                                            },
                                            "text": {
                                                "type": "string",
                                                "example": "up to 2% satsback"
                                            },
                                            "slug": {
                                                "type": "string",
                                                "example": "aliexpress"
                                            },
                                            "image": {
                                                "type": "string",
                                                "example": "https://cdn.satsback.com/stores/partners/aliexpress.svg"
                                            },
                                            "description": {
                                                "type": "string",
                                                "example": "AliExpress brings you quality products at wholesale prices. Enjoy satsback on every purchase."
                                            },
                                            "store_id": {
                                                "type": "string",
                                                "example": "end1md4"
                                            }
                                        },
                                        "type": "object"
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Partner not found"
                    }
                }
            }
        },
        "/api/v2/store/visit/{store_id}/{user_id}": {
            "get": {
                "tags": [
                    "Partner Stores"
                ],
                "summary": "Visit a store",
                "description": "Visit a store",
                "operationId": "8201ad7e97e55a70fbafb3e9c60e0a36",
                "parameters": [
                    {
                        "name": "store_id",
                        "in": "path",
                        "description": "Store ID hash",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "abc123"
                    },
                    {
                        "name": "user_id",
                        "in": "path",
                        "description": "User public ID",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "xyz789"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "store_name": {
                                            "type": "string",
                                            "example": "Example Store"
                                        },
                                        "click_id": {
                                            "type": "string",
                                            "example": "abc123def456"
                                        },
                                        "redirect_url": {
                                            "type": "string",
                                            "example": "https://satsback.com/api/v2/store/redirect/jZqkrnR?signature=..."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Link could not be generated"
                    }
                }
            }
        },
        "/api/v2/store/redirect/{click_id}": {
            "get": {
                "tags": [
                    "Partner Stores"
                ],
                "summary": "Resolve a click to the store URL",
                "description": "Resolves the signed URL returned as `redirect_url` by the visit endpoint. Use that URL exactly as returned: the `signature` query parameter is the credential, so no Authorization header is needed, and rebuilding the URL or changing its query string invalidates it. The body carries the store URL; the same value is also set as a `Location` header, informational only, since the status is 200 and HTTP clients follow `Location` on 3xx responses alone. Read the body.",
                "operationId": "fd07f66adb01e6abec04d4d821dc3002",
                "parameters": [
                    {
                        "name": "click_id",
                        "in": "path",
                        "description": "Click ID hash, as embedded in the redirect_url of the visit response",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "jZqkrnR"
                    },
                    {
                        "name": "signature",
                        "in": "query",
                        "description": "Signature minted by the visit endpoint; only the URL as returned carries a valid one",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "Location": {
                                "description": "The same store URL. Informational: the status is 200, so clients that only follow Location on 3xx will not follow it",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "redirect_url": {
                                            "type": "string",
                                            "example": "https://partner-store.com/affiliate-link"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Missing, tampered or stripped signature",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Invalid signature."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Click not found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "example": "Click not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Too Many Requests"
                    }
                }
            }
        },
        "/api/v2/partner/test-order": {
            "post": {
                "tags": [
                    "Partner Test Orders"
                ],
                "summary": "Create a test order",
                "description": "Creates a real transaction of 21 sats, anchored to the hidden Satsback Test Store, on one of your own users. It starts as `pending`, appears in the user's history and on your webhook, and once accepted pays out through the normal flow. Each partner has a lifetime budget of test orders. Requires the partner bearer token with the `partner:test-orders` ability.",
                "operationId": "81623b664c3b0a6ab1542f283e09c425",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "user_id"
                                ],
                                "properties": {
                                    "user_id": {
                                        "description": "The user.id returned by POST /api/v2/partner/users; the user must belong to your partner account. Users created through the Nostr flow are returned as `satsback_user_id`, which is their public ID and not accepted here",
                                        "type": "string",
                                        "example": "9c1f4a2e-7b3d-4e2f-9a4b-1d2e3f4a5b6c",
                                        "maxLength": 64,
                                        "minLength": 1
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "order": {
                                            "properties": {
                                                "id": {
                                                    "description": "Use this as {id} when flipping the status",
                                                    "type": "string",
                                                    "example": "k2mR8xQw"
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "example": "pending"
                                                },
                                                "satsback": {
                                                    "type": "integer",
                                                    "example": 21
                                                },
                                                "store": {
                                                    "type": "string",
                                                    "example": "Satsback Test Store"
                                                },
                                                "user_id": {
                                                    "type": "string",
                                                    "example": "9c1f4a2e-7b3d-4e2f-9a4b-1d2e3f4a5b6c"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing, unknown or expired token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Unauthenticated."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Lifetime test-order budget reached (body carries `success`), or the token is not a partner credential or lacks the partner:test-orders ability (body carries `message` alone)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "anyOf": [
                                        {
                                            "title": "Budget reached",
                                            "required": [
                                                "success",
                                                "message"
                                            ],
                                            "properties": {
                                                "success": {
                                                    "type": "boolean",
                                                    "example": false
                                                },
                                                "message": {
                                                    "type": "string",
                                                    "example": "Test order limit reached (10 lifetime). Ask Satsback to raise it."
                                                }
                                            },
                                            "type": "object"
                                        },
                                        {
                                            "title": "Credential rejected",
                                            "required": [
                                                "message"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string",
                                                    "example": "Token is missing the required ability: partner:test-orders"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No user with this id belongs to this partner",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "No user with this id belongs to this partner"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Validation error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "errors": {
                                            "type": "object",
                                            "example": {
                                                "user_id": [
                                                    "'user_id' is required: the user id returned by POST /api/v2/partner/users (the user the test order is created for)."
                                                ]
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "Test orders are not provisioned on this environment",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Test orders are not provisioned on this environment"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Too Many Requests"
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/partner/test-order/{id}": {
            "patch": {
                "tags": [
                    "Partner Test Orders"
                ],
                "summary": "Flip a test order's status",
                "description": "Moves a test order to `accepted` or `rejected`, mirroring real network behaviour: pending to accepted makes the cashback spendable and pays it out, pending to rejected declines it, accepted to rejected simulates a clawback, and rejected is terminal. Once the order has been paid out, or while a payout for the user is in flight, the status can no longer change. Requires the partner bearer token with the `partner:test-orders` ability.",
                "operationId": "f8b997858384c326da8551a2514e810f",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "description": "The order.id from the create response",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "k2mR8xQw"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "status"
                                ],
                                "properties": {
                                    "status": {
                                        "type": "string",
                                        "example": "accepted",
                                        "enum": [
                                            "accepted",
                                            "rejected"
                                        ]
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "order": {
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "example": "k2mR8xQw"
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "example": "accepted"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing, unknown or expired token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Unauthenticated."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "The token is not a partner credential, or lacks the partner:test-orders ability",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Token is missing the required ability: partner:test-orders"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Unknown order, or an order that is not yours",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Test order not found"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Invalid state change: rejected is terminal, the order already has this status, it has been paid out, or a payout for the user is in flight (retry in a minute)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "A payout for this user is in flight; retry in a minute"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Validation error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "errors": {
                                            "type": "object",
                                            "example": {
                                                "status": [
                                                    "'status' must be 'accepted' or 'rejected'. A rejected test order is terminal; accepted can still be flipped to rejected (clawback)."
                                                ]
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Too Many Requests"
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/partner/users": {
            "post": {
                "tags": [
                    "Partner Users"
                ],
                "summary": "Create a user on the bearer rail",
                "description": "Creates a Satsback user owned by the calling partner. `external_ref` is the idempotency key: a retry with the same value returns the existing user with `created: false` and status 200 instead of a duplicate; the other fields are not compared on replay. Requires the partner bearer token with the `partner:users` ability.",
                "operationId": "235a3ce1d668718d151bffae184bf12a",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "external_ref",
                                    "country",
                                    "payout_address"
                                ],
                                "properties": {
                                    "external_ref": {
                                        "description": "Your stable reference for this user; the idempotency key",
                                        "type": "string",
                                        "example": "your-stable-user-reference",
                                        "maxLength": 64,
                                        "minLength": 1
                                    },
                                    "country": {
                                        "description": "Two-letter ISO country code",
                                        "type": "string",
                                        "example": "NL",
                                        "maxLength": 2,
                                        "minLength": 2
                                    },
                                    "payout_address": {
                                        "description": "The user's Lightning Address; probed before the user is created, cashback pays out there",
                                        "type": "string",
                                        "pattern": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$",
                                        "example": "user@wallet.example",
                                        "maxLength": 255,
                                        "minLength": 1
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "created": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "user": {
                                            "properties": {
                                                "id": {
                                                    "description": "Stable identifier for partner endpoints",
                                                    "type": "string",
                                                    "format": "uuid",
                                                    "example": "9c1f4a2e-7b3d-4e2f-9a4b-1d2e3f4a5b6c"
                                                },
                                                "public_id": {
                                                    "description": "The user_id hash accepted by GET /api/v2/store/visit/{store_id}/{user_id}",
                                                    "type": "string",
                                                    "example": "k2mR8xQw4Zp7Lc3v"
                                                },
                                                "country": {
                                                    "type": "string",
                                                    "example": "NL"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "200": {
                        "description": "Idempotent replay: a user with this external_ref already exists and is returned unchanged",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "created": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "user": {
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "format": "uuid",
                                                    "example": "9c1f4a2e-7b3d-4e2f-9a4b-1d2e3f4a5b6c"
                                                },
                                                "public_id": {
                                                    "type": "string",
                                                    "example": "k2mR8xQw4Zp7Lc3v"
                                                },
                                                "country": {
                                                    "type": "string",
                                                    "example": "NL"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Unknown country, or the Lightning Address did not answer the probe",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Country not found: XX"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing, unknown or expired token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Unauthenticated."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "The token is not a partner credential, or lacks the partner:users ability",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "example": "Token is missing the required ability: partner:users"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The external_ref refers to a deleted user",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "external_ref 'your-stable-user-reference' refers to a deleted user"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Validation error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "errors": {
                                            "type": "object",
                                            "example": {
                                                "external_ref": [
                                                    "'external_ref' is required: your stable reference for this user (max 64 chars). Retrying a create with the same external_ref returns the same user."
                                                ]
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Too Many Requests"
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        },
        "/api/v2/mcp": {
            "post": {
                "tags": [
                    "Agents"
                ],
                "summary": "MCP endpoint for agents (JSON-RPC 2.0 over streamable HTTP)",
                "description": "The Model Context Protocol server. This is a JSON-RPC 2.0 transport rather than a REST resource: every call is a POST carrying a JSON-RPC envelope, and the method set is discovered through the protocol itself (`initialize`, then `tools/list`). Call the `get_documentation` tool first; it returns the full agent API reference, REST endpoints included. The same bearer token as the REST endpoints authenticates it, and every authenticated call slides the token expiry forward, as on the REST endpoints. Discovery document: `/.well-known/agents.json`.",
                "operationId": "6b2cb96786855e551c83c93224454910",
                "requestBody": {
                    "description": "A JSON-RPC 2.0 request. Notifications omit `id`.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "jsonrpc",
                                    "method"
                                ],
                                "properties": {
                                    "jsonrpc": {
                                        "type": "string",
                                        "example": "2.0",
                                        "enum": [
                                            "2.0"
                                        ]
                                    },
                                    "id": {
                                        "description": "Request id, string or integer; absent on a notification",
                                        "example": 1,
                                        "oneOf": [
                                            {
                                                "type": "string"
                                            },
                                            {
                                                "type": "integer"
                                            }
                                        ]
                                    },
                                    "method": {
                                        "type": "string",
                                        "example": "tools/list"
                                    },
                                    "params": {
                                        "description": "Method parameters; the shape depends on the method",
                                        "type": "object"
                                    }
                                },
                                "type": "object"
                            },
                            "example": {
                                "jsonrpc": "2.0",
                                "id": 1,
                                "method": "tools/list",
                                "params": {}
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "A JSON-RPC 2.0 response envelope carrying `result` or `error` for the method called",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "202": {
                        "description": "Accepted with an empty body: the request was a notification (no `id`), so there is nothing to answer"
                    },
                    "401": {
                        "description": "Unauthenticated"
                    },
                    "429": {
                        "description": "Too Many Requests: 120 calls per minute per token; wait Retry-After seconds"
                    }
                },
                "security": [
                    {
                        "sanctum": []
                    }
                ]
            }
        }
    },
    "components": {
        "schemas": {
            "AgentStore": {
                "properties": {
                    "name": {
                        "type": "string",
                        "example": "AliExpress"
                    },
                    "slug": {
                        "type": "string",
                        "example": "aliexpress"
                    },
                    "url": {
                        "description": "The real webshop URL — for context/disambiguation only. Agents must NOT visit this directly; use GET /api/v2/agent/store/{slug}/visit to get an affiliate-tracked redirect.",
                        "type": "string",
                        "format": "uri",
                        "example": "https://www.aliexpress.com"
                    },
                    "image": {
                        "type": "string",
                        "format": "uri",
                        "example": "https://cdn.satsback.com/stores/aliexpress.svg"
                    },
                    "store_id": {
                        "type": "string",
                        "example": "end1md4"
                    },
                    "featured": {
                        "type": "boolean",
                        "example": false
                    },
                    "cashback_type": {
                        "description": "How the reward is delivered. `percent` = percentage of order total credited to your Satsback balance. `fixed_sats` = fixed amount in satoshis credited to your balance. `discount_code` = no satsback is earned — the user gets an immediate discount at checkout via `cashback_code` instead. Always check this field before assuming sats will land in the account.",
                        "type": "string",
                        "example": "percent",
                        "enum": [
                            "percent",
                            "fixed_sats",
                            "discount_code"
                        ]
                    },
                    "text": {
                        "description": "Human-readable headline matching the public store page (e.g. \"Satsback up to 2.7%\" or \"Satsback up to 217836 sats\"). Intended for display to end users.",
                        "type": "string",
                        "example": "Satsback up to 217836 sats"
                    },
                    "commission_percent": {
                        "description": "Cashback percentage for percent-type stores (null for fixed_sats-type). Applied to the EUR order total.",
                        "type": "number",
                        "example": 2,
                        "nullable": true
                    },
                    "commission_sats": {
                        "description": "Maximum fixed cashback in satoshis for fixed_sats-type stores (null for percent-type). Represents the highest tier; see description for any per-plan breakdown.",
                        "type": "integer",
                        "example": 217774,
                        "nullable": true
                    },
                    "discount": {
                        "description": "Only populated for discount_code-type stores. Describes the immediate checkout discount applied via cashback_code. `unit` is either \"percent\" or an ISO 4217 currency code (e.g. \"eur\", \"usd\"). Null for cashback stores.",
                        "properties": {
                            "value": {
                                "type": "number",
                                "example": 5
                            },
                            "unit": {
                                "type": "string",
                                "example": "percent"
                            }
                        },
                        "type": "object",
                        "nullable": true
                    },
                    "description": {
                        "description": "Markdown-formatted store description. Any [amount|EUR] placeholders have been converted to sats. For stores with multiple plans/variants the full per-plan cashback breakdown is embedded here.",
                        "type": "string",
                        "example": "## BigCommerce\n\nPro Plan purchase (217774 sats)\n\nPlus Plan purchase (69686 sats)\n\nStandard Plan purchase (26132 sats)",
                        "nullable": true
                    },
                    "essentials": {
                        "description": "True when this store uses the Essentials code-based flow",
                        "type": "boolean",
                        "example": false
                    },
                    "cashback_code": {
                        "description": "Discount/cashback code for Essentials stores, null otherwise",
                        "type": "string",
                        "example": "SAVE15",
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "StoreDetail": {
                "properties": {
                    "name": {
                        "type": "string",
                        "example": "AliExpress"
                    },
                    "text": {
                        "type": "string",
                        "example": "up to 2% satsback"
                    },
                    "slug": {
                        "type": "string",
                        "example": "aliexpress"
                    },
                    "image": {
                        "type": "string",
                        "format": "uri",
                        "example": "https://cdn.satsback.com/stores/aliexpress.svg"
                    },
                    "description": {
                        "description": "Sanitized HTML description",
                        "type": "string"
                    },
                    "store_id": {
                        "type": "string",
                        "example": "end1md4"
                    },
                    "cashback_type": {
                        "type": "string",
                        "example": "percent",
                        "enum": [
                            "percent",
                            "currency"
                        ]
                    },
                    "currency": {
                        "type": "string",
                        "example": "eur"
                    },
                    "cashback_code": {
                        "description": "Discount code for essentials stores, null otherwise",
                        "type": "string",
                        "example": "SAVE15",
                        "nullable": true
                    },
                    "satsurl": {
                        "type": "string",
                        "format": "uri",
                        "example": "https://satsback.com/store/aliexpress"
                    },
                    "userCommissionVariable": {
                        "description": "Cashback % for percent stores, false for currency stores",
                        "example": 2,
                        "oneOf": [
                            {
                                "type": "number"
                            },
                            {
                                "type": "boolean"
                            }
                        ]
                    },
                    "userCommissionFixed": {
                        "description": "Cashback amount for currency stores, false for percent stores",
                        "example": 1.234,
                        "oneOf": [
                            {
                                "type": "number"
                            },
                            {
                                "type": "boolean"
                            }
                        ]
                    },
                    "featured": {
                        "type": "boolean",
                        "example": true
                    },
                    "essentials": {
                        "type": "boolean",
                        "example": false
                    },
                    "new": {
                        "type": "boolean",
                        "example": false
                    },
                    "support": {
                        "type": "integer",
                        "example": 1,
                        "nullable": true
                    }
                },
                "type": "object"
            }
        },
        "securitySchemes": {
            "sanctum": {
                "type": "http",
                "scheme": "bearer"
            }
        }
    },
    "tags": [
        {
            "name": "Agent Account",
            "description": "Agent Account Management API"
        },
        {
            "name": "Agents",
            "description": "Agent API — L402 registration, store catalog, and cashback clicks"
        },
        {
            "name": "Main",
            "description": "Generic/Helper API methods"
        },
        {
            "name": "Stores",
            "description": "Stores API"
        },
        {
            "name": "User Account",
            "description": "User Account API"
        },
        {
            "name": "Partner Auth",
            "description": "Partner Auth API"
        },
        {
            "name": "Partner Stores",
            "description": "Partner Stores API"
        },
        {
            "name": "Partner Test Orders",
            "description": "Partner API: self-service test orders"
        },
        {
            "name": "Partner Users",
            "description": "Partner API: bearer-first user creation"
        },
        {
            "name": "Affiliates",
            "description": "Affiliates"
        }
    ]
}