Upload App Version

Upload a built bundle as a draft version. The manifest's name selects the app, creating it in this workspace when it is new; its version must not exist yet. Only static files (HTML, scripts, styles, data, images, fonts) may be in the bundle. The caller is authorized before the body is read. Workspace API keys return 403; use a personal API key or scoped OAuth token.

OAuth scope: api:write.

POST/api/v2/apps/versions
X-API-Key<token>

Your Agent Serve API key, personal or workspace-scoped. Generate one under Settings, then API Keys. Operations that reject workspace keys say so in their own description.

In: header

Query Parameters

workspaceId*string

Workspace the request is authorized against.

Length1 <= length <= 128

Request Body

application/octet-stream

The built bundle archive.

TypeScript Definitions

Use the request body type in TypeScript.

body*App bundle archive

The built bundle archive.

Formatbinary

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://agentserve.valnoraelric.com/api/v2/apps/versions?workspaceId=string" \  -H "X-API-Key: YOUR_API_KEY" \  -H "Content-Type: application/octet-stream" \  -d 'string'
{
  "data": {
    "app": {
      "id": "string",
      "slug": "string",
      "name": "string",
      "ownerWorkspaceId": "string",
      "createdAt": "2019-08-24T14:15:22Z",
      "updatedAt": "2019-08-24T14:15:22Z"
    },
    "version": {
      "id": "string",
      "appId": "string",
      "version": "string",
      "title": "string",
      "status": "draft",
      "artifactSha256": "string",
      "artifactSize": -9007199254740991,
      "fileCount": -9007199254740991,
      "source": {
        "kind": "upload",
        "fileName": "string"
      },
      "permissions": {
        "tables": [
          "string"
        ],
        "model": "read",
        "workflows": [
          "string"
        ],
        "relays": [
          "string"
        ],
        "chat": "ask",
        "files": "read",
        "ai": {
          "models": [
            "string"
          ],
          "media": [
            "image"
          ]
        },
        "knowledge": [
          "string"
        ],
        "integrations": [
          "string"
        ]
      },
      "budgetMonthlyUsd": 0,
      "tools": [
        {
          "name": "string",
          "description": "string",
          "effect": "read",
          "language": "javascript"
        }
      ],
      "allowVulnerable": true,
      "createdAt": "2019-08-24T14:15:22Z",
      "publishedAt": "2019-08-24T14:15:22Z",
      "retiredAt": "2019-08-24T14:15:22Z"
    },
    "createdApp": true
  }
}
{
  "error": {
    "code": "BAD_REQUEST",
    "message": "Invalid request"
  }
}
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Authentication required"
  }
}
{
  "error": {
    "code": "FORBIDDEN",
    "message": "Insufficient workspace permissions",
    "details": {
      "code": "INSUFFICIENT_WORKSPACE_ROLE"
    }
  }
}
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Not found"
  }
}
{
  "error": {
    "code": "CONFLICT",
    "message": "The request conflicts with the current state of the resource"
  }
}
{
  "error": {
    "code": "PAYLOAD_TOO_LARGE",
    "message": "Request body is too large"
  }
}
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "API rate limit exceeded",
    "details": {
      "retryAfter": "2026-01-01T00:00:30.000Z"
    }
  }
}
{
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "Internal server error"
  }
}
{
  "error": {
    "code": "SERVICE_UNAVAILABLE",
    "message": "Service temporarily unavailable"
  }
}