REST API
Read your workspace and handle collaborator access to client stores. Version 1.1.0, described in OpenAPI 3.1 for generating a client.
Authentication
Create a key in Settings → AI tools. Choose what it may do: read apps, stores and releases (workspace:read), check access (collaboration:read), or also send access requests (collaboration:write). The key is shown once. The same page shows your workspace ID.
Every request carries Authorization: Bearer <key> and your workspace ID in the path: https://deploteka.com/api/agent/v1/tenants/YOUR_TENANT_ID. Keep the key in a secret manager and never in code.
Workspace reads work as soon as you have a key. Access checks and requests also need your Shopify organization connected and authorized in the cabinet.
First call
curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer ${DEPLOTEKA_API_TOKEN}" \
"https://deploteka.com/api/agent/v1/tenants/YOUR_TENANT_ID/workspace/apps?limit=5"
The same call from Node.js and Python:
const base = `https://deploteka.com/api/agent/v1/tenants/${process.env.DEPLOTEKA_TENANT_ID}`;
const headers = { authorization: `Bearer ${process.env.DEPLOTEKA_API_TOKEN}` };
const response = await fetch(`${base}/workspace/apps?limit=5`, { headers });
if (!response.ok) throw new Error(`DeploTeka answered ${response.status}`);
const { items, nextCursor } = await response.json();
import os, requests
base = f"https://deploteka.com/api/agent/v1/tenants/{os.environ['DEPLOTEKA_TENANT_ID']}"
headers = {"Authorization": f"Bearer {os.environ['DEPLOTEKA_API_TOKEN']}"}
response = requests.get(f"{base}/workspace/apps", params={"limit": 5}, headers=headers, timeout=30)
response.raise_for_status()
page = response.json() # {"items": [...], "nextCursor": ...}
Pagination
Lists return items and nextCursor. Pass nextCursor as after until it is null. limit is 1–100, 25 by default.
Endpoints
Paths below include {tenantId}, your workspace ID. To ask for access, send a body like this, using only permissions that capabilities returns:
{
"shopDomain": "client-store-shopify-demo.myshopify.com",
"permissions": [
"analytics_reports"
],
"context": {
"system": "other",
"projectRef": "project-42",
"taskRef": "task-7"
},
"idempotencyKey": "project-42:task-7:access:v1"
}
GET /api/agent/v1/tenants/{tenantId}/shopify/capabilities
Requires collaboration:read. Returns supported permission names.
Key access: collaboration:read · MCP tool: shopify_access_capabilities
Response 200
| Field | Type | Required | Notes |
|---|---|---|---|
version | "1" | yes | |
provider | "shopify" | yes | |
permissions | string[] | yes | |
scopes | string[] | yes | |
requestModes | "access" | "additional_permissions"[] | no | 0–2 items |
Other answers: 400 Invalid bounded input, 404 Absent resource or unusable credential; deliberately indistinguishable, 409 Connection/consent or request conflict; do not retry blindly, 429 Rate limit; honor Retry-After, 503 No trustworthy provider result.
GET /api/agent/v1/tenants/{tenantId}/shopify/access
Requires collaboration:read. Asks Shopify for the current relationship. Specific permission scopes are not verified.
Key access: collaboration:read · MCP tool: shopify_access_check
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
shopDomain | query | string | yes | up to 255 characters |
Response 200
| Field | Type | Required | Notes |
|---|---|---|---|
shopDomain | string | yes | |
relationship | "approved" | "pending" | "none" | yes | |
permissionVerification | "not_verified" | yes | |
checkedAt | string (date-time) | yes |
Other answers: 400 Invalid bounded input, 404 Absent resource or unusable credential; deliberately indistinguishable, 409 Connection/consent or request conflict; do not retry blindly, 429 Rate limit; honor Retry-After, 503 No trustworthy provider result.
POST /api/agent/v1/tenants/{tenantId}/shopify/access-requests
Requires collaboration:write. Caller context is traceability, not authority. Sends exactly the listed permissions. Reuse one key for one intent; never change keys to retry an unknown outcome.
Key access: collaboration:write · MCP tool: shopify_access_request
Request body application/json
| Field | Type | Required | Notes |
|---|---|---|---|
shopDomain | string | yes | pattern ^[a-zA-Z0-9][a-zA-Z0-9-]*\.myshopify\.com$ |
context | Context | yes | |
permissions | string[] | yes | 1–40 items |
idempotencyKey | string | yes | up to 200 characters |
collaboratorCode | string | no | pattern ^\d{4}$, write-only |
requestMode | "access" | "additional_permissions" | no | Explicit expansion attempts dispatch for existing approved relationships. Relationship-only refresh cannot verify the added rights.. default "access" |
Response 200
| Field | Type | Required | Notes |
|---|---|---|---|
requestId | string | yes | |
shopDomain | string | yes | |
context | Context | yes | |
requestedPermissions | string[] | yes | |
status | "dispatching" | "pending" | "granted" | "refused" | "unknown" | yes | |
permissionVerification | "not_verified" | yes | |
providerCode | string | null | yes | |
nextAction | "wait_for_merchant" | "verify_required_permissions" | "reconcile_before_retry" | "review_refusal" | "poll" | yes | |
createdAt | string (date-time) | yes | |
updatedAt | string (date-time) | yes | |
requestMode | "access" | "additional_permissions" | no | Persisted request intent; legacy receipts default to access. |
Other answers: 400 Invalid bounded input, 404 Absent resource or unusable credential; deliberately indistinguishable, 409 Connection/consent or request conflict; do not retry blindly, 429 Rate limit; honor Retry-After, 503 No trustworthy provider result.
GET /api/agent/v1/tenants/{tenantId}/shopify/access-requests/{requestId}
Requires collaboration:read. Stored receipt only; updatedAt states freshness.
Key access: collaboration:read · MCP tool: shopify_access_request_status
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
requestId | path | string | yes |
Response 200
| Field | Type | Required | Notes |
|---|---|---|---|
requestId | string | yes | |
shopDomain | string | yes | |
context | Context | yes | |
requestedPermissions | string[] | yes | |
status | "dispatching" | "pending" | "granted" | "refused" | "unknown" | yes | |
permissionVerification | "not_verified" | yes | |
providerCode | string | null | yes | |
nextAction | "wait_for_merchant" | "verify_required_permissions" | "reconcile_before_retry" | "review_refusal" | "poll" | yes | |
createdAt | string (date-time) | yes | |
updatedAt | string (date-time) | yes | |
requestMode | "access" | "additional_permissions" | no | Persisted request intent; legacy receipts default to access. |
Other answers: 400 Invalid bounded input, 404 Absent resource or unusable credential; deliberately indistinguishable, 409 Connection/consent or request conflict; do not retry blindly, 429 Rate limit; honor Retry-After, 503 No trustworthy provider result.
POST /api/agent/v1/tenants/{tenantId}/shopify/access-requests/{requestId}/refresh
Requires collaboration:read. Reconciles evidence without resending. Does not verify individual permissions.
Key access: collaboration:read · MCP tool: shopify_access_request_refresh
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
requestId | path | string | yes |
Request body application/json
Response 200
| Field | Type | Required | Notes |
|---|---|---|---|
requestId | string | yes | |
shopDomain | string | yes | |
context | Context | yes | |
requestedPermissions | string[] | yes | |
status | "dispatching" | "pending" | "granted" | "refused" | "unknown" | yes | |
permissionVerification | "not_verified" | yes | |
providerCode | string | null | yes | |
nextAction | "wait_for_merchant" | "verify_required_permissions" | "reconcile_before_retry" | "review_refusal" | "poll" | yes | |
createdAt | string (date-time) | yes | |
updatedAt | string (date-time) | yes | |
requestMode | "access" | "additional_permissions" | no | Persisted request intent; legacy receipts default to access. |
Other answers: 400 Invalid bounded input, 404 Absent resource or unusable credential; deliberately indistinguishable, 409 Connection/consent or request conflict; do not retry blindly, 429 Rate limit; honor Retry-After, 503 No trustworthy provider result.
GET /api/agent/v1/tenants/{tenantId}/workspace/apps
Requires workspace:read. List workspace app definitions.
Key access: workspace:read · MCP tool: workspace_apps_list
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
limit | query | integer | no | 1–100, default 25 |
after | query | string | no | Pass nextCursor from the previous page of this collection.. pattern ^[A-Za-z0-9_-]{1,128}$ |
Response 200
| Field | Type | Required | Notes |
|---|---|---|---|
items | object[] | yes | 0–100 items |
nextCursor | string | null | yes |
Each item:
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | pattern ^[A-Za-z0-9_-]{1,128}$ |
name | string | yes | |
status | string | null | yes |
Other answers: 400 Invalid bounded input, 404 Absent resource or unusable credential; deliberately indistinguishable, 429 Rate limit; honor Retry-After, 503 No trustworthy provider result.
GET /api/agent/v1/tenants/{tenantId}/workspace/stores
Requires workspace:read. List workspace stores and their recorded status.
Key access: workspace:read · MCP tool: workspace_stores_list
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
limit | query | integer | no | 1–100, default 25 |
after | query | string | no | Pass nextCursor from the previous page of this collection.. pattern ^[A-Za-z0-9_-]{1,128}$ |
Response 200
| Field | Type | Required | Notes |
|---|---|---|---|
items | object[] | yes | 0–100 items |
nextCursor | string | null | yes |
Each item:
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | pattern ^[A-Za-z0-9_-]{1,128}$ |
shopDomain | string | yes | |
status | string | yes |
Other answers: 400 Invalid bounded input, 404 Absent resource or unusable credential; deliberately indistinguishable, 429 Rate limit; honor Retry-After, 503 No trustworthy provider result.
GET /api/agent/v1/tenants/{tenantId}/workspace/releases/{releaseId}
Requires workspace:read. Read a saved fleet release by ID.
Key access: workspace:read · MCP tool: workspace_release_status
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
releaseId | path | string | yes | pattern ^[A-Za-z0-9_-]{1,128}$ |
Response 200
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | pattern ^[A-Za-z0-9_-]{1,128}$ |
masterAppId | string | yes | pattern ^[A-Za-z0-9_-]{1,128}$ |
state | string | yes | |
createdAt | string (date-time) | yes | |
updatedAt | string (date-time) | yes |
Other answers: 400 Invalid bounded input, 404 Absent resource or unusable credential; deliberately indistinguishable, 429 Rate limit; honor Retry-After, 503 No trustworthy provider result.
Errors and retries
Errors are JSON: {"error": "…"}, one of NOT_FOUND, INVALID_INPUT, IDEMPOTENCY_CONFLICT, ACTIVE_REQUEST_CONFLICT, CONNECTION_REQUIRED, PROVIDER_UNAVAILABLE, UNAVAILABLE, RATE_LIMITED.
- 400: check the fields against the endpoint above.
- 404: check the workspace ID, the key’s access and expiry, then the resource ID. A refused key also answers 404.
- 409: resolve the conflict first. Don’t retry blindly.
- 429: wait the number of seconds in
Retry-After. - 503 or a timeout: back off. For an access request, keep the same idempotency key and body. If you have a receipt, read or refresh it before sending another request.
A pending request needs the merchant’s approval. An approved relationship does not prove Shopify granted every permission you asked for.