Marketplace
Browse, deploy, and manage marketplace items (apps and agents). Includes vertical/category listings, available add-ons and AI models, deployment progress tracking, reviews, and admin-only listing CRUD.
All endpoints require authentication via X-API-Key header and the appropriate scope.
Marketplace Item Object
{
"_id": "mkt_abc123",
"name": "HP Collects",
"description": "Hyperscale automated collections agent",
"vendor": "Strongly AI",
"type": "app",
"vertical": "legal",
"rating": 4.8,
"reviews": 24,
"featured": true,
"tags": ["collections", "legal", "automation"],
"images": ["https://cdn.example.com/hp-collects-1.png"],
"pricing": { "model": "subscription", "monthly": 499 },
"appName": "hp-collects",
"createdAt": "2026-01-10T08:00:00Z",
"updatedAt": "2026-05-01T14:22:00Z"
}
GET /api/v1/marketplace/items
List marketplace items with pagination and filters.
Scope: marketplace:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | No | Search term to filter items by name, description, or tags |
vertical | string | No | Filter by vertical/category |
type | string | No | Filter by type (app or agent) |
featured | string | No | Filter featured items (set to "true") |
limit | number | No | Number of items per page |
cursor | string | No | meta.nextCursor of the previous page; omit for the first page |
sort | string | No | Sort field, prefixed with - for descending (default: -createdAt) |
Response 200 OK
Each list item carries only _id, rating, reviews, featured, tags, images, pricing, appName, createdAt and updatedAt. Get the item for its name, description, vendor, type and the rest of the Marketplace Item object.
{
"data": [
{
"_id": "mkt_abc123",
"rating": 4.8,
"reviews": 24,
"featured": true,
"tags": ["collections", "legal", "automation"],
"images": ["https://cdn.example.com/hp-collects-1.png"],
"pricing": { "model": "subscription", "monthly": 499 },
"appName": "hp-collects",
"createdAt": "2026-01-10T08:00:00Z",
"updatedAt": "2026-05-01T14:22:00Z"
}
],
"meta": {
"total": 42,
"limit": 50,
"nextCursor": null,
"requestId": "req_abc123"
}
}
GET /api/v1/marketplace/verticals
List all marketplace verticals/categories with item counts and average rating, most items first. _id is the vertical.
Scope: marketplace:read
Response 200 OK
{
"data": [
{ "_id": "healthcare", "count": 12, "avgRating": 4.6 },
{ "_id": "legal", "count": 8, "avgRating": 4.8 },
{ "_id": "finance", "count": 6, "avgRating": 4.2 }
],
"meta": { "requestId": "req_abc123" }
}
GET /api/v1/marketplace/available-addons
List the running or deploying add-ons you can connect a marketplace deployment to. grouped groups them by type and also includes your connected object-store data sources (S3, GCS, MinIO, Azure Blob), marked isDataSource: true.
Scope: marketplace:read
Response 200 OK
{
"data": {
"addons": [
{ "_id": "addon_001", "label": "orders-db", "type": "postgresql", "status": "running", "cpu": "1", "memory": "2Gi", "disk": "10Gi", "owner": "user_123" }
],
"grouped": {
"postgresql": [
{ "_id": "addon_001", "label": "orders-db", "type": "postgresql", "status": "running", "cpu": "1", "memory": "2Gi", "disk": "10Gi", "owner": "user_123", "isOwned": true, "isDataSource": false }
],
"s3": [
{ "_id": "ds_001", "label": "raw-bucket", "type": "s3", "status": "connected", "owner": "user_123", "isOwned": true, "isDataSource": true }
]
}
},
"meta": { "requestId": "req_abc123" }
}
GET /api/v1/marketplace/available-models
List AI models available for deployment from the marketplace.
Scope: marketplace:read
Response 200 OK
{
"data": {
"models": [
{ "_id": "model_001", "name": "GPT-4o mini", "provider": "openai", "vendorModelId": "gpt-4o-mini", "modelType": "chat", "type": "third-party", "status": "active", "owner": "user_123", "capabilities": ["chat"] }
],
"grouped": {
"openai": [
{ "_id": "model_001", "name": "GPT-4o mini", "provider": "openai", "vendorModelId": "gpt-4o-mini", "modelType": "chat", "type": "third-party", "status": "active", "owner": "user_123", "capabilities": ["chat"], "isOwned": true }
]
}
},
"meta": { "requestId": "req_abc123" }
}
grouped holds the same models grouped by provider.
POST /api/v1/marketplace/deploy
Deploy a marketplace offering. The request is checked first (terms, sizes, governance, and for an admin the target organization); a refused request answers with its reason and nothing is created. Otherwise the deployment starts, the response is 202 Accepted, and it continues in the background: follow it with GET /marketplace/deployments/:id/status.
Scope: marketplace:deploy
Request Body
{
"appName": "kanban",
"config": {
"marketplaceItemId": "TAF3eYpX8iQ7shNnA",
"termsAccepted": true,
"resources": { "cpu": "1", "memory": "2GB", "disk": "10GB", "instances": 1 },
"addons": [
{
"id": "db",
"type": "postgres",
"useExisting": false,
"createNew": { "label": "kanban-db", "cpu": "0.5", "memory": "1GB", "disk": "10GB" }
}
]
}
}
| Field | Type | Required | Description |
|---|---|---|---|
appName | string | Yes | The offering's appName, as returned by GET /marketplace/items |
config.marketplaceItemId | string | Yes | The marketplace item ID |
config.termsAccepted | boolean | Yes | Must be true to accept the Marketplace terms |
config.resources | object | No | The app's size and capacity: cpu (cores, e.g. "1", "500m"), memory (e.g. "2GB"), disk, instances, useSpot (run the app on spot capacity, default false) and spotFallback (with useSpot: fall back to on-demand when spot is unavailable, default true) |
config.addons | array | No | For each add-on the offering needs: id and type from the offering, useExisting with existingId, or createNew with label, cpu, memory, disk and optional backupConfig |
config.permissions | object | No | isPublic and allowedUsers for the deployed app |
config.targetOrganizationId | string | No | Admins only: deploy into another organization, owned by its owner |
Sizes
Nothing is sized by default:
- The app runs at
config.resourceswhen given, otherwise at the size the offering declares (resources.defaultsinGET /marketplace/items/:id/deploy-config). - Each new add-on runs at the
cpu,memoryanddiskin itscreateNew, otherwise at the offering'saddons[].defaults. - A size that cannot run (not a size, below the add-on type's minimum memory, or larger than the biggest node) is refused with
400before anything is created. - When a size is still missing, the deployment fails at that step and its status names what is missing.
Response 202 Accepted
{
"data": {
"message": "Deployment initiated",
"appName": "kanban",
"marketplaceItemId": "TAF3eYpX8iQ7shNnA",
"deploymentId": "dpl_abc123"
},
"meta": { "requestId": "..." }
}
Pass deploymentId as :id to the deployment status endpoint.
Errors
| Status | Code | When |
|---|---|---|
400 | validation-error | A required field is missing, or a size cannot run (the message says which) |
403 | forbidden / governance-blocked | The offering is not available to you, a non-admin set targetOrganizationId, or governance requirements are not met |
422 | validation-error | termsAccepted is not true |
GET /api/v1/marketplace/deployments
List all marketplace items deployed by the current user, keyed by marketplace item ID.
Scope: marketplace:deploy
Response 200 OK
{
"data": {
"deployedItems": {
"mkt_abc123": {
"appId": "app_xyz789",
"appName": "my-hp-collects",
"status": "running",
"marketplaceAppName": "hp-collects",
"deployedAt": "2026-05-10T12:00:00Z"
}
}
},
"meta": { "requestId": "req_abc123" }
}
GET /api/v1/marketplace/deployments/:id
Get full deployment info including progress, status, and created resources for a marketplace item.
Scope: marketplace:deploy
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Marketplace item/deployment ID |
Response 200 OK
{
"data": {
"deploymentId": "dpl_abc123",
"marketplaceItemId": "mkt_abc123",
"appName": "hp-collects",
"deployed": false,
"progress": {
"status": "deploying",
"currentStep": 3,
"percentage": 65,
"stepMessage": "Downloading app",
"startedAt": "2026-05-16T10:00:00Z",
"updatedAt": "2026-05-16T10:02:00Z",
"completedAt": null
},
"result": null,
"error": null,
"createdResources": null,
"cleanupResults": null
},
"meta": { "requestId": "req_abc123" }
}
GET /api/v1/marketplace/deployments/:id/status
Get lightweight deployment status with progress percentage for a marketplace item.
Scope: marketplace:deploy
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Marketplace item/deployment ID |
Response 200 OK
{
"data": {
"deploymentId": "dpl_abc123",
"marketplaceItemId": "mkt_abc123",
"deployed": false,
"status": "deploying",
"progress": {
"currentStep": 3,
"percentage": 65,
"stepMessage": "Downloading app",
"updatedAt": "2026-05-16T10:02:00Z"
},
"error": null
},
"meta": { "requestId": "req_abc123" }
}
POST /api/v1/marketplace/deployments/:id/cancel
Cancel an in-progress marketplace deployment.
Scope: marketplace:deploy
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Marketplace item/deployment ID to cancel |
Response 202 Accepted
The deployment, as GET /marketplace/deployments/:id shows it, progress.status cancelling. Follow it until it is cancelled: what it created has then been removed (cleanupResults says what).
DELETE /api/v1/marketplace/deployments/:id
Remove the record of a finished (complete, failed or cancelled) deployment. What it created is kept.
Scope: marketplace:deploy
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The deployment ID |
Response 204 No Content
Errors: 404 when there is no such deployment (or you cannot see it); 409 while it is still running (cancel it first).
-----------|------|----------|-------------|
| id | string | Yes | Marketplace item/deployment ID to clear progress for |
Response 200 OK
{
"data": {
"message": "Deployment record removed",
"deploymentId": "dpl_abc123",
"cleared": true,
"previousStatus": "failed"
},
"meta": { "requestId": "req_abc123" }
}
GET /api/v1/marketplace/items/:id
Get full details for a single marketplace item.
Scope: marketplace:read
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Marketplace item ID |
Response 200 OK
Returns the full Marketplace Item object.
GET /api/v1/marketplace/items/:id/deploy-config
Get the deploy.json configuration for a marketplace item.
Scope: marketplace:read
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Marketplace item ID |
Response 200 OK
{
"data": {
"appName": "hp-collects",
"addons": ["postgresql"],
"models": ["qwen-2-5-7b"],
"workflows": ["pii-redaction"],
"envSchema": []
},
"meta": { "requestId": "req_abc123" }
}
GET /api/v1/marketplace/items/:id/license
Get the license text for a marketplace item.
Scope: marketplace:read
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Marketplace item ID |
Response 200 OK
{
"data": {
"content": "# LICENSE\n\nCopyright 2026 ...",
"found": true
},
"meta": { "requestId": "req_abc123" }
}
GET /api/v1/marketplace/items/:id/reviews
List all reviews for a marketplace item.
Scope: marketplace:read
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Marketplace item ID |
Response 200 OK
{
"data": {
"reviews": [
{
"userId": "user_456",
"userName": "Jane Smith",
"rating": 5,
"title": "Game changer",
"comment": "Cut our processing time in half.",
"createdAt": "2026-04-15T10:30:00Z",
"helpful": 0,
"verified": true
}
],
"rating": 4.8,
"totalReviews": 24
},
"meta": { "requestId": "req_abc123" }
}
POST /api/v1/marketplace/items/:id/reviews
Add a review to a marketplace item.
Scope: marketplace:deploy
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Marketplace item ID |
Request Body
{
"rating": 5,
"title": "Game changer",
"comment": "Cut our processing time in half."
}
| Field | Type | Required | Description |
|---|---|---|---|
rating | number | Yes | Rating from 1 to 5 |
title | string | Yes | Review title |
comment | string | Yes | Review comment text |
Response 201 Created
Your review, as the item's reviews list shows it.
{
"data": {
"userId": "u1",
"userName": "Ada",
"rating": 5,
"title": "Great",
"comment": "Works",
"createdAt": "2026-10-11T00:00:00.000Z",
"helpful": 0,
"verified": true
},
"meta": { "requestId": "..." }
}
POST /api/v1/marketplace/items
Create a new marketplace listing. Admin only.
Scope: marketplace:admin
Request Body
{
"name": "HP Collects",
"description": "Hyperscale automated collections agent",
"vendor": "Strongly AI",
"type": "app",
"vertical": "legal"
}
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Item name |
description | string | Yes | Item description |
vendor | string | Yes | Vendor name |
type | string | Yes | Item type (app or agent) |
vertical | string | Yes | Vertical/category for the item |
Response 201 Created
{
"data": "mkt_abc123",
"meta": { "requestId": "req_abc123" }
}
PATCH /api/v1/marketplace/items/:id
Update an existing marketplace listing. Admin only.
Scope: marketplace:admin
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Marketplace item ID |
Request Body
Any subset of the Marketplace Item object fields to update.
Response 200 OK
data is the number of listings updated: 1, or 0 when no listing has that ID. Get the item to read its new state.
{
"data": 1,
"meta": { "requestId": "req_abc123" }
}
DELETE /api/v1/marketplace/items/:id
Delete a marketplace listing. Admin only.
Scope: marketplace:admin
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Marketplace item ID |
Response 204 No Content
POST /api/v1/marketplace/usage-events
Record one usage event of an offering with metered billing (a resume processed, an interview
hour, a change in seats). Recording the same idempotencyKey again records nothing.
Scope: offering-usage:write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
offeringId | string | Yes | The offering |
meterKey | string | Yes | A meter of the offering's subscription, for example resumes |
quantity | number | Yes | How much (a counter: the amount used; a gauge: its value now) |
idempotencyKey | string | Yes | Your unique key for the event |
occurredAt | string | No | When it happened, ISO 8601 (default now) |
Response 201 Created: { eventId, deduplicated }.