{
  "openapi": "3.1.0",
  "info": {
    "title": "LinkSense API",
    "version": "1.0.0",
    "description": "Manage LinkSense projects, dynamic links, iOS apps, and Android apps programmatically. All endpoints require authentication with an API key (Pro plan).",
    "contact": {
      "name": "LinkSense Support",
      "email": "support@linksense.net",
      "url": "https://linksense.net/contact"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://linksense.net/api/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {"name": "Projects", "description": "Top-level containers for dynamic links."},
    {"name": "Dynamic Links", "description": "Smart links that route by device."},
    {"name": "Short Links", "description": "Brand-able aliases for dynamic links (Pro feature)."},
    {"name": "iOS Apps", "description": "iOS app registrations used for Universal Links."},
    {"name": "Android Apps", "description": "Android app registrations used for App Links."}
  ],
  "paths": {
    "/projects": {
      "get": {
        "tags": ["Projects"],
        "summary": "List projects",
        "operationId": "listProjects",
        "parameters": [
          {"name": "page", "in": "query", "schema": {"type": "integer", "minimum": 1, "default": 1}},
          {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 10}},
          {"name": "search", "in": "query", "schema": {"type": "string"}},
          {"name": "sortBy", "in": "query", "schema": {"type": "string", "enum": ["name", "subdomain", "created_at", "updated_at"]}},
          {"name": "sortOrder", "in": "query", "schema": {"type": "string", "enum": ["asc", "desc"]}}
        ],
        "responses": {
          "200": {
            "description": "Paginated project list.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {"$ref": "#/components/schemas/SuccessEnvelope"},
                    {"properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/ProjectWithCounts"}}}}
                  ]
                }
              }
            }
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "429": {"$ref": "#/components/responses/RateLimited"}
        }
      },
      "post": {
        "tags": ["Projects"],
        "summary": "Create a project",
        "operationId": "createProject",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {"$ref": "#/components/schemas/CreateProjectRequest"}
            }
          }
        },
        "responses": {
          "201": {
            "description": "Project created.",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProjectResponse"}}}
          },
          "400": {"$ref": "#/components/responses/InvalidInput"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {"$ref": "#/components/responses/AccessDenied"},
          "409": {"$ref": "#/components/responses/SubdomainTaken"},
          "429": {"$ref": "#/components/responses/RateLimited"}
        }
      }
    },
    "/projects/{projectId}": {
      "parameters": [{"$ref": "#/components/parameters/ProjectId"}],
      "get": {
        "tags": ["Projects"],
        "summary": "Get a project",
        "operationId": "getProject",
        "responses": {
          "200": {"description": "Project.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProjectResponse"}}}},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      },
      "put": {
        "tags": ["Projects"],
        "summary": "Update a project",
        "operationId": "updateProject",
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpdateProjectRequest"}}}
        },
        "responses": {
          "200": {"description": "Updated project.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProjectResponse"}}}},
          "400": {"$ref": "#/components/responses/InvalidInput"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/SubdomainTaken"}
        }
      },
      "delete": {
        "tags": ["Projects"],
        "summary": "Delete a project",
        "operationId": "deleteProject",
        "responses": {
          "200": {"description": "Deleted."},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      }
    },
    "/projects/{projectId}/links": {
      "parameters": [{"$ref": "#/components/parameters/ProjectId"}],
      "get": {
        "tags": ["Dynamic Links"],
        "summary": "List dynamic links in a project",
        "operationId": "listDynamicLinks",
        "parameters": [
          {"name": "page", "in": "query", "schema": {"type": "integer", "minimum": 1, "default": 1}},
          {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 10}}
        ],
        "responses": {
          "200": {"description": "Paginated link list.", "content": {"application/json": {"schema": {"allOf": [{"$ref": "#/components/schemas/SuccessEnvelope"}, {"properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/DynamicLink"}}}}]}}}},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      },
      "post": {
        "tags": ["Dynamic Links"],
        "summary": "Create a dynamic link",
        "operationId": "createDynamicLink",
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateDynamicLinkRequest"}}}
        },
        "responses": {
          "201": {"description": "Dynamic link created.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DynamicLinkResponse"}}}},
          "400": {"$ref": "#/components/responses/InvalidInput"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {"$ref": "#/components/responses/AccessDenied"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/CustomPathExists"}
        }
      }
    },
    "/projects/{projectId}/links/{linkId}": {
      "parameters": [
        {"$ref": "#/components/parameters/ProjectId"},
        {"$ref": "#/components/parameters/LinkId"}
      ],
      "get": {
        "tags": ["Dynamic Links"],
        "summary": "Get a dynamic link",
        "operationId": "getDynamicLink",
        "responses": {
          "200": {"description": "Dynamic link.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DynamicLinkResponse"}}}},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      },
      "put": {
        "tags": ["Dynamic Links"],
        "summary": "Update a dynamic link",
        "operationId": "updateDynamicLink",
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpdateDynamicLinkRequest"}}}
        },
        "responses": {
          "200": {"description": "Updated dynamic link.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DynamicLinkResponse"}}}},
          "400": {"$ref": "#/components/responses/InvalidInput"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      },
      "delete": {
        "tags": ["Dynamic Links"],
        "summary": "Delete a dynamic link",
        "operationId": "deleteDynamicLink",
        "responses": {
          "200": {"description": "Deleted."},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      }
    },
    "/projects/{projectId}/short-links": {
      "parameters": [{"$ref": "#/components/parameters/ProjectId"}],
      "get": {
        "tags": ["Short Links"],
        "summary": "List short links in a project",
        "operationId": "listShortLinks",
        "parameters": [
          {"name": "page", "in": "query", "schema": {"type": "integer", "minimum": 1, "default": 1}},
          {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 10}},
          {"name": "dynamic_link_id", "in": "query", "schema": {"type": "string", "format": "uuid"}, "description": "Filter to short links aliasing a single parent dynamic link."}
        ],
        "responses": {
          "200": {"description": "Paginated short link list.", "content": {"application/json": {"schema": {"allOf": [{"$ref": "#/components/schemas/SuccessEnvelope"}, {"properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/ShortLink"}}}}]}}}},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      },
      "post": {
        "tags": ["Short Links"],
        "summary": "Create a short link",
        "operationId": "createShortLink",
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateShortLinkRequest"}}}
        },
        "responses": {
          "201": {"description": "Short link created.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ShortLinkResponse"}}}},
          "400": {"$ref": "#/components/responses/InvalidInput"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {"$ref": "#/components/responses/ForbiddenPlan"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/SlugExists"}
        }
      }
    },
    "/projects/{projectId}/short-links/{shortLinkId}": {
      "parameters": [
        {"$ref": "#/components/parameters/ProjectId"},
        {"$ref": "#/components/parameters/ShortLinkId"}
      ],
      "get": {
        "tags": ["Short Links"],
        "summary": "Get a short link",
        "operationId": "getShortLink",
        "responses": {
          "200": {"description": "Short link.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ShortLinkResponse"}}}},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      },
      "delete": {
        "tags": ["Short Links"],
        "summary": "Delete a short link",
        "operationId": "deleteShortLink",
        "responses": {
          "200": {"description": "Deleted."},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      }
    },
    "/projects/{projectId}/ios-apps": {
      "parameters": [{"$ref": "#/components/parameters/ProjectId"}],
      "get": {
        "tags": ["iOS Apps"],
        "summary": "List iOS apps registered to a project",
        "operationId": "listIosApps",
        "responses": {
          "200": {"description": "Paginated iOS app list.", "content": {"application/json": {"schema": {"allOf": [{"$ref": "#/components/schemas/SuccessEnvelope"}, {"properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/IosApp"}}}}]}}}},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      },
      "post": {
        "tags": ["iOS Apps"],
        "summary": "Register an iOS app",
        "operationId": "createIosApp",
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateIosAppRequest"}}}},
        "responses": {
          "201": {"description": "iOS app created.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/IosAppResponse"}}}},
          "400": {"$ref": "#/components/responses/InvalidInput"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/BundleIdExists"}
        }
      }
    },
    "/projects/{projectId}/ios-apps/{appId}": {
      "parameters": [
        {"$ref": "#/components/parameters/ProjectId"},
        {"$ref": "#/components/parameters/AppId"}
      ],
      "get": {
        "tags": ["iOS Apps"],
        "summary": "Get an iOS app",
        "operationId": "getIosApp",
        "responses": {
          "200": {"description": "iOS app.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/IosAppResponse"}}}},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      },
      "put": {
        "tags": ["iOS Apps"],
        "summary": "Update an iOS app",
        "operationId": "updateIosApp",
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpdateIosAppRequest"}}}},
        "responses": {
          "200": {"description": "Updated iOS app.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/IosAppResponse"}}}},
          "400": {"$ref": "#/components/responses/InvalidInput"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      },
      "delete": {
        "tags": ["iOS Apps"],
        "summary": "Delete an iOS app",
        "operationId": "deleteIosApp",
        "responses": {
          "200": {"description": "Deleted."},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/LinkedReferences"}
        }
      }
    },
    "/projects/{projectId}/android-apps": {
      "parameters": [{"$ref": "#/components/parameters/ProjectId"}],
      "get": {
        "tags": ["Android Apps"],
        "summary": "List Android apps registered to a project",
        "operationId": "listAndroidApps",
        "responses": {
          "200": {"description": "Paginated Android app list.", "content": {"application/json": {"schema": {"allOf": [{"$ref": "#/components/schemas/SuccessEnvelope"}, {"properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/AndroidApp"}}}}]}}}},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      },
      "post": {
        "tags": ["Android Apps"],
        "summary": "Register an Android app",
        "operationId": "createAndroidApp",
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateAndroidAppRequest"}}}},
        "responses": {
          "201": {"description": "Android app created.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AndroidAppResponse"}}}},
          "400": {"$ref": "#/components/responses/InvalidInput"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/PackageNameExists"}
        }
      }
    },
    "/projects/{projectId}/android-apps/{appId}": {
      "parameters": [
        {"$ref": "#/components/parameters/ProjectId"},
        {"$ref": "#/components/parameters/AppId"}
      ],
      "get": {
        "tags": ["Android Apps"],
        "summary": "Get an Android app",
        "operationId": "getAndroidApp",
        "responses": {
          "200": {"description": "Android app.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AndroidAppResponse"}}}},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      },
      "put": {
        "tags": ["Android Apps"],
        "summary": "Update an Android app",
        "operationId": "updateAndroidApp",
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpdateAndroidAppRequest"}}}},
        "responses": {
          "200": {"description": "Updated Android app.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AndroidAppResponse"}}}},
          "400": {"$ref": "#/components/responses/InvalidInput"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      },
      "delete": {
        "tags": ["Android Apps"],
        "summary": "Delete an Android app",
        "operationId": "deleteAndroidApp",
        "responses": {
          "200": {"description": "Deleted."},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/LinkedReferences"}
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "ls_live_*",
        "description": "API key issued from Dashboard → Settings → API Keys. Include as `Authorization: Bearer ls_live_...`."
      }
    },
    "parameters": {
      "ProjectId": {"name": "projectId", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}},
      "LinkId": {"name": "linkId", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}},
      "ShortLinkId": {"name": "shortLinkId", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}},
      "AppId": {"name": "appId", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}
    },
    "schemas": {
      "SuccessEnvelope": {
        "type": "object",
        "required": ["data"],
        "properties": {
          "data": {},
          "pagination": {"$ref": "#/components/schemas/Pagination"}
        }
      },
      "Pagination": {
        "type": "object",
        "properties": {
          "page": {"type": "integer"},
          "limit": {"type": "integer"},
          "total": {"type": "integer"},
          "totalPages": {"type": "integer"},
          "hasNextPage": {"type": "boolean"},
          "hasPreviousPage": {"type": "boolean"}
        }
      },
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "INVALID_INPUT", "UNAUTHORIZED", "ACCESS_DENIED", "NOT_FOUND",
                  "IOS_APP_NOT_FOUND", "ANDROID_APP_NOT_FOUND",
                  "SUBDOMAIN_TAKEN",
                  "CUSTOM_PATH_EXISTS", "BUNDLE_ID_EXISTS", "PACKAGE_NAME_EXISTS",
                  "LINKED_REFERENCES", "RATE_LIMITED", "DATABASE_ERROR",
                  "CREATE_FAILED", "UPDATE_FAILED", "DELETE_FAILED", "UNKNOWN_ERROR"
                ]
              },
              "message": {"type": "string"},
              "details": {}
            }
          }
        }
      },
      "Project": {
        "type": "object",
        "required": ["id", "name", "subdomain", "created_at", "updated_at", "user_id"],
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "name": {"type": "string"},
          "subdomain": {"type": "string"},
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"},
          "user_id": {"type": "string", "format": "uuid"}
        }
      },
      "ProjectWithCounts": {
        "allOf": [
          {"$ref": "#/components/schemas/Project"},
          {
            "type": "object",
            "properties": {
              "_count": {
                "type": "object",
                "properties": {"dynamic_links": {"type": "integer"}}
              }
            }
          }
        ]
      },
      "ProjectResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {"data": {"$ref": "#/components/schemas/Project"}}
      },
      "CreateProjectRequest": {
        "type": "object",
        "required": ["name", "subdomain"],
        "properties": {
          "name": {"type": "string", "maxLength": 100},
          "subdomain": {"type": "string", "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$"}
        }
      },
      "UpdateProjectRequest": {
        "type": "object",
        "properties": {
          "name": {"type": "string", "maxLength": 100},
          "subdomain": {"type": "string", "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$"}
        }
      },
      "DynamicLink": {
        "type": "object",
        "required": ["id", "project_id", "name", "created_at", "updated_at"],
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "project_id": {"type": "string", "format": "uuid"},
          "name": {"type": "string"},
          "custom_path": {"type": "string", "nullable": true},
          "full_url": {"type": "string", "format": "uri"},
          "desktop_url": {"type": "string", "format": "uri", "nullable": true},
          "ios_app_id": {"type": "string", "format": "uuid", "nullable": true},
          "android_app_id": {"type": "string", "format": "uuid", "nullable": true},
          "ios_fallback_url": {"type": "string", "format": "uri", "nullable": true},
          "android_fallback_url": {"type": "string", "format": "uri", "nullable": true},
          "ios_deferred_deep_link": {"type": "boolean"},
          "social_title": {"type": "string", "nullable": true},
          "social_description": {"type": "string", "nullable": true},
          "social_image_url": {"type": "string", "format": "uri", "nullable": true},
          "referrer_params": {"type": "object", "additionalProperties": {"type": "string"}, "nullable": true},
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"}
        }
      },
      "DynamicLinkResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {"data": {"$ref": "#/components/schemas/DynamicLink"}}
      },
      "CreateDynamicLinkRequest": {
        "type": "object",
        "required": ["name"],
        "properties": {
          "name": {"type": "string", "maxLength": 100},
          "custom_path": {"type": "string", "maxLength": 50},
          "desktop_url": {"type": "string", "format": "uri"},
          "ios_app_id": {"type": "string", "format": "uuid"},
          "android_app_id": {"type": "string", "format": "uuid"},
          "ios_fallback_url": {"type": "string", "format": "uri"},
          "android_fallback_url": {"type": "string", "format": "uri"},
          "ios_deferred_deep_link": {"type": "boolean"},
          "social_title": {"type": "string"},
          "social_description": {"type": "string"},
          "social_image_url": {"type": "string", "format": "uri"},
          "referrer_params": {"type": "object", "additionalProperties": {"type": "string"}}
        }
      },
      "UpdateDynamicLinkRequest": {
        "type": "object",
        "properties": {
          "name": {"type": "string", "maxLength": 100},
          "custom_path": {"type": "string", "maxLength": 50},
          "desktop_url": {"type": "string", "format": "uri", "nullable": true},
          "ios_app_id": {"type": "string", "format": "uuid", "nullable": true},
          "android_app_id": {"type": "string", "format": "uuid", "nullable": true},
          "ios_fallback_url": {"type": "string", "format": "uri", "nullable": true},
          "android_fallback_url": {"type": "string", "format": "uri", "nullable": true},
          "ios_deferred_deep_link": {"type": "boolean"},
          "social_title": {"type": "string", "nullable": true},
          "social_description": {"type": "string", "nullable": true},
          "social_image_url": {"type": "string", "format": "uri", "nullable": true},
          "referrer_params": {"type": "object", "additionalProperties": {"type": "string"}, "nullable": true}
        }
      },
      "ShortLink": {
        "type": "object",
        "required": ["id", "project_id", "dynamic_link_id", "slug", "short_url", "source", "created_at", "updated_at"],
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "project_id": {"type": "string", "format": "uuid"},
          "dynamic_link_id": {"type": "string", "format": "uuid", "description": "Parent dynamic link this slug aliases."},
          "slug": {"type": "string", "minLength": 3, "maxLength": 20, "description": "Lowercase, alphanumeric with non-leading/trailing - or _."},
          "short_url": {"type": "string", "format": "uri", "description": "Fully-formed short URL for sharing."},
          "source": {"type": "string", "enum": ["dashboard", "api"], "description": "Surface that created the alias."},
          "created_by": {"type": "string", "format": "uuid", "nullable": true},
          "created_by_api_key_id": {"type": "string", "format": "uuid", "nullable": true, "description": "API key that minted the alias when source = api."},
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"}
        }
      },
      "ShortLinkResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {"data": {"$ref": "#/components/schemas/ShortLink"}}
      },
      "CreateShortLinkRequest": {
        "type": "object",
        "required": ["dynamic_link_id"],
        "properties": {
          "dynamic_link_id": {"type": "string", "format": "uuid", "description": "Parent dynamic link this slug will alias. Must belong to the same project."},
          "slug": {"type": "string", "minLength": 3, "maxLength": 20, "description": "Optional. Auto-generated as a 4-character base36 string when omitted."}
        }
      },
      "IosApp": {
        "type": "object",
        "required": ["id", "project_id", "name", "bundle_id", "team_id", "created_at", "updated_at"],
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "project_id": {"type": "string", "format": "uuid"},
          "name": {"type": "string"},
          "bundle_id": {"type": "string"},
          "team_id": {"type": "string"},
          "appstore_id": {"type": "string", "nullable": true},
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"}
        }
      },
      "IosAppResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {"data": {"$ref": "#/components/schemas/IosApp"}}
      },
      "CreateIosAppRequest": {
        "type": "object",
        "required": ["name", "bundle_id", "team_id"],
        "properties": {
          "name": {"type": "string"},
          "bundle_id": {"type": "string"},
          "team_id": {"type": "string"},
          "appstore_id": {"type": "string"}
        }
      },
      "UpdateIosAppRequest": {
        "type": "object",
        "properties": {
          "name": {"type": "string"},
          "bundle_id": {"type": "string"},
          "team_id": {"type": "string"},
          "appstore_id": {"type": "string"}
        }
      },
      "AndroidApp": {
        "type": "object",
        "required": ["id", "project_id", "name", "package_name", "sha_fingerprints", "created_at", "updated_at"],
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "project_id": {"type": "string", "format": "uuid"},
          "name": {"type": "string"},
          "package_name": {"type": "string"},
          "sha_fingerprints": {"type": "array", "items": {"type": "string"}},
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"}
        }
      },
      "AndroidAppResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {"data": {"$ref": "#/components/schemas/AndroidApp"}}
      },
      "CreateAndroidAppRequest": {
        "type": "object",
        "required": ["name", "package_name", "sha_fingerprints"],
        "properties": {
          "name": {"type": "string"},
          "package_name": {"type": "string"},
          "sha_fingerprints": {"type": "array", "items": {"type": "string"}, "minItems": 1}
        }
      },
      "UpdateAndroidAppRequest": {
        "type": "object",
        "properties": {
          "name": {"type": "string"},
          "package_name": {"type": "string"},
          "sha_fingerprints": {"type": "array", "items": {"type": "string"}}
        }
      }
    },
    "responses": {
      "InvalidInput": {"description": "Request validation failed.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "Unauthorized": {"description": "API key missing, invalid, or revoked.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "AccessDenied": {"description": "Plan does not include API access or plan limit reached.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "NotFound": {"description": "Resource not found.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "SubdomainTaken": {"description": "Subdomain already in use.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "CustomPathExists": {"description": "Link with this custom path already exists in the project.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "SlugExists": {"description": "Slug is already used by another link or short link in this project. Slug namespace is shared with dynamic_links.custom_path.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "ForbiddenPlan": {"description": "Feature requires a higher plan tier (e.g. URL shortening requires Pro).", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "BundleIdExists": {"description": "iOS app with this bundle ID already exists in the project.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "PackageNameExists": {"description": "Android app with this package name already exists in the project.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "LinkedReferences": {"description": "App cannot be deleted because dynamic links still reference it.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "RateLimited": {"description": "Rate limit exceeded (60 requests per minute per API key).", "headers": {"X-RateLimit-Limit": {"schema": {"type": "integer"}}, "X-RateLimit-Remaining": {"schema": {"type": "integer"}}, "X-RateLimit-Reset": {"schema": {"type": "integer"}}}, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}
    }
  }
}
