Skip to content

API Reference

Manage workspaces, upload specs, and interact with mock data through the Testfly REST API.

Base URL: https://api.testfly.com
Interactive docs available at /scalar/v1 on the running API.


Authentication

All platform API endpoints require authentication. Testfly supports two methods:

API Key (recommended for CI/scripts)

Pass your API key in the X-API-Key header:

curl -H "X-API-Key: tfk_your_api_key_here" \
  https://api.testfly.com/api/workspaces

JWT Bearer Token (for portal/browser)

Include the bearer token from login:

curl -H "Authorization: Bearer eyJhbG..." \
  https://api.testfly.com/api/workspaces

Create API keys from the Testfly portal under Settings → API Keys.


Workspaces

Workspaces are isolated mock API environments. Each workspace gets its own subdomain, database, and configuration.

Create workspace

POST /api/workspaces

{
  "name": "Pet Store Mock",
  "slug": "petstore",
  "rowCount": 1000,
  "seedValue": 42
}
FieldTypeRequiredDescription
namestringYesDisplay name
slugstringYesURL-safe identifier. Becomes your subdomain: {slug}.mock.testfly.com
rowCountintegerNoRows per resource table. Default: 100. Range: 1–10,000
seedValueintegerNoRandom seed for reproducible data. Same seed = identical data every time

Response 201 Created:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Pet Store Mock",
  "slug": "petstore",
  "subdomain": "petstore",
  "status": "Provisioning",
  "rowCount": 1000,
  "seedValue": 42,
  "settings": null,
  "createdBy": "...",
  "createdAt": "2026-02-17T10:00:00Z",
  "updatedAt": "2026-02-17T10:00:00Z"
}

List workspaces

GET /api/workspaces

Returns all workspaces for the authenticated organization.

Get workspace

GET /api/workspaces/{id}

Update workspace

PUT /api/workspaces/{id}

{
  "name": "Updated Name",
  "rowCount": 10000,
  "settings": {
    "latencyMs": 200,
    "errorRate": 0.05,
    "corsOrigins": ["https://app.example.com"],
    "authEnabled": false
  }
}
SettingTypeDefaultDescription
latencyMsinteger0Artificial response delay in milliseconds
errorRatefloat0.0Random 500 error probability (0.0–1.0). Set to 0.1 for 10% failure rate
corsOriginsstring[][]Allowed CORS origins
authEnabledbooleanfalseRequire authentication on mock endpoints

Delete workspace

DELETE /api/workspaces/{id}

Marks workspace as deleted and cleans up the SQLite database. Returns 204 No Content.

Regenerate data

POST /api/workspaces/{id}/regenerate

Drops all mock data and regenerates from the active spec. Useful for resetting between test runs. Respects current rowCount and seedValue.

Pause / Resume

POST /api/workspaces/{id}/pause
POST /api/workspaces/{id}/resume

Paused workspaces return 503 for all mock requests. Resume to re-activate.

Usage stats

GET /api/workspaces/{id}/usage

Returns daily request counts and bandwidth for the workspace.

Workspace status lifecycle

Provisioning → Active → Paused → Active
                    ↓ Error (if spec processing fails)

Specs

Upload OpenAPI specs to define the schema for your mock API. Each workspace can have multiple spec versions; only one can be active at a time.

Upload spec

POST /api/workspaces/{wid}/specs

{
  "rawSpec": "openapi: '3.0.0'\ninfo:\n  title: Pet Store\n  ...",
  "versionLabel": "v1.0"
}
FieldTypeRequiredDescription
rawSpecstringYesFull OpenAPI spec as YAML or JSON string
versionLabelstringNoVersion label (e.g., "v1.0"). Defaults to "v1"

Response 201 Created. The spec starts with status Pending and transitions to Ready after background processing.

List specs

GET /api/workspaces/{wid}/specs

Get spec

GET /api/workspaces/{wid}/specs/{id}

Delete spec

DELETE /api/workspaces/{wid}/specs/{id}

Spec status lifecycle

Pending → Parsing → Ready
                  ↓ Error (with errorMessage)

Resources & Routes

After a spec is processed, Testfly extracts resources (database tables), routes (API endpoints), and relationships (foreign keys). These are read-only — derived from your spec.

List resources

GET /api/workspaces/{wid}/specs/{id}/resources

[
  {
    "id": "...",
    "schemaName": "Pet",
    "tableName": "pets",
    "routeBasePath": "/pets",
    "sortOrder": 1,
    "rowCountOverride": null
  },
  {
    "id": "...",
    "schemaName": "User",
    "tableName": "users",
    "routeBasePath": "/users",
    "sortOrder": 0
  }
]

sortOrder reflects the topological sort — parent tables first.

List routes

GET /api/workspaces/{wid}/specs/{id}/routes

[
  {
    "httpMethod": "GET",
    "pathTemplate": "/pets",
    "operationId": "listPets",
    "responseStatusCode": 200,
    "isCollection": true
  },
  {
    "httpMethod": "POST",
    "pathTemplate": "/pets",
    "operationId": "createPet",
    "responseStatusCode": 201,
    "isCollection": false
  }
]

List relationships

GET /api/workspaces/{wid}/specs/{id}/relationships

[
  {
    "sourceColumn": "owner_id",
    "targetColumn": "id",
    "relationshipType": "ManyToOne"
  }
]

Mock API (CRUD)

Once a workspace is Active, your mock API is live. Access it via subdomain or path prefix:

# Subdomain (production)
https://petstore.mock.testfly.com/pets

# Path prefix (development)
https://api.testfly.com/mock/petstore/pets

List records (paginated)

GET /pets?page=1&pageSize=20&sortBy=name&sortDesc=true&species=cat

{
  "data": [
    {
      "id": "a1b2c3d4",
      "name": "Luna",
      "species": "cat",
      "owner_id": "u_7f8e9d"
    }
  ],
  "meta": {
    "page": 1,
    "pageSize": 20,
    "totalCount": 47,
    "totalPages": 3
  }
}
ParamTypeDefaultDescription
pageint1Page number (1-indexed)
pageSizeint20Results per page (max 100)
sortBystring—Column name to sort by
sortDescboolfalseSort descending
any otherstring—Filter: ?status=active

Get single record

GET /pets/{id}

{ "id": "a1b2c3d4", "name": "Luna", "species": "cat", "owner_id": "u_7f8e9d" }

Returns 404 with {"error": "Resource not found"} if not found.

Create record

POST /pets
Content-Type: application/json

{ "name": "Bella", "species": "dog", "owner_id": "u_7f8e9d" }

Returns 201 Created with auto-generated UUID id and Location header.

Update record

PUT /pets/{id}
Content-Type: application/json

{ "name": "Bella Mae" }

Partial updates supported. Returns 200 or 404.

Delete record

DELETE /pets/{id}

Returns 204 No Content or 404.


Errors

All errors return a JSON body:

{ "error": "Human-readable error message" }
CodeMeaning
400Bad request (malformed JSON, invalid parameters)
401Missing or invalid authentication
403Not authorized for this organization/workspace
404Resource not found
405Method not allowed on this route
500Server error (or simulated error if errorRate configured)
503Workspace is paused or provisioning

Try it now

Create a free workspace and start making API calls in minutes.