{
  "openapi": "3.0.3",
  "info": {
    "title": "Maxiaa Partner API",
    "version": "1.0.0",
    "description": "Publieke REST-API voor identiteitsverificatie (KYC/Wwft). Start een verificatie, volg de status, en ontvang een ondertekende webhook zodra het verdict klaar is. Authenticatie via een API-sleutel (Bearer). Sandbox- en live-omgeving zijn gescheiden via de sleutel-prefix (mxa_test_ / mxa_live_).",
    "contact": {
      "name": "Maxiaa support",
      "email": "support@maxiaa.com"
    }
  },
  "servers": [
    {
      "url": "https://wkrhvuxmsbvzqluwigst.supabase.co/functions/v1/v1",
      "description": "Interim (Supabase Edge). Na domeinregistratie: https://api.maxiaa.com/v1"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Verifications",
      "description": "Verificaties starten, opvragen en (in sandbox) afronden."
    },
    {
      "name": "Webhooks",
      "description": "Endpoints registreren voor ondertekende events."
    },
    {
      "name": "System",
      "description": "Liveness."
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "tags": [
          "System"
        ],
        "summary": "Liveness-check",
        "security": [],
        "operationId": "getHealth",
        "responses": {
          "200": {
            "description": "Service leeft",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/verifications": {
      "post": {
        "tags": [
          "Verifications"
        ],
        "summary": "Start een verificatie",
        "operationId": "createVerification",
        "description": "Maakt een verificatie-verzoek en retourneert een `verify_url` die je de eindgebruiker laat doorlopen. In de sandbox-omgeving wordt de verificatie standaard direct met een voorspelbaar verdict afgerond (stel `sandbox.auto_complete: false` in om de asynchrone levenscyclus na te bootsen).",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateVerificationRequest"
              },
              "examples": {
                "standaard": {
                  "value": {
                    "method": "document_liveness",
                    "reference": "klant-8821"
                  }
                },
                "sandbox_async": {
                  "value": {
                    "reference": "test-01",
                    "sandbox": {
                      "scenario": "approved",
                      "auto_complete": false
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Verificatie aangemaakt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Verification"
                }
              }
            },
            "headers": {
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              }
            }
          },
          "401": {
            "description": "Ontbrekende of ongeldige API-sleutel",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API-sleutel mist de scope verify:create",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Idempotency-Key hergebruikt met andere inhoud",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit bereikt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Verifications"
        ],
        "summary": "Lijst verificaties (cursor-paginatie)",
        "operationId": "listVerifications",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "id van de laatste rij op de vorige pagina"
          }
        ],
        "responses": {
          "200": {
            "description": "Lijst",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationList"
                }
              }
            }
          },
          "401": {
            "description": "Ontbrekende of ongeldige API-sleutel",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit bereikt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/verifications/{id}": {
      "get": {
        "tags": [
          "Verifications"
        ],
        "summary": "Haal één verificatie op (status + verdict + dossier-ref)",
        "operationId": "getVerification",
        "parameters": [
          {
            "$ref": "#/components/parameters/VerificationId"
          }
        ],
        "responses": {
          "200": {
            "description": "Verificatie",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Verification"
                }
              }
            }
          },
          "401": {
            "description": "Ontbrekende of ongeldige API-sleutel",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Niet gevonden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/verifications/{id}/complete": {
      "post": {
        "tags": [
          "Verifications"
        ],
        "summary": "Rond een sandbox-verificatie af (alleen sandbox)",
        "operationId": "completeSandboxVerification",
        "description": "Simuleert dat de eindgebruiker de verify-link met een specimen-document heeft doorlopen; levert een voorspelbaar verdict (= scenario) en vuurt de webhook af. Werkt uitsluitend met een sandbox-sleutel.",
        "parameters": [
          {
            "$ref": "#/components/parameters/VerificationId"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "scenario": {
                    "$ref": "#/components/schemas/SandboxScenario"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Afgerond",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Verification"
                }
              }
            }
          },
          "403": {
            "description": "Geen sandbox-sleutel",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Niet gevonden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Al afgerond",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Registreer een webhook-endpoint",
        "operationId": "createWebhook",
        "description": "Retourneert het `secret` ÉÉNMALIG. Bewaar het veilig; het wordt daarna nooit meer getoond. Gebruik het om de `X-Maxiaa-Signature`-header te verifiëren.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Endpoint aangemaakt (met secret)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointWithSecret"
                }
              }
            }
          },
          "401": {
            "description": "Ontbrekende of ongeldige API-sleutel",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API-sleutel mist de scope webhooks:manage",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ongeldige url",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Lijst webhook-endpoints (zonder secret)",
        "operationId": "listWebhooks",
        "responses": {
          "200": {
            "description": "Lijst",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookEndpoint"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Haal één webhook-endpoint op",
        "operationId": "getWebhook",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          }
        ],
        "responses": {
          "200": {
            "description": "Endpoint",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            }
          },
          "404": {
            "description": "Niet gevonden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Deactiveer een webhook-endpoint",
        "operationId": "deleteWebhook",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          }
        ],
        "responses": {
          "200": {
            "description": "Gedeactiveerd",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Niet gevonden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API-sleutel met prefix `mxa_test_` (sandbox) of `mxa_live_` (productie). Stuur als `Authorization: Bearer <sleutel>`."
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string"
        },
        "description": "Herhaal veilig: dezelfde sleutel + dezelfde body geeft exact hetzelfde antwoord."
      },
      "VerificationId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "WebhookId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "headers": {
      "RateLimitRemaining": {
        "description": "Resterende requests in het huidige minuutvenster",
        "schema": {
          "type": "integer"
        }
      }
    },
    "schemas": {
      "SandboxScenario": {
        "type": "string",
        "enum": [
          "approved",
          "review",
          "rejected"
        ],
        "default": "approved"
      },
      "Method": {
        "type": "string",
        "enum": [
          "document_liveness",
          "idin",
          "document_only"
        ],
        "default": "document_liveness"
      },
      "CreateVerificationRequest": {
        "type": "object",
        "properties": {
          "method": {
            "$ref": "#/components/schemas/Method"
          },
          "reference": {
            "type": "string",
            "description": "Je eigen referentie (bv. gebruiker-id). Komt terug in de webhook.",
            "maxLength": 200
          },
          "sandbox": {
            "type": "object",
            "properties": {
              "scenario": {
                "$ref": "#/components/schemas/SandboxScenario"
              },
              "auto_complete": {
                "type": "boolean",
                "default": true
              }
            }
          }
        }
      },
      "Verification": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string",
            "example": "verification"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "in_progress",
              "completed"
            ]
          },
          "environment": {
            "type": "string",
            "enum": [
              "sandbox",
              "live"
            ]
          },
          "method": {
            "$ref": "#/components/schemas/Method"
          },
          "reference": {
            "type": "string",
            "nullable": true
          },
          "verify_url": {
            "type": "string",
            "format": "uri"
          },
          "verdict": {
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/Verdict"
              }
            ]
          },
          "dossier_ref": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Verdict": {
        "type": "object",
        "properties": {
          "outcome": {
            "type": "string",
            "enum": [
              "approved",
              "review",
              "rejected"
            ]
          },
          "assurance_level": {
            "type": "string",
            "enum": [
              "low",
              "substantial",
              "high"
            ],
            "nullable": true
          },
          "reasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "reviewed": {
            "type": "boolean"
          }
        }
      },
      "VerificationList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "example": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Verification"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_starting_after": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "CreateWebhookRequest": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "https-URL van je ontvanger"
          },
          "description": {
            "type": "string",
            "maxLength": 200
          },
          "event_types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "default": [
              "verification.completed"
            ]
          },
          "environment": {
            "type": "string",
            "enum": [
              "all",
              "sandbox",
              "live"
            ],
            "default": "all"
          }
        }
      },
      "WebhookEndpoint": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "event_types": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "environment": {
            "type": "string"
          },
          "active": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookEndpointWithSecret": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEndpoint"
          },
          {
            "type": "object",
            "properties": {
              "secret": {
                "type": "string",
                "description": "whsec_… — eenmalig getoond"
              }
            }
          }
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "authentication_error",
                  "invalid_request_error",
                  "not_found_error",
                  "rate_limit_error",
                  "idempotency_error",
                  "api_error"
                ]
              },
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "request_id": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}