{
  "openapi": "3.1.0",
  "info": {
    "title": "Capvant API",
    "version": "1.0.0",
    "summary": "Lender API and Partner API for the Capvant SME funding marketplace.",
    "description": "Two API families, one authentication and error model. The Lender API (`/v1`) lets funding partners pull their deal flow, report statuses, submit offers, message clients, and receive webhooks. The Partner API (`/partner/v1`) lets referral partners submit and track referrals and receive webhooks. Both are authenticated with an `X-API-Key` header and share the same error envelope, rate limit, and webhook signing scheme.",
    "contact": {
      "name": "Capvant Partnerships",
      "email": "partnerships@capvant.com"
    }
  },
  "servers": [
    {
      "url": "https://api.capvant.com/v1",
      "description": "Lender API v1"
    },
    {
      "url": "https://api.capvant.com/partner/v1",
      "description": "Partner API v1"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "Lender: Meta",
      "description": "Liveness and auth check."
    },
    {
      "name": "Lender: Deals",
      "description": "Read and update deals routed to your lane."
    },
    {
      "name": "Lender: Messages",
      "description": "The client conversation on a deal."
    },
    {
      "name": "Lender: Documents",
      "description": "Typed document requests on a deal."
    },
    {
      "name": "Lender: Webhooks",
      "description": "Register endpoints to receive deal events."
    },
    {
      "name": "Lender: Sandbox",
      "description": "Self-serve synthetic test deals."
    },
    {
      "name": "Partner: Meta",
      "description": "Liveness and auth check."
    },
    {
      "name": "Partner: Referrals",
      "description": "Submit and track referrals."
    },
    {
      "name": "Partner: Webhooks",
      "description": "Register endpoints to receive referral events."
    }
  ],
  "paths": {
    "/ping": {
      "get": {
        "operationId": "lenderPing",
        "tags": [
          "Lender: Meta"
        ],
        "summary": "Verify your Lender API key",
        "responses": {
          "200": {
            "description": "Key is valid.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "lender": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "ok",
                    "lender"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/deals": {
      "get": {
        "operationId": "listDeals",
        "tags": [
          "Lender: Deals"
        ],
        "summary": "List deals routed to your lane",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "new",
                "in_review",
                "offer_made",
                "declined",
                "funded"
              ]
            },
            "description": "Filter by your reported lender_status."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Opaque cursor from a previous page's next_cursor."
          }
        ],
        "responses": {
          "200": {
            "description": "A page of deals.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deals": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DealSummary"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "deals",
                    "next_cursor"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/deals/{ref}": {
      "get": {
        "operationId": "getDeal",
        "tags": [
          "Lender: Deals"
        ],
        "summary": "Retrieve a deal",
        "parameters": [
          {
            "$ref": "#/components/parameters/DealRef"
          }
        ],
        "responses": {
          "200": {
            "description": "The deal.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DealDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/deals/{ref}/status": {
      "post": {
        "operationId": "updateDealStatus",
        "tags": [
          "Lender: Deals"
        ],
        "summary": "Report a deal's outcome",
        "description": "Updates lender_status through the same code path an inbound lender email reply uses, so status is consistent regardless of channel. Returns the full, refreshed deal.",
        "parameters": [
          {
            "$ref": "#/components/parameters/DealRef"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "in_review",
                      "offer_made",
                      "declined",
                      "funded"
                    ]
                  },
                  "reason": {
                    "type": "string",
                    "maxLength": 2000,
                    "description": "Free-text reason, encouraged on declined."
                  },
                  "funded_amount": {
                    "type": "number",
                    "description": "On funded, the completed amount."
                  }
                },
                "required": [
                  "status"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Refreshed deal.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DealDetail"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/deals/{ref}/offers": {
      "post": {
        "operationId": "submitOffer",
        "tags": [
          "Lender: Deals"
        ],
        "summary": "Submit or update your offer on a deal",
        "parameters": [
          {
            "$ref": "#/components/parameters/DealRef"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount": {
                    "type": "number",
                    "description": "Offered amount in the deal currency."
                  },
                  "currency": {
                    "type": "string",
                    "description": "Defaults to the deal currency."
                  },
                  "rate_type": {
                    "type": "string",
                    "enum": [
                      "apr",
                      "factor",
                      "monthly"
                    ]
                  },
                  "rate_value": {
                    "type": "number"
                  },
                  "term_months": {
                    "type": "integer"
                  },
                  "fees": {
                    "type": "number"
                  },
                  "maturity": {
                    "type": "string",
                    "enum": [
                      "indicative",
                      "firm"
                    ],
                    "default": "indicative"
                  },
                  "expires_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "notes": {
                    "type": "string"
                  }
                },
                "required": [
                  "amount"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Offer recorded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "offer_id": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "offer_id"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/deals/{ref}/messages": {
      "get": {
        "operationId": "listDealMessages",
        "tags": [
          "Lender: Messages"
        ],
        "summary": "List the client conversation on a deal",
        "parameters": [
          {
            "$ref": "#/components/parameters/DealRef"
          }
        ],
        "responses": {
          "200": {
            "description": "Messages, oldest first, up to 200.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "messages": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Message"
                      }
                    }
                  },
                  "required": [
                    "messages"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "sendDealMessage",
        "tags": [
          "Lender: Messages"
        ],
        "summary": "Send a message to the client on a deal",
        "description": "The client is notified by email; replies land back on the same thread.",
        "parameters": [
          {
            "$ref": "#/components/parameters/DealRef"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "body": {
                    "type": "string",
                    "maxLength": 8000,
                    "description": "Required unless request_upload is true, in which case a default upload-request message is used."
                  },
                  "request_upload": {
                    "type": "boolean",
                    "description": "Attach a secure document-upload link to the notification."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Message stored.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "notified": {
                      "type": "boolean"
                    },
                    "status_intercepted": {
                      "type": "boolean",
                      "description": "True if the message text was interpreted as a status update instead of (or in addition to) being sent as a message."
                    }
                  },
                  "required": [
                    "id",
                    "notified",
                    "status_intercepted"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/deals/{ref}/requests": {
      "get": {
        "operationId": "listDocumentRequests",
        "tags": [
          "Lender: Documents"
        ],
        "summary": "List document requests on a deal",
        "parameters": [
          {
            "$ref": "#/components/parameters/DealRef"
          }
        ],
        "responses": {
          "200": {
            "description": "Document requests, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "requests": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DocumentRequest"
                      }
                    }
                  },
                  "required": [
                    "requests"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createDocumentRequest",
        "tags": [
          "Lender: Documents"
        ],
        "summary": "Request a typed document from the client",
        "description": "Notifies the client through the same mechanism a message with request_upload uses, deep-linked to this item. Capped at 20 open (not forwarded or waived) requests per deal.",
        "parameters": [
          {
            "$ref": "#/components/parameters/DealRef"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "item_type": {
                    "type": "string",
                    "enum": [
                      "bank_statements_6m",
                      "management_accounts",
                      "debt_schedule",
                      "aged_debtors",
                      "filed_accounts",
                      "proof_of_id",
                      "other"
                    ]
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 2000,
                    "description": "Free text shown to the client alongside the item."
                  },
                  "label": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Overrides the default display label."
                  }
                },
                "required": [
                  "item_type"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Request created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request": {
                      "$ref": "#/components/schemas/DocumentRequest"
                    }
                  },
                  "required": [
                    "request"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/deals/{ref}/requests/{id}/files": {
      "get": {
        "operationId": "getDocumentRequestFiles",
        "tags": [
          "Lender: Documents"
        ],
        "summary": "Get signed download URLs for a document request's files",
        "description": "Signed URLs use the same HMAC mechanism as the links in the relay email and expire 7 days after this call. Returns an empty files array if nothing has been uploaded yet.",
        "parameters": [
          {
            "$ref": "#/components/parameters/DealRef"
          },
          {
            "$ref": "#/components/parameters/DocumentRequestId"
          }
        ],
        "responses": {
          "200": {
            "description": "Files uploaded against this document request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "files": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DocumentRequestFile"
                      }
                    }
                  },
                  "required": [
                    "files"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "operationId": "listLenderWebhooks",
        "tags": [
          "Lender: Webhooks"
        ],
        "summary": "List your registered webhook endpoints",
        "responses": {
          "200": {
            "description": "Endpoints, secrets never included.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "webhooks": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookPublic"
                      }
                    }
                  },
                  "required": [
                    "webhooks"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createLenderWebhook",
        "tags": [
          "Lender: Webhooks"
        ],
        "summary": "Register a webhook endpoint",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Must be an https:// URL."
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "deal.created",
                        "deal.updated",
                        "message.created",
                        "request.fulfilled"
                      ]
                    },
                    "description": "Defaults to all events."
                  }
                },
                "required": [
                  "url"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Endpoint created; secret shown once.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookCreated"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/webhooks/{id}": {
      "delete": {
        "operationId": "deleteLenderWebhook",
        "tags": [
          "Lender: Webhooks"
        ],
        "summary": "Remove a webhook endpoint",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "ok"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/test/deals": {
      "post": {
        "operationId": "createTestDeal",
        "tags": [
          "Lender: Sandbox"
        ],
        "summary": "Create a synthetic deal on your own lane",
        "description": "No request body. Business name is prefixed 'TEST -'; contact email is on the non-resolving internal.invalid domain. Capped at 10 live test deals per lender.",
        "responses": {
          "201": {
            "description": "Test deal created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DealDetail"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/CapExceeded"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/test/deals/{ref}": {
      "delete": {
        "operationId": "deleteTestDeal",
        "tags": [
          "Lender: Sandbox"
        ],
        "summary": "Delete a test deal",
        "description": "Only ever deletes rows recognised as synthetic by their internal.invalid contact email; a real deal's ref always 404s here.",
        "parameters": [
          {
            "$ref": "#/components/parameters/DealRef"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "ref": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "ok",
                    "ref",
                    "deleted"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/partner/v1/ping": {
      "get": {
        "operationId": "partnerPing",
        "tags": [
          "Partner: Meta"
        ],
        "summary": "Verify your Partner API key",
        "servers": [
          {
            "url": "https://api.capvant.com/partner/v1"
          }
        ],
        "responses": {
          "200": {
            "description": "Key is valid.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "partner": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "ok",
                    "partner"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/partner/v1/referrals": {
      "servers": [
        {
          "url": "https://api.capvant.com/partner/v1"
        }
      ],
      "get": {
        "operationId": "listReferrals",
        "tags": [
          "Partner: Referrals"
        ],
        "summary": "List your referrals",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by pipeline status, e.g. partial, submitted, in_review, funded, declined."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of referrals.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "referrals": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ReferralListItem"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "referrals",
                    "next_cursor"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "submitReferral",
        "tags": [
          "Partner: Referrals"
        ],
        "summary": "Submit a referral",
        "description": "Creates a lead attributed to your partner account. Enters the standard pre-submission pipeline; never triggers a lender notification by itself.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Replays the original referral instead of creating a duplicate on retry."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReferralCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Referral created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReferralCreated"
                }
              }
            }
          },
          "200": {
            "description": "Existing referral reused (idempotent replay or recent duplicate).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReferralCreated"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/InvalidRequestUnprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/partner/v1/referrals/{id}": {
      "servers": [
        {
          "url": "https://api.capvant.com/partner/v1"
        }
      ],
      "get": {
        "operationId": "getReferral",
        "tags": [
          "Partner: Referrals"
        ],
        "summary": "Retrieve a referral",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The referral, with commission and status history.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReferralDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/partner/v1/webhooks": {
      "servers": [
        {
          "url": "https://api.capvant.com/partner/v1"
        }
      ],
      "get": {
        "operationId": "listPartnerWebhooks",
        "tags": [
          "Partner: Webhooks"
        ],
        "summary": "List your registered webhook endpoints",
        "responses": {
          "200": {
            "description": "Endpoints, secrets never included.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "webhooks": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookPublic"
                      }
                    }
                  },
                  "required": [
                    "webhooks"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createPartnerWebhook",
        "tags": [
          "Partner: Webhooks"
        ],
        "summary": "Register a webhook endpoint",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Must be an https:// URL."
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "referral.updated",
                        "referral.funded",
                        "commission.payable"
                      ]
                    },
                    "description": "Defaults to all three events."
                  }
                },
                "required": [
                  "url"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Endpoint created; secret shown once.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookCreated"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/partner/v1/webhooks/{id}": {
      "servers": [
        {
          "url": "https://api.capvant.com/partner/v1"
        }
      ],
      "delete": {
        "operationId": "deletePartnerWebhook",
        "tags": [
          "Partner: Webhooks"
        ],
        "summary": "Remove a webhook endpoint",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "ok"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Lender keys start with cv_live_; Partner keys start with cv_pk_. Shown once at creation, sent on every request."
      }
    },
    "parameters": {
      "DealRef": {
        "name": "ref",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "The deal reference, e.g. CV93A41205. Case-insensitive."
      },
      "DocumentRequestId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "The document request ID, from GET /deals/{ref}/requests."
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing, invalid, or revoked API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "code": "unauthorized",
                "message": "A valid X-API-Key header is required."
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Over 120 requests in the current one-minute window for this key.",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds until the window resets."
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "code": "rate_limited",
                "message": "Too many requests. Slow down and retry shortly."
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "The reference/id does not exist, or belongs to another organisation.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "code": "not_found",
                "message": "Deal not found."
              }
            }
          }
        }
      },
      "InvalidRequest": {
        "description": "Malformed body or parameters.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "code": "invalid_request",
                "message": "Invalid JSON body."
              }
            }
          }
        }
      },
      "InvalidRequestUnprocessable": {
        "description": "The referral body failed field-level validation (used for 422 on referral submission).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "code": "invalid_request",
                "message": "A valid contact.email is required."
              }
            }
          }
        }
      },
      "CapExceeded": {
        "description": "A per-account limit was hit (currently only the 10-live-test-deal cap).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "code": "cap_exceeded",
                "message": "You already have 10 live test deals (limit 10). Delete some with DELETE /test/deals/{ref} before creating more."
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "Something failed on our side. Safe to retry with backoff.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "code": "internal_error",
                "message": "Something went wrong."
              }
            }
          }
        }
      }
    },
    "schemas": {
      "ErrorEnvelope": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "unauthorized",
                  "rate_limited",
                  "not_found",
                  "invalid_request",
                  "cap_exceeded",
                  "internal_error"
                ]
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "DealSummary": {
        "type": "object",
        "properties": {
          "ref": {
            "type": "string"
          },
          "business": {
            "type": "object",
            "properties": {
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "company_number": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "contact": {
            "type": "object",
            "properties": {
              "first_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "last_name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "currency": {
            "type": [
              "string",
              "null"
            ]
          },
          "product": {
            "type": [
              "string",
              "null"
            ]
          },
          "market": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "lender_status": {
            "type": [
              "string",
              "null"
            ]
          },
          "statements_available": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "ref",
          "business",
          "contact",
          "statements_available",
          "created_at",
          "updated_at"
        ]
      },
      "DealOffer": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "currency": {
            "type": [
              "string",
              "null"
            ]
          },
          "kind": {
            "type": "string"
          },
          "maturity": {
            "type": "string",
            "enum": [
              "indicative",
              "firm",
              "provisional"
            ]
          },
          "status": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "kind",
          "maturity",
          "status",
          "created_at"
        ]
      },
      "DealDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/DealSummary"
          },
          {
            "type": "object",
            "properties": {
              "contact_email": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "contact_phone": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "purpose": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "monthly_revenue": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "annual_turnover": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "offers": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/DealOffer"
                }
              },
              "messages_count": {
                "type": "integer"
              },
              "documents": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "label"
                  ]
                }
              }
            },
            "required": [
              "offers",
              "messages_count",
              "documents"
            ]
          }
        ]
      },
      "Message": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "lender_to_borrower",
              "borrower_to_lender"
            ]
          },
          "body": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "direction",
          "body",
          "created_at"
        ]
      },
      "WebhookPublic": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "active": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_success_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_failure_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "failure_count": {
            "type": "integer"
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "active",
          "created_at",
          "failure_count"
        ]
      },
      "WebhookCreated": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookPublic"
          },
          {
            "type": "object",
            "properties": {
              "secret": {
                "type": "string",
                "description": "Shown only in this response. Used to compute X-Capvant-Signature."
              }
            },
            "required": [
              "secret"
            ]
          }
        ]
      },
      "ReferralConsent": {
        "type": "object",
        "properties": {
          "obtained": {
            "type": "boolean",
            "const": true
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "obtained",
          "timestamp"
        ]
      },
      "ReferralCreate": {
        "type": "object",
        "properties": {
          "business": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "maxLength": 200
              },
              "company_number": {
                "type": "string",
                "maxLength": 50
              }
            },
            "required": [
              "name"
            ]
          },
          "contact": {
            "type": "object",
            "properties": {
              "first_name": {
                "type": "string",
                "maxLength": 100
              },
              "last_name": {
                "type": "string",
                "maxLength": 100
              },
              "email": {
                "type": "string",
                "format": "email"
              },
              "phone": {
                "type": "string",
                "maxLength": 50
              }
            },
            "required": [
              "first_name",
              "last_name",
              "email"
            ]
          },
          "amount": {
            "type": "number",
            "exclusiveMinimum": 0
          },
          "currency": {
            "type": "string",
            "description": "Defaults to the market currency (GBP for UK, USD for US)."
          },
          "product": {
            "type": "string",
            "maxLength": 100
          },
          "country": {
            "type": "string",
            "enum": [
              "UK",
              "US"
            ]
          },
          "consent": {
            "$ref": "#/components/schemas/ReferralConsent"
          }
        },
        "required": [
          "business",
          "contact",
          "amount",
          "country",
          "consent"
        ]
      },
      "ReferralCreated": {
        "type": "object",
        "properties": {
          "ref": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "received"
            ]
          }
        },
        "required": [
          "ref",
          "id",
          "status"
        ]
      },
      "CommissionSummary": {
        "type": [
          "object",
          "null"
        ],
        "properties": {
          "state": {
            "type": "string"
          },
          "amount": {
            "type": "number"
          },
          "currency": {
            "type": "string"
          }
        }
      },
      "ReferralListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "ref": {
            "type": "string"
          },
          "business_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "contact_email": {
            "type": "string",
            "description": "Masked in list responses, e.g. j****@domain.com."
          },
          "amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "currency": {
            "type": [
              "string",
              "null"
            ]
          },
          "country": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string"
          },
          "commission": {
            "$ref": "#/components/schemas/CommissionSummary"
          }
        },
        "required": [
          "id",
          "ref",
          "contact_email",
          "status"
        ]
      },
      "ReferralDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ReferralListItem"
          },
          {
            "type": "object",
            "properties": {
              "contact_first_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "contact_last_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "contact_phone": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "product": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "commission_history": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "number"
                    },
                    "currency": {
                      "type": "string"
                    },
                    "calculated_at": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "approved_at": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "paid_at": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    }
                  }
                }
              },
              "status_history": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "old_status": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "new_status": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            },
            "note": "contact_email is unmasked on this detail endpoint, unlike the list."
          }
        ]
      },
      "WebhookEventEnvelope": {
        "type": "object",
        "description": "The body of every webhook delivery, signed via X-Capvant-Signature (HMAC-SHA256 of the raw body).",
        "properties": {
          "event": {
            "type": "string",
            "enum": [
              "deal.created",
              "deal.updated",
              "message.created",
              "request.fulfilled",
              "referral.updated",
              "referral.funded",
              "commission.payable"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "data": {
            "type": "object",
            "description": "Shape depends on event: deal.* carries a DealSummary, message.created carries a Message plus the deal ref, request.fulfilled carries { deal_ref, request_id, item_type, label, file_count, uploaded_at }."
          }
        },
        "required": [
          "event",
          "created_at",
          "data"
        ]
      },
      "DocumentRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "item_type": {
            "type": "string",
            "enum": [
              "bank_statements_6m",
              "management_accounts",
              "debt_schedule",
              "aged_debtors",
              "filed_accounts",
              "proof_of_id",
              "other"
            ]
          },
          "label": {
            "type": "string"
          },
          "note": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "requested",
              "uploaded",
              "forwarded",
              "waived"
            ]
          },
          "requested_via": {
            "type": "string",
            "enum": [
              "hub",
              "api",
              "adapter",
              "system"
            ]
          },
          "requested_at": {
            "type": "string",
            "format": "date-time"
          },
          "uploaded_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "forwarded_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "file_count": {
            "type": "integer"
          },
          "has_files": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "item_type",
          "label",
          "status",
          "requested_via",
          "requested_at",
          "file_count",
          "has_files"
        ]
      },
      "DocumentRequestFile": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Index of this file within the request, stable for the life of the request."
          },
          "filename": {
            "type": "string"
          },
          "content_type": {
            "type": "string"
          },
          "size_bytes": {
            "type": "integer",
            "nullable": true,
            "description": "Null if the file's size could not be read."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Signed, expiring download URL. Valid for 7 days from when this endpoint was called."
          }
        },
        "required": [
          "id",
          "filename",
          "content_type",
          "size_bytes",
          "url"
        ]
      }
    }
  }
}
