{
  "openapi": "3.1.0",
  "info": {
    "title": "Autodisc Drops API",
    "version": "1.0.0",
    "description": "Public, accountless API for temporary Autodisc deployments. A Drop is public, expires after 24 hours, and can be claimed into an authenticated account. Creating or claiming a Drop changes external state.",
    "termsOfService": "https://autodisc.xyz/tos",
    "contact": {
      "name": "Autodisc support",
      "url": "https://autodisc.xyz/contact"
    },
    "license": {
      "name": "Autodisc API terms",
      "identifier": "LicenseRef-Autodisc-API-Terms"
    }
  },
  "externalDocs": {
    "description": "Autodisc developer resources",
    "url": "https://autodisc.xyz/developers"
  },
  "servers": [
    {
      "url": "https://api.autodisc.xyz",
      "description": "Autodisc public API"
    }
  ],
  "tags": [
    {
      "name": "Drops",
      "description": "Temporary public deployments"
    }
  ],
  "paths": {
    "/api/v1/drops": {
      "post": {
        "operationId": "createDropFromGitHub",
        "summary": "Create a Drop from a public GitHub repository",
        "description": "Creates a public deployment that expires after 24 hours. Inspect the repository and obtain the user's approval before starting compute.",
        "tags": ["Drops"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDropRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The Drop was accepted for asynchronous deployment.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DropCreateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "description": "The anonymous create quota was exhausted.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/drops/upload": {
      "post": {
        "operationId": "createDropFromUpload",
        "summary": "Create a Drop from a ZIP archive",
        "description": "Uploads a reviewed ZIP whose project files are at the archive root. Exclude credentials, dotenv files, dependency directories, build caches, editor state, local databases, and unrelated files.",
        "tags": ["Drops"],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["source", "request"],
                "properties": {
                  "source": {
                    "type": "string",
                    "format": "binary",
                    "description": "ZIP archive, at most 25 MB."
                  },
                  "request": {
                    "type": "string",
                    "description": "JSON-encoded CreateDropUploadRequest."
                  }
                }
              },
              "encoding": {
                "request": {
                  "contentType": "application/json"
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The uploaded Drop was accepted for asynchronous deployment.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DropCreateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "description": "The anonymous create quota was exhausted.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/drops/{drop_id}": {
      "get": {
        "operationId": "getDrop",
        "summary": "Read Drop deployment status",
        "description": "Poll until status is ready or failed. Keep the control token private and never commit it.",
        "tags": ["Drops"],
        "security": [
          {
            "dropControlToken": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DropId"
          }
        ],
        "responses": {
          "200": {
            "description": "Current Drop state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DropStatusResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/drops/{drop_id}/claim": {
      "post": {
        "operationId": "claimDrop",
        "summary": "Claim a Drop into an authenticated account",
        "description": "Transfers the temporary deployment into the caller's account. This operation requires an authenticated Autodisc bearer token and the private claim token returned at creation.",
        "tags": ["Drops"],
        "security": [
          {
            "autodiscBearerToken": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DropId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClaimDropRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The Drop was claimed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClaimDropResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "dropControlToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "dropctl_live_…",
        "description": "Private capability returned by Drop creation."
      },
      "autodiscBearerToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "Authenticated Autodisc user session token."
      }
    },
    "parameters": {
      "DropId": {
        "name": "drop_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "headers": {
      "RateLimit": {
        "description": "Current quota state using the IETF RateLimit structured field, for example `\"drops-hour\";r=2;t=1800`.",
        "schema": {
          "type": "string"
        }
      },
      "RateLimitPolicy": {
        "description": "Quota policy using the IETF RateLimit-Policy structured field, for example `\"drops-hour\";q=3;w=3600`.",
        "schema": {
          "type": "string"
        }
      },
      "RateLimitLimit": {
        "description": "Compatibility field containing the hourly create limit.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "RateLimitRemaining": {
        "description": "Compatibility field containing the number of creates remaining in the current rolling window.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "RateLimitReset": {
        "description": "Compatibility field containing seconds until quota becomes available.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before attempting another create.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      }
    },
    "responses": {
      "Error": {
        "description": "The request failed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "DropGitHubSource": {
        "type": "object",
        "additionalProperties": false,
        "required": ["kind", "url"],
        "properties": {
          "kind": {
            "type": "string",
            "const": "github"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "HTTPS URL for a public GitHub repository."
          },
          "ref": {
            "type": "string",
            "description": "Optional branch, tag, or commit."
          }
        }
      },
      "CreateDropRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["source"],
        "properties": {
          "source": {
            "$ref": "#/components/schemas/DropGitHubSource"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "lifetime_hours": {
            "type": "integer",
            "const": 24,
            "default": 24
          },
          "manifest_path": {
            "type": "string",
            "maxLength": 240
          },
          "requested_mode": {
            "type": "string",
            "enum": ["auto", "static", "compute"],
            "default": "auto"
          },
          "start_command": {
            "type": "string",
            "maxLength": 2000
          },
          "setup_command": {
            "type": "string",
            "maxLength": 4000
          },
          "port": {
            "type": "integer",
            "minimum": 1,
            "maximum": 65535
          },
          "environment": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "default": {}
          }
        }
      },
      "DropCreateResponse": {
        "type": "object",
        "required": [
          "drop_id",
          "status",
          "status_url",
          "expires_at",
          "control_token",
          "claim_url",
          "limits"
        ],
        "properties": {
          "drop_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": ["accepted", "provisioning", "ready", "failed", "claimed", "deleted", "deleting"]
          },
          "status_url": {
            "type": "string",
            "format": "uri"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "control_token": {
            "type": "string",
            "writeOnly": true
          },
          "claim_url": {
            "type": "string",
            "format": "uri"
          },
          "public_url": {
            "type": ["string", "null"],
            "format": "uri"
          },
          "limits": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          }
        }
      },
      "DropStatusResponse": {
        "type": "object",
        "required": ["drop_id", "status", "source"],
        "properties": {
          "drop_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string"
          },
          "created_at": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "expires_at": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "public_url": {
            "type": ["string", "null"],
            "format": "uri"
          },
          "source": {
            "type": "object",
            "additionalProperties": {
              "type": ["string", "null"]
            }
          },
          "failure_message": {
            "type": ["string", "null"]
          }
        }
      },
      "ClaimDropRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["claim_token"],
        "properties": {
          "claim_token": {
            "type": "string",
            "minLength": 32,
            "maxLength": 200,
            "writeOnly": true
          },
          "target_account_id": {
            "type": ["string", "null"]
          },
          "target_environment": {
            "type": "string",
            "const": "production",
            "default": "production"
          }
        }
      },
      "ClaimDropResponse": {
        "type": "object",
        "required": ["drop_id", "project_id", "account_id", "status"],
        "properties": {
          "drop_id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": ["detail"],
        "properties": {
          "detail": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {}
              }
            ]
          }
        }
      }
    }
  }
}
