{
  "openapi": "3.1.0",
  "info": {
    "title": "Benefits City API",
    "version": "0.3.0",
    "description": "Read-only, no-auth API for US bank-account, savings and credit-card signup bonuses. Same data and ordering as the MCP tools (value descending, never influenced by commission). Errors use {error:{type,message,code?,param?}}.",
    "contact": {
      "email": "bonuses@aiagentscity.com"
    }
  },
  "servers": [
    {
      "url": "https://aiagentscity.com/benefits"
    }
  ],
  "paths": {
    "/api/search": {
      "get": {
        "operationId": "searchBonuses",
        "summary": "Search offers (same filters as the MCP search_bonuses tool)",
        "parameters": [
          {
            "name": "bonus_type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "bank_account",
                "credit_card",
                "savings"
              ]
            }
          },
          {
            "name": "state",
            "in": "query",
            "description": "2-letter US state code; nationwide offers always match",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{2}$"
            }
          },
          {
            "name": "min_bonus_amount_usd",
            "in": "query",
            "description": "Cards: estimated USD value of points",
            "schema": {
              "type": "number",
              "minimum": 0
            }
          },
          {
            "name": "direct_deposit_required",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "query",
            "in": "query",
            "description": "Keyword on bank/issuer and product name",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Offers, highest bonus first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Bonus"
                  }
                }
              }
            }
          },
          "400": {
            "description": "invalid_param — names the offending parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/expiring": {
      "get": {
        "operationId": "expiringSoon",
        "summary": "Offers expiring within N days, soonest first",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 365,
              "default": 30
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Offers with a stated expiry inside the window",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Bonus"
                  }
                }
              }
            }
          },
          "400": {
            "description": "invalid_param",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/compare": {
      "get": {
        "operationId": "compareBonuses",
        "summary": "Compare 2 to 4 offers",
        "parameters": [
          {
            "name": "ids",
            "in": "query",
            "required": true,
            "description": "Comma-separated, 2 to 4 distinct ids",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The offers plus a summary naming the highest bonus and earliest expiry",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "bonuses": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Bonus"
                      }
                    },
                    "summary": {
                      "type": "object",
                      "properties": {
                        "highest_bonus_usd": {
                          "type": "string"
                        },
                        "earliest_expiry": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "invalid_param — wrong id count or duplicates",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "not_found — an id is unknown or expired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/bonuses/{id}": {
      "get": {
        "operationId": "getBonus",
        "summary": "One offer",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The offer",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Bonus"
                }
              }
            }
          },
          "404": {
            "description": "not_found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/bonuses.json": {
      "get": {
        "operationId": "listBonuses",
        "summary": "Every currently served offer",
        "responses": {
          "200": {
            "description": "All offers",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Bonus"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/insights": {
      "get": {
        "operationId": "getInsights",
        "summary": "Original statistics computed live from the served offers (counts, medians, shares) with denominators and an as_of date",
        "responses": {
          "200": {
            "description": "Insights",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/api/stats": {
      "get": {
        "operationId": "getStats",
        "summary": "Live counts and totals",
        "responses": {
          "200": {
            "description": "Stats",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/go/{id}": {
      "get": {
        "operationId": "applyRedirect",
        "summary": "Tracked apply link: 302 to the issuer (or partner) page. Use apply_url from an offer.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Redirect to the offer page"
          },
          "404": {
            "description": "Unknown or expired offer"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "type",
              "message"
            ],
            "properties": {
              "type": {
                "type": "string",
                "examples": [
                  "invalid_param",
                  "not_found"
                ]
              },
              "message": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "param": {
                "type": "string"
              }
            }
          }
        }
      },
      "Bonus": {
        "type": "object",
        "required": [
          "id",
          "bank_or_issuer",
          "product_name",
          "bonus_type",
          "bonus_amount_usd"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "bank_or_issuer": {
            "type": "string"
          },
          "product_name": {
            "type": "string"
          },
          "bonus_type": {
            "type": "string",
            "enum": [
              "bank_account",
              "credit_card",
              "savings"
            ]
          },
          "bonus_amount_usd": {
            "type": "number",
            "description": "Cards: estimated USD value of points"
          },
          "bonus_max_usd": {
            "type": "number",
            "nullable": true,
            "description": "Top tier of a tiered offer; bonus_amount_usd is the value the stated requirements earn"
          },
          "bonus_points": {
            "type": [
              "number",
              "null"
            ]
          },
          "annual_fee_usd": {
            "type": [
              "number",
              "null"
            ]
          },
          "requirements": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "min_deposit_usd": {
            "type": [
              "number",
              "null"
            ]
          },
          "direct_deposit_required": {
            "type": "boolean"
          },
          "expiry_date": {
            "type": [
              "string",
              "null"
            ],
            "description": "YYYY-MM-DD (US Eastern) or null"
          },
          "states_available": {
            "oneOf": [
              {
                "type": "string",
                "const": "nationwide"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          },
          "application_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "source_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_verified_date": {
            "type": [
              "string",
              "null"
            ]
          },
          "offer_history": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "verification": {
            "type": [
              "object",
              "null"
            ],
            "description": "{method: issuer_page|aggregator_consensus, verified_at, sources[]}"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "expired",
              "needs_review"
            ]
          },
          "eligibility": {
            "type": [
              "object",
              "null"
            ]
          },
          "sponsored": {
            "type": "boolean",
            "description": "True when the apply link is an affiliate link"
          },
          "apply_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Our tracked /go link"
          },
          "disclosure_url": {
            "type": "string"
          }
        }
      }
    }
  }
}