Xbow Resources API
Upload and manage files used in assessments, such as source code archives.All endpoints require an _organization_ API key.## Upload flowResources use a multipart S3 upload. The full flow is:1. **Create** — `POST /api/v1/organizations/:organizationId/resources` — initiates an upload and returns a resource ID. Status is `initiated`.2. **Get part URLs** — `POST /api/v1/resources/:resourceId/parts` — provide a list of part numbers and receive a corresponding list of presigned S3 `PUT` URLs.3. **Upload parts** — `PUT` each part directly to its presigned URL. Save the `ETag` header from each part response.4. **Commit** — `POST /api/v1/resources/:resourceId/commit` — submit the part numbers and ETags. Optionally include a `sha256` checksum of the full file for server-side integrity verification. Status moves to `processing`.5. **Poll** — `GET /api/v1/resources/:resourceId` — wait until status is `ready` (or `failed`).6. **Delete** — `DELETE /api/v1/resources/:resourceId` — the resource can be manually deleted when required. Status moves to `deleted`.The maximum part size is 5 GiB. Parts must be at least 5 MiB each, except the final part which may be smaller.Breaking large files into multiple parts allows failed parts to be retried individually rather than restarting the entire upload.## Resource statuses| Status | Meaning ||---|---|| `initiated` | Upload in progress — parts not yet committed || `processing` | Commit received — server is validating and storing || `ready` | Available to use in assessments || `failed` | Processing failed — see `statusMessage` for details || `deleted` | Deleted |## ExampleThis snippet shows how to upload an example file named `source.tar.gz` using the API multipart upload feature.It uses the `fetch` API and assumes a Node.js environment with `fs/promises` available.```typescriptimport fs from "node:fs/promises";import crypto from "node:crypto";const BASE = "https://console.xbow.com";const ORG_ID = "your-organization-id";const API_KEY = "your-api-key";const PART_SIZE = 5 * 1024 * 1024; // 5 MiB minimumconst API_VERSION = "next";const headers = { "Authorization": `Bearer ${API_KEY}`, "X-XBOW-API-Version": `${API_VERSION}` };// 1. Create resourceconst created = await fetch(`${BASE}/api/v1/organizations/${ORG_ID}/resources`, { method: "POST", headers: { ...headers, "Content-Type": "application/json" }, body: JSON.stringify({ name: "My source", fileName: "source.tar.gz", type: "source" }),}).then(r => r.json());const resourceId = created.id;// 2. Split file into parts and request presigned URLsconst file = await fs.readFile("source.tar.gz");const partCount = Math.ceil(file.length / PART_SIZE);const { parts: partUrls } = await fetch(`${BASE}/api/v1/resources/${resourceId}/parts`, { method: "POST", headers: { ...headers, "Content-Type": "application/json" }, body: JSON.stringify({ parts: Array.from({ length: partCount }, (_, i) => i + 1) }),}).then(r => r.json());// 3. Upload each part to S3 directly, collect ETagsconst uploadedParts = await Promise.all(partUrls.map(async ({ partNumber, url }) => { const chunk = file.slice((partNumber - 1) * PART_SIZE, partNumber * PART_SIZE); const res = await fetch(url, { method: "PUT", body: chunk }); return { partNumber, eTag: res.headers.get("ETag").replaceAll('"', "") };}));// 4. Commit (sha256 is optional but recommended for integrity verification)const sha256 = crypto.createHash("sha256").update(file).digest("hex");await fetch(`${BASE}/api/v1/resources/${resourceId}/commit`, { method: "POST", headers: { ...headers, "Content-Type": "application/json" }, body: JSON.stringify({ parts: uploadedParts, sha256 }),}).then(r => r.json());// 5. Poll until readylet resource;do { await new Promise(r => setTimeout(r, 5000)); resource = await fetch(`${BASE}/api/v1/resources/${resourceId}`, { headers }).then(r => r.json());} while (resource.status === "processing" || resource.status === "initiated");if (resource.status !== "ready") throw new Error(`Upload failed: ${resource.statusMessage}`);console.log("Resource ready:", resource.id);// 6. Delete when no longer requiredawait fetch(`${BASE}/api/v1/resources/${resourceId}`, { method: "DELETE", headers,});```
Xbow Resources API is one of 9 APIs that Xbow publishes on the APIs.io network, described by a machine-readable OpenAPI specification.
Tagged areas include Resources. The published artifact set on APIs.io includes an OpenAPI specification and API documentation.
This API exposes 6 operations across 4 paths. It is described by OpenAPI 3.1.0, at version 2026-07-01.
Requests are made against 3 base URLs: https://console.xbow.com/, https://console.eu.xbow.com/, https://console.sg.xbow.com/.
Metadata
The identity and technical contract details declared by the specification.
Authentication & Security 1
Xbow Resources API declares
1 security scheme
for authenticating requests.
It accepts HTTP bearer tokens (API Key) (Authorization).
Authorization— Authorization header with Bearer token
Paths & Operations 6
Across 4 paths, the API surfaces 6 operations — 1 DELETE, 2 GET, 3 POST. Each is listed below with its method, path, parameters, and response codes.
Upload and manage files used in assessments, such as source code archives. All endpoints require an organization API key. Upload flow Resources use a multipart S3 upload. The full…
Specification
The full machine-readable OpenAPI contract behind this narrative.
Source
More from Xbow 8
Other APIs Xbow publishes across the network.