{
  "openapi": "3.1.0",
  "info": {
    "title": "CodigosAfiliados public feeds",
    "description": "Read-only, unauthenticated JSON feeds for AI/LLM citation and agent consumption. Community-verified referral codes for Spain. Documented for humans and models in /llms.txt; discoverable via /.well-known/api-catalog (RFC 9727). Markdown representations of content pages exist at /marca/{slug}.md and /blog/{slug}.md. Rate limit: 120 requests per minute per client on the dynamic endpoints, announced live via RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset headers (IETF RateLimit-Fields draft); exceeding it returns a 429 with Retry-After. /api/codes-index.json is a static file and is not rate-limited.",
    "version": "1.1.0",
    "contact": {
      "url": "https://www.codigosafiliados.com/contacto"
    }
  },
  "servers": [
    {
      "url": "https://www.codigosafiliados.com"
    }
  ],
  "paths": {
    "/api/codes-index.json": {
      "get": {
        "operationId": "getCodesIndex",
        "summary": "Index of brands with active referral codes",
        "description": "Top brands with at least one community-verified active code, each with its canonical hub URL. Regenerated continuously; cache-friendly.",
        "responses": {
          "200": {
            "description": "The index.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "source": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "generated_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "total_brands": {
                      "type": "integer"
                    },
                    "total_active_codes": {
                      "type": "integer"
                    },
                    "brands": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "slug": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string",
                            "format": "uri"
                          }
                        },
                        "additionalProperties": true
                      }
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "503": {
            "description": "The database could not be reached. Retry after the Retry-After header; this response is never cached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/brand-summary/{slug}.json": {
      "get": {
        "operationId": "getBrandSummary",
        "summary": "One brand's referral-programme summary",
        "description": "The facts an agent needs to answer «does {brand} have a referral code and what does it pay»: top code, rewards for both parties, terms, verification count and the canonical hub URL.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9-]+$"
            },
            "description": "Brand slug, e.g. n26. The full slug list is in /api/codes-index.json."
          }
        ],
        "responses": {
          "200": {
            "description": "The brand summary.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "brand": {
                      "type": "string"
                    },
                    "slug": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "website": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "uri"
                    },
                    "category": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "active_code_count": {
                      "type": "integer"
                    },
                    "top_code": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "reward_user": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "reward_referrer": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "terms": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "404": {
            "description": "No brand with that slug has an active referral programme here. Body is the standard error object with code brand_not_found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "The database could not be reached. Retry after the Retry-After header; this response is never cached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/{unknown}": {
      "get": {
        "operationId": "unknownEndpoint",
        "summary": "Any /api/* path that is not documented above",
        "description": "Answers with the standard JSON error object (code endpoint_not_found) instead of the site's HTML 404 page, so an agent that guesses a URL gets something parseable. The documented surface is the two feeds above.",
        "parameters": [
          {
            "name": "unknown",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Any undocumented path segment."
          }
        ],
        "responses": {
          "404": {
            "description": "Standard error object, code endpoint_not_found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/codes-index.json": {
      "get": {
        "operationId": "getCodesIndexV1",
        "summary": "Index of brands with active referral codes (v1)",
        "description": "Versioned v1 endpoint. Top brands with at least one community-verified active code, each with its canonical hub URL. Regenerated continuously; cache-friendly.",
        "responses": {
          "200": {
            "description": "The index.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "source": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "generated_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "total_brands": {
                      "type": "integer"
                    },
                    "total_active_codes": {
                      "type": "integer"
                    },
                    "brands": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "slug": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string",
                            "format": "uri"
                          }
                        },
                        "additionalProperties": true
                      }
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/brand-summary/{slug}.json": {
      "get": {
        "operationId": "getBrandSummaryV1",
        "summary": "Top referral codes and verified rewards for a brand (v1)",
        "description": "Versioned v1 endpoint. Highest-voted community referral codes, user and referrer rewards, and verification status for one brand. Dynamic, rate-limited.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9-]+$"
            },
            "description": "Brand slug, e.g. n26. The full slug list is in /api/codes-index.json."
          }
        ],
        "responses": {
          "200": {
            "description": "The brand summary.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "brand": {
                      "type": "string"
                    },
                    "slug": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "website": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "uri"
                    },
                    "category": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "active_code_count": {
                      "type": "integer"
                    },
                    "top_code": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "reward_user": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "reward_referrer": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "terms": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "404": {
            "description": "No brand with that slug has an active referral programme here. Body is the standard error object with code brand_not_found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "The database could not be reached. Retry after the Retry-After header; this response is never cached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "responses": {
      "RateLimited": {
        "description": "Rate limit exceeded: more than 120 requests in the current 60-second window. Body is the standard error object with code rate_limited. Wait Retry-After seconds; the RateLimit-* headers are also present on non-429 responses from rate-limited endpoints, so a client can self-throttle before ever hitting this.",
        "headers": {
          "Retry-After": {
            "description": "Seconds until the window resets. Always equals RateLimit-Reset.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Limit": {
            "description": "Requests allowed per 60-second window (120).",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Remaining": {
            "description": "Requests left in the current window.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Reset": {
            "description": "Seconds until the window resets.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error",
          "code",
          "message"
        ],
        "description": "Every error from this API is this shape: a short human label, a stable machine code, a Spanish sentence explaining what happened, and where to look next. HTML is never returned for an /api/* error.",
        "properties": {
          "error": {
            "type": "string",
            "description": "Short label, e.g. Not found."
          },
          "code": {
            "type": "string",
            "description": "Stable machine-readable code. Safe to branch on; the message text is not.",
            "examples": [
              "endpoint_not_found",
              "brand_not_found",
              "rate_limited"
            ]
          },
          "message": {
            "type": "string",
            "description": "What happened, in Spanish."
          },
          "hint": {
            "type": "string",
            "description": "Where to look to resolve it. Optional."
          }
        }
      }
    }
  },
  "security": [],
  "x-api-versioning": {
    "version": "v1",
    "strategy": "url-path",
    "supported_versions": [
      "v1"
    ],
    "deprecation_policy": "https://www.codigosafiliados.com/developers#deprecation"
  }
}
