{
  "openapi": "3.1.0",
  "info": {
    "title": "Advanta API",
    "version": "1.0.0",
    "description": "Advanta APIs for creditworthiness scoring, ESG assessment, and ERP connectivity.\n\n## Authentication\n\nAll endpoints require a Bearer token (API key). Get sandbox keys at\n[tech.advanta.pt/sandbox](https://tech.advanta.pt/sandbox).\n\n## Environments\n\n- **Sandbox**: `sk_test_*` keys, synthetic data, free, no SLA\n- **Production**: `sk_live_*` keys, real data, metered billing, 99.9% SLA\n\n## Rate limits\n\nPer-API-key, per-minute. Defaults: free 60, starter 600, growth 6000, enterprise negotiated.\nHeaders `X-RateLimit-*` accompany every response.\n\n## Status\n\nLive status at [status.advanta.pt](https://status.advanta.pt).",
    "contact": {
      "name": "Advanta Developer Support",
      "email": "diogo@advanta.pt",
      "url": "https://tech.advanta.pt/docs"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://api.advanta.pt",
      "description": "Production"
    },
    {
      "url": "https://tech.advanta.pt/api",
      "description": "Sandbox"
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key prefixed with `sk_live_` (production) or `sk_test_` (sandbox)."
      },
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "sk_(test|live)_<hex>",
        "description": "API key, sent as Authorization: Bearer sk_test_..."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "requestId": {
            "type": "string"
          },
          "docsUrl": {
            "type": "string",
            "format": "uri"
          },
          "fields": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              },
              "required": [
                "path",
                "message"
              ]
            }
          }
        },
        "required": [
          "code",
          "message",
          "status",
          "requestId"
        ]
      },
      "ScoreRequest": {
        "type": "object",
        "properties": {
          "nif": {
            "type": "string",
            "pattern": "^\\d{9}$"
          },
          "customer_reference": {
            "type": "string",
            "maxLength": 128
          },
          "refresh": {
            "type": "string",
            "enum": [
              "cached_ok",
              "force_refresh"
            ],
            "default": "cached_ok"
          }
        },
        "required": [
          "nif"
        ]
      },
      "ScoreResponse": {
        "type": "object",
        "properties": {
          "score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1000
          },
          "tier": {
            "type": "string",
            "enum": [
              "A",
              "B",
              "C",
              "D",
              "E"
            ]
          },
          "pd_estimate": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0,
            "maximum": 1
          },
          "components": {
            "type": "object",
            "additionalProperties": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            }
          },
          "reasons": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "impact": {
                  "type": "string",
                  "enum": [
                    "positive",
                    "negative"
                  ]
                },
                "weight": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1
                }
              },
              "required": [
                "code",
                "label",
                "impact",
                "weight"
              ]
            }
          },
          "algorithm_version": {
            "type": "string"
          },
          "data_sources": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "computed_at": {
            "type": "string",
            "format": "date-time"
          },
          "cache": {
            "type": "string",
            "enum": [
              "fresh",
              "cached"
            ]
          },
          "synthetic": {
            "type": "boolean"
          },
          "customer_reference": {
            "type": "string"
          }
        },
        "required": [
          "score",
          "tier",
          "pd_estimate",
          "components",
          "reasons",
          "algorithm_version",
          "data_sources",
          "computed_at",
          "cache",
          "synthetic"
        ]
      },
      "EsgRequest": {
        "type": "object",
        "properties": {
          "nif": {
            "type": "string",
            "pattern": "^\\d{9}$"
          },
          "customer_reference": {
            "type": "string",
            "maxLength": 128
          },
          "sector": {
            "type": "string"
          },
          "answers": {
            "type": "object",
            "additionalProperties": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              ]
            }
          }
        },
        "required": [
          "nif",
          "sector",
          "answers"
        ]
      },
      "EsgResponse": {
        "type": "object",
        "properties": {
          "overall": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "tier": {
            "type": "string",
            "enum": [
              "leader",
              "advancer",
              "developing",
              "starter",
              "lagging"
            ]
          },
          "environmental": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "social": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "governance": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "vsme_alignment": {
            "type": "integer",
            "minimum": 0,
            "maximum": 27
          },
          "aligned_sdgs": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1,
              "maximum": 17
            }
          },
          "recommendations": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "pillar": {
                  "type": "string",
                  "enum": [
                    "E",
                    "S",
                    "G"
                  ]
                },
                "priority": {
                  "type": "integer",
                  "minimum": 1
                },
                "title": {
                  "type": "string"
                },
                "body": {
                  "type": "string"
                },
                "effort": {
                  "type": "string",
                  "enum": [
                    "low",
                    "medium",
                    "high"
                  ]
                },
                "impact": {
                  "type": "string",
                  "enum": [
                    "low",
                    "medium",
                    "high"
                  ]
                },
                "timeline": {
                  "type": "string"
                },
                "sdgs": {
                  "type": "array",
                  "items": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 17
                  }
                }
              },
              "required": [
                "id",
                "pillar",
                "priority",
                "title",
                "body",
                "effort",
                "impact",
                "timeline",
                "sdgs"
              ]
            }
          },
          "algorithm_version": {
            "type": "string"
          },
          "computed_at": {
            "type": "string",
            "format": "date-time"
          },
          "synthetic": {
            "type": "boolean"
          },
          "customer_reference": {
            "type": "string"
          }
        },
        "required": [
          "overall",
          "tier",
          "environmental",
          "social",
          "governance",
          "vsme_alignment",
          "aligned_sdgs",
          "recommendations",
          "algorithm_version",
          "computed_at",
          "synthetic"
        ]
      },
      "ErpOAuthInitiateRequest": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "enum": [
              "toconline",
              "primavera",
              "phc",
              "sage",
              "moloni",
              "invoicexpress"
            ]
          },
          "customer_reference": {
            "type": "string",
            "minLength": 1
          },
          "return_url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "provider",
          "customer_reference",
          "return_url"
        ]
      },
      "ErpOAuthInitiateResponse": {
        "type": "object",
        "properties": {
          "authorize_url": {
            "type": "string",
            "format": "uri"
          },
          "state": {
            "type": "string"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "authorize_url",
          "state",
          "expires_at"
        ]
      },
      "ErpSyncRequest": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "enum": [
              "toconline",
              "primavera",
              "phc",
              "sage",
              "moloni",
              "invoicexpress"
            ]
          },
          "customer_reference": {
            "type": "string",
            "minLength": 1
          },
          "since": {
            "type": "string",
            "format": "date-time"
          },
          "mode": {
            "type": "string",
            "enum": [
              "incremental",
              "full"
            ],
            "default": "incremental"
          }
        },
        "required": [
          "provider",
          "customer_reference"
        ]
      },
      "ErpSyncResponse": {
        "type": "object",
        "properties": {
          "run_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running"
            ]
          },
          "estimated_duration_seconds": {
            "type": [
              "integer",
              "null"
            ]
          },
          "webhook_will_fire": {
            "type": "boolean"
          }
        },
        "required": [
          "run_id",
          "status",
          "estimated_duration_seconds",
          "webhook_will_fire"
        ]
      },
      "ErrorBody": {
        "type": "object",
        "required": [
          "code",
          "message",
          "status",
          "requestId"
        ],
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "requestId": {
            "type": "string"
          },
          "docsUrl": {
            "type": "string",
            "format": "uri"
          },
          "fields": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "AdminKey": {
        "type": "object",
        "required": [
          "id",
          "name",
          "env",
          "key_prefix",
          "scopes",
          "created_at",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "env": {
            "type": "string",
            "enum": [
              "sandbox",
              "live"
            ]
          },
          "key_prefix": {
            "type": "string",
            "example": "sk_test_a1b2"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "rate_limit_per_minute": {
            "type": "integer",
            "nullable": true
          },
          "last_used_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "revoked_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "revoked",
              "expired"
            ]
          }
        }
      },
      "WebhookEndpoint": {
        "type": "object",
        "required": [
          "id",
          "url",
          "enabled_events",
          "signing_secret_prefix",
          "status",
          "consecutive_failures",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "enabled_events": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "*"
            ]
          },
          "signing_secret_prefix": {
            "type": "string",
            "example": "whsec_a1b2c3d"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled",
              "failed"
            ]
          },
          "consecutive_failures": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_success_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_failure_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      }
    },
    "parameters": {}
  },
  "paths": {
    "/v1/score": {
      "post": {
        "summary": "Compute creditworthiness score",
        "description": "Returns a 0-1000 creditworthiness score with tier (A-E), probability of default,\ncomponent breakdown, and explainability reasons.\n\n**Tier behavior** (important for live-mode integration testing):\n- `sandbox` keys → returns deterministic synthetic scores from a fixed fixture set (see Sandbox NIFs below)\n- `live` keys before Q3 2026 → returns **HTTP 503 with `code: \"live_tier_not_available\"`** and a `roadmap_url`. This is intentional and documented at https://tech.advanta.pt/roadmap. Banks integrating their production code paths against the live tier should test for this 503 explicitly and degrade gracefully until the live adapter ships.\n- `live` keys from Q3 2026 onward → returns scores composed across Iberinform + BdP CRC + AT validation adapters. Bureau-data lookups are billed as a separate `bureau_passthrough` Stripe meter line (cost+15% wholesale).\n\n**Sandbox NIFs** (sandbox keys only — deterministic responses):\n- `509123456` — Tier A, low PD\n- `508666777` — Tier B, concentration risk\n- `505333444` — Tier D, recent default\n- `999999990` — returns 422 `invalid_nif` (for SDK error-handling tests)\n\n**Caching**: by default returns cached score if computed within last 24h.\nPass `refresh: \"force_refresh\"` to recompute.",
        "x-advanta-readiness": {
          "sandbox": "live",
          "live": "roadmap",
          "live_target_quarter": "Q3 2026",
          "live_blockers": [
            "Iberinform contract signature",
            "BdP CRC partner or aggregator agreement",
            "Stripe bureau_passthrough meter wired"
          ],
          "roadmap_url": "https://tech.advanta.pt/roadmap"
        },
        "tags": [
          "Scoring"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nif": {
                    "type": "string",
                    "pattern": "^\\d{9}$"
                  },
                  "customer_reference": {
                    "type": "string",
                    "maxLength": 128
                  },
                  "refresh": {
                    "type": "string",
                    "enum": [
                      "cached_ok",
                      "force_refresh"
                    ],
                    "default": "cached_ok"
                  }
                },
                "required": [
                  "nif"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Score computed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "score": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 1000
                    },
                    "tier": {
                      "type": "string",
                      "enum": [
                        "A",
                        "B",
                        "C",
                        "D",
                        "E"
                      ]
                    },
                    "pd_estimate": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "minimum": 0,
                      "maximum": 1
                    },
                    "components": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 1
                      }
                    },
                    "reasons": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "code": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "impact": {
                            "type": "string",
                            "enum": [
                              "positive",
                              "negative"
                            ]
                          },
                          "weight": {
                            "type": "number",
                            "minimum": 0,
                            "maximum": 1
                          }
                        },
                        "required": [
                          "code",
                          "label",
                          "impact",
                          "weight"
                        ]
                      }
                    },
                    "algorithm_version": {
                      "type": "string"
                    },
                    "data_sources": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "computed_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "cache": {
                      "type": "string",
                      "enum": [
                        "fresh",
                        "cached"
                      ]
                    },
                    "synthetic": {
                      "type": "boolean"
                    },
                    "customer_reference": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "score",
                    "tier",
                    "pd_estimate",
                    "components",
                    "reasons",
                    "algorithm_version",
                    "data_sources",
                    "computed_at",
                    "cache",
                    "synthetic"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "requestId": {
                      "type": "string"
                    },
                    "docsUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "path",
                          "message"
                        ]
                      }
                    }
                  },
                  "required": [
                    "code",
                    "message",
                    "status",
                    "requestId"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "API key lacks scope or tenant suspended",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "requestId": {
                      "type": "string"
                    },
                    "docsUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "path",
                          "message"
                        ]
                      }
                    }
                  },
                  "required": [
                    "code",
                    "message",
                    "status",
                    "requestId"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Company not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "requestId": {
                      "type": "string"
                    },
                    "docsUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "path",
                          "message"
                        ]
                      }
                    }
                  },
                  "required": [
                    "code",
                    "message",
                    "status",
                    "requestId"
                  ]
                }
              }
            }
          },
          "422": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "requestId": {
                      "type": "string"
                    },
                    "docsUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "path",
                          "message"
                        ]
                      }
                    }
                  },
                  "required": [
                    "code",
                    "message",
                    "status",
                    "requestId"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "requestId": {
                      "type": "string"
                    },
                    "docsUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "path",
                          "message"
                        ]
                      }
                    }
                  },
                  "required": [
                    "code",
                    "message",
                    "status",
                    "requestId"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/esg": {
      "post": {
        "summary": "Compute ESG assessment",
        "tags": [
          "ESG"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nif": {
                    "type": "string",
                    "pattern": "^\\d{9}$"
                  },
                  "customer_reference": {
                    "type": "string",
                    "maxLength": 128
                  },
                  "sector": {
                    "type": "string"
                  },
                  "answers": {
                    "type": "object",
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      ]
                    }
                  }
                },
                "required": [
                  "nif",
                  "sector",
                  "answers"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Assessment computed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "overall": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "tier": {
                      "type": "string",
                      "enum": [
                        "leader",
                        "advancer",
                        "developing",
                        "starter",
                        "lagging"
                      ]
                    },
                    "environmental": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "social": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "governance": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "vsme_alignment": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 27
                    },
                    "aligned_sdgs": {
                      "type": "array",
                      "items": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 17
                      }
                    },
                    "recommendations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "pillar": {
                            "type": "string",
                            "enum": [
                              "E",
                              "S",
                              "G"
                            ]
                          },
                          "priority": {
                            "type": "integer",
                            "minimum": 1
                          },
                          "title": {
                            "type": "string"
                          },
                          "body": {
                            "type": "string"
                          },
                          "effort": {
                            "type": "string",
                            "enum": [
                              "low",
                              "medium",
                              "high"
                            ]
                          },
                          "impact": {
                            "type": "string",
                            "enum": [
                              "low",
                              "medium",
                              "high"
                            ]
                          },
                          "timeline": {
                            "type": "string"
                          },
                          "sdgs": {
                            "type": "array",
                            "items": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 17
                            }
                          }
                        },
                        "required": [
                          "id",
                          "pillar",
                          "priority",
                          "title",
                          "body",
                          "effort",
                          "impact",
                          "timeline",
                          "sdgs"
                        ]
                      }
                    },
                    "algorithm_version": {
                      "type": "string"
                    },
                    "computed_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "synthetic": {
                      "type": "boolean"
                    },
                    "customer_reference": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "overall",
                    "tier",
                    "environmental",
                    "social",
                    "governance",
                    "vsme_alignment",
                    "aligned_sdgs",
                    "recommendations",
                    "algorithm_version",
                    "computed_at",
                    "synthetic"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "requestId": {
                      "type": "string"
                    },
                    "docsUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "path",
                          "message"
                        ]
                      }
                    }
                  },
                  "required": [
                    "code",
                    "message",
                    "status",
                    "requestId"
                  ]
                }
              }
            }
          },
          "422": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "requestId": {
                      "type": "string"
                    },
                    "docsUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "path",
                          "message"
                        ]
                      }
                    }
                  },
                  "required": [
                    "code",
                    "message",
                    "status",
                    "requestId"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "requestId": {
                      "type": "string"
                    },
                    "docsUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "path",
                          "message"
                        ]
                      }
                    }
                  },
                  "required": [
                    "code",
                    "message",
                    "status",
                    "requestId"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/erp-connector/oauth/initiate": {
      "post": {
        "summary": "Start ERP OAuth flow",
        "tags": [
          "ERP Connector"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": [
                      "toconline",
                      "primavera",
                      "phc",
                      "sage",
                      "moloni",
                      "invoicexpress"
                    ]
                  },
                  "customer_reference": {
                    "type": "string",
                    "minLength": 1
                  },
                  "return_url": {
                    "type": "string",
                    "format": "uri"
                  }
                },
                "required": [
                  "provider",
                  "customer_reference",
                  "return_url"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Authorize URL",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "authorize_url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "state": {
                      "type": "string"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "authorize_url",
                    "state",
                    "expires_at"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/erp-connector/sync": {
      "post": {
        "summary": "Trigger ERP sync",
        "description": "Pulls invoices and transactions from the connected ERP into the bank tenant.\n\n**Tier behavior:**\n- `sandbox` keys + `demo` provider → fully functional with synthetic data\n- `sandbox` keys + real provider names (`toconline`, `primavera`, etc.) → returns synthetic data labelled with that provider (no real OAuth, no real fetch)\n- `live` keys with real provider → live OAuth integration shipping per https://tech.advanta.pt/roadmap (TOC Online targeted Q3 2026, others Q1 2027)\n\nUntil live OAuth ships per provider, `live` keys requesting non-`demo` providers return `503 oauth_credentials_not_configured`.",
        "tags": [
          "ERP Connector"
        ],
        "x-advanta-readiness": {
          "sandbox_demo": "live",
          "sandbox_real_providers": "live (synthetic data)",
          "live_oauth_per_provider": {
            "toc_online": "roadmap (Q3 2026)",
            "primavera": "roadmap (Q4 2026)",
            "phc": "roadmap (Q4 2026)",
            "moloni": "roadmap (Q4 2026)",
            "sage": "roadmap (Q4 2026)",
            "invoicexpress": "roadmap (Q4 2026)",
            "vendus_holded_odoo_dynamics_jasmin_netsuite_sap": "roadmap (Q1 2027)"
          },
          "roadmap_url": "https://tech.advanta.pt/roadmap"
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": [
                      "toconline",
                      "primavera",
                      "phc",
                      "sage",
                      "moloni",
                      "invoicexpress"
                    ]
                  },
                  "customer_reference": {
                    "type": "string",
                    "minLength": 1
                  },
                  "since": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "incremental",
                      "full"
                    ],
                    "default": "incremental"
                  }
                },
                "required": [
                  "provider",
                  "customer_reference"
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Sync queued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "run_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "queued",
                        "running"
                      ]
                    },
                    "estimated_duration_seconds": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "webhook_will_fire": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "run_id",
                    "status",
                    "estimated_duration_seconds",
                    "webhook_will_fire"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/keys": {
      "get": {
        "tags": [
          "Admin · Keys"
        ],
        "summary": "List this tenant's API keys",
        "description": "Returns metadata only — no plaintext, no hash. Requires scope keys:manage or *.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AdminKey"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Missing scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/keys/rotate": {
      "post": {
        "tags": [
          "Admin · Keys"
        ],
        "summary": "Rotate an API key",
        "description": "Issues a fresh key. The OLD key gets expires_at = now() + grace_days (max 30, default 7). Plaintext shown once.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "api_key_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "grace_days": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 30,
                    "default": 7
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "api_key": {
                      "type": "string",
                      "example": "sk_test_<28hex>"
                    },
                    "api_key_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "rotated_from": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "old_expires_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "grace_days": {
                      "type": "integer"
                    },
                    "warning": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Missing scope or cross-tenant attempt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/keys/revoke": {
      "post": {
        "tags": [
          "Admin · Keys"
        ],
        "summary": "Revoke an API key",
        "description": "Marks the key revoked immediately. Idempotent. Refuses to revoke the LAST active key.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "api_key_id"
                ],
                "properties": {
                  "api_key_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "reason": {
                    "type": "string",
                    "maxLength": 256
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revoked": {
                      "type": "boolean"
                    },
                    "revoked_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "api_key_id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Refused — last active key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "422": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/gdpr/export": {
      "post": {
        "tags": [
          "Admin · GDPR"
        ],
        "summary": "GDPR Article 15 — export tenant data",
        "description": "Returns a JSON bundle of every record we hold tied to your tenant.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Export bundle",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/gdpr/erase": {
      "post": {
        "tags": [
          "Admin · GDPR"
        ],
        "summary": "GDPR Article 17 — erase tenant",
        "description": "IRREVERSIBLE. Anonymizes PII, retains rows under Lei 83/2017 (PT AML 7-year retention). All keys revoked immediately.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "confirmation"
                ],
                "properties": {
                  "confirmation": {
                    "type": "string",
                    "enum": [
                      "ERASE-MY-DATA"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "erased": {
                      "type": "boolean"
                    },
                    "tenant_status": {
                      "type": "string",
                      "enum": [
                        "terminated"
                      ]
                    },
                    "redacted_api_keys": {
                      "type": "integer"
                    },
                    "redacted_usage_rows": {
                      "type": "integer"
                    },
                    "redacted_audit_rows": {
                      "type": "integer"
                    },
                    "retained_under_legal_basis": {
                      "type": "object"
                    },
                    "completed_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "confirmation_required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/webhooks": {
      "get": {
        "tags": [
          "Admin · Webhooks"
        ],
        "summary": "List webhook endpoints",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "endpoints": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookEndpoint"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Admin · Webhooks"
        ],
        "summary": "Register a webhook endpoint",
        "description": "Up to 20 active endpoints per tenant. URL must be HTTPS. The signing secret is returned ONCE.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048
                  },
                  "enabled_events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "default": [
                      "*"
                    ]
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 256
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "endpoint_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "signing_secret": {
                      "type": "string",
                      "example": "whsec_<64hex>"
                    },
                    "warning": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "too_many_endpoints",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "422": {
            "description": "invalid_request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Admin · Webhooks"
        ],
        "summary": "Soft-delete a webhook endpoint",
        "description": "Sets status = disabled. Idempotent.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean"
                    },
                    "endpoint_id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/webhooks/rotate": {
      "post": {
        "tags": [
          "Admin · Webhooks"
        ],
        "summary": "Rotate a webhook signing secret",
        "description": "Old secret stops working immediately. Plaintext shown once.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "endpoint_id"
                ],
                "properties": {
                  "endpoint_id": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "endpoint_id": {
                      "type": "string"
                    },
                    "signing_secret": {
                      "type": "string"
                    },
                    "warning": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/webhooks/test": {
      "post": {
        "tags": [
          "Admin · Webhooks"
        ],
        "summary": "Send a synthetic webhook.test event",
        "description": "Useful for verifying signature handling. Delivery is asynchronous; expect arrival within ~60 seconds.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "endpoint_id"
                ],
                "properties": {
                  "endpoint_id": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted — event enqueued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "event_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "endpoint_id": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/status": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Public health check",
        "description": "No auth required. Returns 200/207/503 based on DB reachability, cron heartbeat, and recent 5xx rate.",
        "responses": {
          "200": {
            "description": "Operational",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "207": {
            "description": "Degraded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "503": {
            "description": "Down",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {},
  "tags": [
    {
      "name": "Score",
      "description": "Credit-scoring API."
    },
    {
      "name": "ESG",
      "description": "ESG assessment API."
    },
    {
      "name": "ERP Connector",
      "description": "OAuth + sync against accounting software."
    },
    {
      "name": "Admin · Keys",
      "description": "Self-service API key lifecycle. Tenant-scoped."
    },
    {
      "name": "Admin · GDPR",
      "description": "GDPR Art. 15 (export) and Art. 17 (erasure) for B2B API tenants."
    },
    {
      "name": "Admin · Webhooks",
      "description": "Stripe-style webhook endpoints. HMAC-SHA256 signed deliveries with 5-attempt exponential-backoff retries."
    },
    {
      "name": "Health",
      "description": "Public health check."
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ]
}