{
  "openapi": "3.1.0",
  "info": {
    "title": "WarpLink API",
    "version": "1.0.0",
    "description": "Deep linking API for developers and small teams."
  },
  "servers": [
    { "url": "https://api.warplink.app/v1", "description": "Production" },
    { "url": "http://localhost:3000/api/v1", "description": "Development" }
  ],
  "security": [{ "bearerAuth": [] }],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key in format `wl_live_xxx` (production) or `wl_test_xxx` (test)."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": { "type": "string", "example": "NOT_FOUND" },
              "message": { "type": "string", "example": "Link not found" },
              "details": {
                "type": "object",
                "properties": {
                  "fields": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "field": { "type": "string" },
                        "message": { "type": "string" }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "Pagination": {
        "type": "object",
        "properties": {
          "total": { "type": "integer" },
          "limit": { "type": "integer" },
          "offset": { "type": "integer" },
          "has_more": { "type": "boolean" }
        }
      },
      "Link": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "short_url": { "type": "string", "example": "https://aplnk.to/abc123" },
          "slug": { "type": "string", "example": "abc123" },
          "domain": { "type": "string", "example": "aplnk.to" },
          "destination_url": { "type": "string", "format": "uri" },
          "ios_url": { "type": ["string", "null"], "format": "uri" },
          "ios_fallback_url": { "type": ["string", "null"], "format": "uri" },
          "android_url": { "type": ["string", "null"], "format": "uri" },
          "android_fallback_url": { "type": ["string", "null"], "format": "uri" },
          "og_title": { "type": ["string", "null"] },
          "og_description": { "type": ["string", "null"] },
          "og_image_url": { "type": ["string", "null"], "format": "uri" },
          "app_id": { "type": ["string", "null"], "format": "uuid" },
          "expires_at": { "type": ["string", "null"], "format": "date-time" },
          "is_active": { "type": "boolean" },
          "tags": { "type": "array", "items": { "type": "string" } },
          "parameters": { "$ref": "#/components/schemas/LinkParamConfig" },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "LinkParamConfig": {
        "type": ["object", "null"],
        "description": "Per-link query-parameter rules. `injected` params are appended to the destination URL; `forwarding` controls which incoming params pass through. Org-level defaults are inherited and merged with link-level config (link wins on key conflict). Precedence: link > org. Send `null` (or omit) to clear/inherit the org defaults.",
        "required": ["injected", "inheritOrgInjected", "suppressedOrgKeys"],
        "properties": {
          "injected": {
            "type": "array",
            "description": "Params appended to the destination URL.",
            "items": {
              "type": "object",
              "required": ["key", "value", "mode"],
              "properties": {
                "key": { "type": "string", "maxLength": 64 },
                "value": { "type": "string", "maxLength": 512 },
                "mode": { "type": ["string", "null"], "enum": ["always", "default", null], "description": "`always` overrides an incoming param; `default` only fills when absent; `null` inherits `defaultMode`." }
              }
            }
          },
          "forwarding": {
            "type": ["object", "null"],
            "description": "Incoming-param forwarding. `null` inherits the org default.",
            "required": ["enabled", "allowlist"],
            "properties": {
              "enabled": { "type": "boolean" },
              "allowlist": { "type": ["array", "null"], "items": { "type": "string" }, "description": "When enabled, only these incoming params forward. `null` forwards all." }
            }
          },
          "defaultMode": { "type": ["string", "null"], "enum": ["always", "default", null], "description": "Fallback mode for injected params whose `mode` is null. `null` inherits the org default." },
          "inheritOrgInjected": { "type": "boolean", "description": "Whether to inherit org-level injected params." },
          "suppressedOrgKeys": { "type": "array", "items": { "type": "string" }, "description": "Org injected-param keys to suppress on this link." }
        }
      },
      "App": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "org_id": { "type": "string", "format": "uuid" },
          "name": { "type": "string" },
          "ios_bundle_id": { "type": ["string", "null"] },
          "ios_team_id": { "type": ["string", "null"] },
          "ios_app_store_id": { "type": ["string", "null"] },
          "ios_app_store_url": { "type": ["string", "null"], "format": "uri" },
          "ios_universal_link_paths": { "type": ["array", "null"], "items": { "type": "string" } },
          "android_package_name": { "type": ["string", "null"] },
          "android_sha256_fingerprints": { "type": ["array", "null"], "items": { "type": "string" } },
          "android_play_store_url": { "type": ["string", "null"], "format": "uri" },
          "android_app_links_paths": { "type": ["array", "null"], "items": { "type": "string" } },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "ApiKey": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "key_prefix": { "type": "string", "example": "wl_live_" },
          "name": { "type": "string" },
          "scopes": { "type": "array", "items": { "type": "string" } },
          "last_used_at": { "type": ["string", "null"], "format": "date-time" },
          "expires_at": { "type": ["string", "null"], "format": "date-time" },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "Invitation": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "org_id": { "type": "string", "format": "uuid" },
          "email": { "type": "string", "format": "email" },
          "role": { "type": "string", "enum": ["admin", "member"] },
          "invited_by": { "type": ["string", "null"] },
          "token": { "type": "string" },
          "expires_at": { "type": "string", "format": "date-time" },
          "accepted_at": { "type": ["string", "null"], "format": "date-time" },
          "revoked_at": { "type": ["string", "null"], "format": "date-time" },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "InvitationListItem": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "org_id": { "type": "string", "format": "uuid" },
          "email": { "type": "string", "format": "email" },
          "role": { "type": "string", "enum": ["admin", "member"] },
          "invited_by": { "type": ["string", "null"] },
          "expires_at": { "type": "string", "format": "date-time" },
          "accepted_at": { "type": ["string", "null"], "format": "date-time" },
          "revoked_at": { "type": ["string", "null"], "format": "date-time" },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "Domain": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "org_id": { "type": "string", "format": "uuid" },
          "domain": { "type": "string", "example": "links.myapp.com" },
          "verified": { "type": "boolean" },
          "ssl_status": { "type": "string" },
          "verification_token": { "type": "string" },
          "verified_at": { "type": ["string", "null"], "format": "date-time" },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "Organization": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "name": { "type": "string" },
          "slug": { "type": "string" },
          "plan": { "type": "string", "enum": ["free", "starter", "growth", "scale"] },
          "monthly_click_limit": { "type": "integer" },
          "billing_period_start": { "type": "string", "format": "date-time" },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      }
    },
    "parameters": {
      "limitParam": { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "minimum": 1, "maximum": 100 } },
      "offsetParam": { "name": "offset", "in": "query", "schema": { "type": "integer", "default": 0, "minimum": 0 } }
    }
  },
  "paths": {
    "/links": {
      "post": {
        "operationId": "createLink",
        "summary": "Create a link",
        "tags": ["Links"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["destination_url"],
                "properties": {
                  "destination_url": { "type": "string", "format": "uri" },
                  "slug": { "type": "string", "minLength": 2, "maxLength": 100, "description": "Custom slug. Auto-generated if omitted." },
                  "ios_url": { "type": "string", "format": "uri" },
                  "ios_fallback_url": { "type": "string", "format": "uri" },
                  "android_url": { "type": "string", "format": "uri" },
                  "android_fallback_url": { "type": "string", "format": "uri" },
                  "og_title": { "type": "string", "maxLength": 255 },
                  "og_description": { "type": "string" },
                  "og_image_url": { "type": "string", "format": "uri" },
                  "tags": { "type": "array", "items": { "type": "string", "maxLength": 50 }, "maxItems": 20 },
                  "expires_at": { "type": "string", "format": "date-time", "description": "Must be in the future." },
                  "password": { "type": "string" },
                  "app_id": { "type": "string", "format": "uuid" },
                  "parameters": { "$ref": "#/components/schemas/LinkParamConfig" }
                }
              }
            }
          }
        },
        "responses": {
          "201": { "description": "Link created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Link" } } } },
          "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "409": { "description": "Slug already taken", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "429": { "description": "Rate limit exceeded", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "get": {
        "operationId": "listLinks",
        "summary": "List links",
        "tags": ["Links"],
        "parameters": [
          { "$ref": "#/components/parameters/limitParam" },
          { "$ref": "#/components/parameters/offsetParam" },
          { "name": "tag", "in": "query", "schema": { "type": "string" } },
          { "name": "is_active", "in": "query", "schema": { "type": "string", "enum": ["true", "false"] } },
          { "name": "search", "in": "query", "schema": { "type": "string", "maxLength": 200 } }
        ],
        "responses": {
          "200": {
            "description": "List of links",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/Link" } },
                    "pagination": { "$ref": "#/components/schemas/Pagination" }
                  }
                }
              }
            }
          },
          "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/links/{id}": {
      "get": {
        "operationId": "getLink",
        "summary": "Get a link",
        "tags": ["Links"],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": {
          "200": { "description": "Link details", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Link" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "patch": {
        "operationId": "updateLink",
        "summary": "Update a link",
        "tags": ["Links"],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "destination_url": { "type": "string", "format": "uri" },
                  "ios_url": { "type": ["string", "null"], "format": "uri" },
                  "ios_fallback_url": { "type": ["string", "null"], "format": "uri" },
                  "android_url": { "type": ["string", "null"], "format": "uri" },
                  "android_fallback_url": { "type": ["string", "null"], "format": "uri" },
                  "og_title": { "type": ["string", "null"], "maxLength": 255 },
                  "og_description": { "type": ["string", "null"] },
                  "og_image_url": { "type": ["string", "null"], "format": "uri" },
                  "tags": { "type": ["array", "null"], "items": { "type": "string", "maxLength": 50 }, "maxItems": 20 },
                  "expires_at": { "type": ["string", "null"], "format": "date-time" },
                  "password": { "type": ["string", "null"] },
                  "app_id": { "type": ["string", "null"], "format": "uuid" },
                  "parameters": { "$ref": "#/components/schemas/LinkParamConfig" }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Updated link", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Link" } } } },
          "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "delete": {
        "operationId": "deleteLink",
        "summary": "Delete a link",
        "description": "Permanently deletes the link. This is not reversible: it also removes the link's click history and frees the slug for reuse. To pause a link instead while keeping its data, send a PATCH with `is_active` set to `false`.",
        "tags": ["Links"],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": {
          "200": { "description": "Deleted link", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Link" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/apps": {
      "post": {
        "operationId": "createApp",
        "summary": "Create an app",
        "tags": ["Apps"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["name"],
                "properties": {
                  "name": { "type": "string", "minLength": 1, "maxLength": 255 },
                  "ios_bundle_id": { "type": "string", "description": "Reverse-domain notation, e.g. com.example.myapp" },
                  "ios_team_id": { "type": "string", "description": "Apple Team ID, e.g. ABCDE12345" },
                  "ios_app_store_id": { "type": "string", "description": "Numeric App Store ID" },
                  "ios_app_store_url": { "type": "string", "format": "uri" },
                  "ios_universal_link_paths": { "type": "array", "items": { "type": "string" } },
                  "android_package_name": { "type": "string", "description": "Java package name, e.g. com.example.myapp" },
                  "android_sha256_fingerprints": { "type": "array", "items": { "type": "string" } },
                  "android_play_store_url": { "type": "string", "format": "uri" },
                  "android_app_links_paths": { "type": "array", "items": { "type": "string" } }
                }
              }
            }
          }
        },
        "responses": {
          "201": { "description": "App created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/App" } } } },
          "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "409": { "description": "Duplicate bundle ID or package name", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "get": {
        "operationId": "listApps",
        "summary": "List apps",
        "tags": ["Apps"],
        "parameters": [
          { "$ref": "#/components/parameters/limitParam" },
          { "$ref": "#/components/parameters/offsetParam" },
          { "name": "search", "in": "query", "schema": { "type": "string", "maxLength": 200 } }
        ],
        "responses": {
          "200": {
            "description": "List of apps",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/App" } },
                    "pagination": { "$ref": "#/components/schemas/Pagination" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/apps/{id}": {
      "get": {
        "operationId": "getApp",
        "summary": "Get an app",
        "tags": ["Apps"],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": {
          "200": { "description": "App details", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/App" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "patch": {
        "operationId": "updateApp",
        "summary": "Update an app",
        "tags": ["Apps"],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": { "type": "string", "minLength": 1, "maxLength": 255 },
                  "ios_bundle_id": { "type": ["string", "null"] },
                  "ios_team_id": { "type": ["string", "null"] },
                  "ios_app_store_id": { "type": ["string", "null"] },
                  "ios_app_store_url": { "type": ["string", "null"], "format": "uri" },
                  "ios_universal_link_paths": { "type": ["array", "null"], "items": { "type": "string" } },
                  "android_package_name": { "type": ["string", "null"] },
                  "android_sha256_fingerprints": { "type": ["array", "null"], "items": { "type": "string" } },
                  "android_play_store_url": { "type": ["string", "null"], "format": "uri" },
                  "android_app_links_paths": { "type": ["array", "null"], "items": { "type": "string" } }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Updated app", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/App" } } } },
          "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "409": { "description": "Duplicate", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "delete": {
        "operationId": "deleteApp",
        "summary": "Delete an app",
        "tags": ["Apps"],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": {
          "200": { "description": "Deleted app", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/App" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/keys": {
      "post": {
        "operationId": "createApiKey",
        "summary": "Create an API key",
        "tags": ["API Keys"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["name", "scopes"],
                "properties": {
                  "name": { "type": "string", "minLength": 1, "maxLength": 100 },
                  "scopes": {
                    "type": "array",
                    "minItems": 1,
                    "items": { "type": "string", "enum": ["links:read", "links:write", "apps:read", "apps:write", "analytics:read"] }
                  },
                  "expires_at": { "type": "string", "format": "date-time", "description": "Must be in the future." }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "API key created. The `raw_key` field is only returned once.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/ApiKey" },
                    { "type": "object", "properties": { "raw_key": { "type": "string", "example": "wl_live_abc123def456" } } }
                  ]
                }
              }
            }
          },
          "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "get": {
        "operationId": "listApiKeys",
        "summary": "List API keys",
        "tags": ["API Keys"],
        "responses": {
          "200": {
            "description": "List of API keys",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/ApiKey" } }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/keys/{id}": {
      "get": {
        "operationId": "getApiKey",
        "summary": "Get an API key",
        "tags": ["API Keys"],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": {
          "200": { "description": "API key details", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiKey" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "delete": {
        "operationId": "deleteApiKey",
        "summary": "Delete an API key",
        "tags": ["API Keys"],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": {
          "204": { "description": "Deleted" },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/attribution/match": {
      "post": {
        "operationId": "attributionMatch",
        "summary": "Match an app install to a link click",
        "tags": ["Attribution"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["platform", "fingerprint_version", "sdk_version"],
                "properties": {
                  "fingerprint": { "type": "string", "pattern": "^[a-f0-9]{64}$", "description": "SHA-256 fingerprint hex string." },
                  "platform": { "type": "string", "enum": ["ios", "android"] },
                  "fingerprint_version": { "type": "string", "enum": ["basic", "enriched"] },
                  "sdk_version": { "type": "string" },
                  "device_id": { "type": "string", "format": "uuid", "description": "IDFV (iOS) or equivalent device identifier." },
                  "referrer": { "type": "string", "description": "Install referrer string (Google Play)." },
                  "accept_language": { "type": "string" },
                  "screen_width": { "type": "integer", "minimum": 0 },
                  "screen_height": { "type": "integer", "minimum": 0 },
                  "timezone_offset": { "type": "integer" },
                  "user_agent": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Attribution result",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["matched"],
                      "properties": {
                        "matched": { "type": "boolean", "const": true },
                        "match_type": { "type": "string", "enum": ["deterministic", "probabilistic"] },
                        "match_confidence": { "type": "number", "minimum": 0, "maximum": 1 },
                        "link_id": { "type": "string", "format": "uuid" },
                        "deep_link_url": { "type": ["string", "null"] },
                        "destination_url": { "type": ["string", "null"] },
                        "custom_params": { "type": "object", "additionalProperties": true },
                        "install_id": { "type": "string", "format": "uuid" },
                        "app_id": { "type": ["string", "null"], "format": "uuid" }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["matched"],
                      "properties": {
                        "matched": { "type": "boolean", "const": false }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/invitations": {
      "post": {
        "operationId": "createInvitation",
        "summary": "Create an invitation",
        "tags": ["Invitations"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["email", "role"],
                "properties": {
                  "email": { "type": "string", "format": "email", "maxLength": 255 },
                  "role": { "type": "string", "enum": ["admin", "member"] }
                }
              }
            }
          }
        },
        "responses": {
          "201": { "description": "Invitation created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Invitation" } } } },
          "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "403": { "description": "Forbidden or seat limit exceeded", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "409": { "description": "Already a member or duplicate invitation", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "get": {
        "operationId": "listInvitations",
        "summary": "List invitations",
        "tags": ["Invitations"],
        "parameters": [
          { "$ref": "#/components/parameters/limitParam" },
          { "$ref": "#/components/parameters/offsetParam" },
          { "name": "status", "in": "query", "schema": { "type": "string", "enum": ["pending", "accepted", "revoked", "expired", "all"], "default": "pending" } }
        ],
        "responses": {
          "200": {
            "description": "List of invitations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/InvitationListItem" } },
                    "pagination": { "$ref": "#/components/schemas/Pagination" }
                  }
                }
              }
            }
          },
          "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "403": { "description": "Forbidden", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/invitations/{id}": {
      "delete": {
        "operationId": "revokeInvitation",
        "summary": "Revoke an invitation",
        "tags": ["Invitations"],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": {
          "200": { "description": "Revoked invitation", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Invitation" } } } },
          "400": { "description": "Invalid ID, already accepted, already revoked, or expired", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "403": { "description": "Forbidden", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/domains": {
      "post": {
        "operationId": "createDomain",
        "summary": "Add a custom domain",
        "tags": ["Domains"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["domain"],
                "properties": {
                  "domain": { "type": "string", "minLength": 4, "maxLength": 255, "example": "links.myapp.com", "description": "Must be a valid domain. IP addresses and reserved domains (aplnk.to, warplink.app) are not allowed." }
                }
              }
            }
          }
        },
        "responses": {
          "201": { "description": "Domain created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Domain" } } } },
          "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "403": { "description": "Forbidden, plan upgrade required, or domain limit exceeded", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "409": { "description": "Domain already registered", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "get": {
        "operationId": "listDomains",
        "summary": "List custom domains",
        "tags": ["Domains"],
        "parameters": [
          { "$ref": "#/components/parameters/limitParam" },
          { "$ref": "#/components/parameters/offsetParam" }
        ],
        "responses": {
          "200": {
            "description": "List of custom domains",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/Domain" } },
                    "pagination": { "$ref": "#/components/schemas/Pagination" }
                  }
                }
              }
            }
          },
          "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "403": { "description": "Forbidden", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/domains/{id}": {
      "get": {
        "operationId": "getDomain",
        "summary": "Get a custom domain",
        "tags": ["Domains"],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": {
          "200": { "description": "Domain details", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Domain" } } } },
          "400": { "description": "Invalid ID", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "403": { "description": "Forbidden", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "delete": {
        "operationId": "deleteDomain",
        "summary": "Delete a custom domain",
        "tags": ["Domains"],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": {
          "200": { "description": "Deleted domain", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Domain" } } } },
          "400": { "description": "Invalid ID", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "403": { "description": "Forbidden", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/domains/{id}/verify": {
      "post": {
        "operationId": "verifyDomain",
        "summary": "Verify a custom domain's DNS configuration",
        "tags": ["Domains"],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": {
          "200": {
            "description": "Verification result",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": ["verified", "domain"],
                      "properties": {
                        "verified": { "type": "boolean", "const": true },
                        "domain": { "$ref": "#/components/schemas/Domain" }
                      }
                    },
                    {
                      "type": "object",
                      "required": ["verified", "domain", "dns"],
                      "properties": {
                        "verified": { "type": "boolean", "const": false },
                        "domain": { "$ref": "#/components/schemas/Domain" },
                        "dns": {
                          "type": "object",
                          "properties": {
                            "expected_cname": { "type": "string", "example": "links.aplnk.to" },
                            "current_cname": { "type": ["string", "null"] },
                            "message": { "type": "string" }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": { "description": "Invalid ID", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "403": { "description": "Forbidden", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/organizations/{id}": {
      "delete": {
        "operationId": "deleteOrganization",
        "summary": "Delete an organization",
        "description": "Permanently deletes the organization and all associated data (links, apps, members, etc.) via database cascade. Requires the `X-Confirmation-Name` header matching the organization name. The API key can only delete its own organization.",
        "tags": ["Organizations"],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } },
          { "name": "X-Confirmation-Name", "in": "header", "required": true, "schema": { "type": "string" }, "description": "Must match the organization name exactly." }
        ],
        "responses": {
          "200": { "description": "Deleted organization", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Organization" } } } },
          "400": { "description": "Invalid ID or missing confirmation header", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "403": { "description": "Forbidden or confirmation name mismatch", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/sdk/validate": {
      "get": {
        "operationId": "validateSdkKey",
        "summary": "Validate an API key",
        "description": "Validates the provided API key and returns the associated organization ID. Used by SDKs to verify configuration.",
        "tags": ["SDK"],
        "responses": {
          "200": {
            "description": "Valid API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["valid", "org_id"],
                  "properties": {
                    "valid": { "type": "boolean", "const": true },
                    "org_id": { "type": "string", "format": "uuid" }
                  }
                }
              }
            }
          },
          "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "403": { "description": "Forbidden", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/links/resolve/{slug}": {
      "get": {
        "operationId": "resolveLink",
        "summary": "Resolve a link by slug",
        "description": "Looks up a link by its slug and optional domain. Returns the link's deep link configuration for SDK use.",
        "tags": ["Links"],
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string", "minLength": 1, "maxLength": 100, "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" } },
          { "name": "domain", "in": "query", "schema": { "type": "string", "minLength": 1, "maxLength": 255, "default": "aplnk.to" }, "description": "Domain to resolve the slug against. Defaults to aplnk.to." }
        ],
        "responses": {
          "200": {
            "description": "Resolved link",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": { "type": "string", "format": "uuid" },
                    "slug": { "type": "string" },
                    "domain": { "type": "string" },
                    "destination_url": { "type": "string", "format": "uri" },
                    "ios_url": { "type": ["string", "null"], "format": "uri" },
                    "ios_fallback_url": { "type": ["string", "null"], "format": "uri" },
                    "android_url": { "type": ["string", "null"], "format": "uri" },
                    "android_fallback_url": { "type": ["string", "null"], "format": "uri" },
                    "custom_params": { "type": "object", "additionalProperties": true },
                    "created_at": { "type": "string", "format": "date-time" }
                  }
                }
              }
            }
          },
          "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "410": { "description": "Link has expired", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    }
  }
}
