{
  "openapi": "3.1.0",
  "info": {
    "title": "LatAm Tax ID API",
    "version": "0.1.0",
    "description": "Validate Latin American tax IDs. v0.1 covers Peru RUC (company RUCs, prefix 20, return full SUNAT registry data; natural-person RUCs return check-digit validation only). Also available as a remote MCP server at /mcp (Streamable HTTP, tool `validate_peru_ruc`).",
    "contact": {
      "name": "HALPII S.A.C.",
      "email": "contacto@halpii.com"
    }
  },
  "servers": [
    {
      "url": "https://taxid.halpii.com"
    }
  ],
  "security": [
    {
      "bearer": []
    },
    {
      "apiKeyHeader": []
    },
    {}
  ],
  "paths": {
    "/v1/pe/ruc/{ruc}": {
      "get": {
        "operationId": "validatePeruRuc",
        "summary": "Validate a Peru RUC and look up the company",
        "description": "Checks the RUC format and check digit, then looks up legal-entity RUCs (prefix 20) in the SUNAT Padrón Reducido. Counts against the daily quota (10/day without a key, 100/day with a free key).",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9 .-]{11,20}$"
            },
            "example": "20100047218"
          }
        ],
        "responses": {
          "200": {
            "description": "Lookup result (including invalid check digit, not found, or withheld natural-person RUC)",
            "headers": {
              "x-ratelimit-limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "schema": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RucResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed RUC (not 11 digits or unknown prefix)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RucResult"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Daily quota exceeded",
            "headers": {
              "x-ratelimit-limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "x-ratelimit-reset": {
                "schema": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/keys": {
      "post": {
        "operationId": "createApiKey",
        "summary": "Create a free API key",
        "security": [
          {}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Key created (shown once)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key_id": {
                      "type": "string"
                    },
                    "api_key": {
                      "type": "string"
                    },
                    "plan": {
                      "type": "string"
                    },
                    "daily_limit": {
                      "type": "integer"
                    },
                    "note": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid email",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many keys from this network today",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Usage of your API key (last 30 days)",
        "security": [
          {
            "bearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "responses": {
          "200": {
            "description": "Usage",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key_id": {
                      "type": "string"
                    },
                    "plan": {
                      "type": "string"
                    },
                    "daily_limit": {
                      "type": "integer"
                    },
                    "used_today": {
                      "type": "integer"
                    },
                    "last_30_days": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "day": {
                            "type": "string"
                          },
                          "count": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "operationId": "health",
        "summary": "Health and data freshness",
        "security": [
          {}
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "pe_padron_as_of": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer"
      },
      "apiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      }
    },
    "schemas": {
      "RucResult": {
        "type": "object",
        "required": [
          "country",
          "id_type",
          "format_valid",
          "check_digit_valid",
          "taxpayer_type",
          "found",
          "assessment",
          "source"
        ],
        "properties": {
          "country": {
            "type": "string",
            "const": "PE"
          },
          "id_type": {
            "type": "string",
            "const": "RUC"
          },
          "ruc": {
            "type": [
              "string",
              "null"
            ],
            "example": "20100047218"
          },
          "input": {
            "type": "string"
          },
          "format_valid": {
            "type": "boolean",
            "description": "11 digits with a known prefix (10, 15, 16, 17, 20)"
          },
          "check_digit_valid": {
            "type": "boolean",
            "description": "Mod-11 check digit matches. Computed offline."
          },
          "taxpayer_type": {
            "type": "string",
            "enum": [
              "legal_entity",
              "natural_person",
              "unknown"
            ]
          },
          "found": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "true/false = looked up in the registry; null = not looked up (invalid, or natural person withheld for privacy)"
          },
          "legal_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "code": {
                "type": "string",
                "example": "ACTIVO"
              },
              "label": {
                "type": "string",
                "example": "Active"
              },
              "active": {
                "type": "boolean"
              }
            }
          },
          "domicile_condition": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "code": {
                "type": "string",
                "example": "HABIDO"
              },
              "label": {
                "type": "string"
              },
              "located": {
                "type": "boolean"
              }
            }
          },
          "address": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "line": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "ubigeo": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "INEI 6-digit district code"
              },
              "district": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "province": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "department": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "country": {
                "type": "string",
                "const": "PE"
              }
            }
          },
          "assessment": {
            "type": "object",
            "properties": {
              "verdict": {
                "type": "string",
                "enum": [
                  "pass",
                  "review",
                  "fail"
                ]
              },
              "reasons": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "source": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "url": {
                "type": "string"
              },
              "data_as_of": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date"
              }
            }
          },
          "notice": {
            "type": "string"
          },
          "disclaimer": {
            "type": "string"
          }
        }
      }
    }
  }
}