DeploTeka Set up your first store
Developer docs: REST API

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

FieldTypeRequiredNotes
version"1"yes
provider"shopify"yes
permissionsstring[]yes
scopesstring[]yes
requestModes"access" | "additional_permissions"[]no0–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

NameInTypeRequiredNotes
shopDomainquerystringyesup to 255 characters

Response 200

FieldTypeRequiredNotes
shopDomainstringyes
relationship"approved" | "pending" | "none"yes
permissionVerification"not_verified"yes
checkedAtstring (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

FieldTypeRequiredNotes
shopDomainstringyespattern ^[a-zA-Z0-9][a-zA-Z0-9-]*\.myshopify\.com$
contextContextyes
permissionsstring[]yes1–40 items
idempotencyKeystringyesup to 200 characters
collaboratorCodestringnopattern ^\d{4}$, write-only
requestMode"access" | "additional_permissions"noExplicit expansion attempts dispatch for existing approved relationships. Relationship-only refresh cannot verify the added rights.. default "access"

Response 200

FieldTypeRequiredNotes
requestIdstringyes
shopDomainstringyes
contextContextyes
requestedPermissionsstring[]yes
status"dispatching" | "pending" | "granted" | "refused" | "unknown"yes
permissionVerification"not_verified"yes
providerCodestring | nullyes
nextAction"wait_for_merchant" | "verify_required_permissions" | "reconcile_before_retry" | "review_refusal" | "poll"yes
createdAtstring (date-time)yes
updatedAtstring (date-time)yes
requestMode"access" | "additional_permissions"noPersisted 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

NameInTypeRequiredNotes
requestIdpathstringyes

Response 200

FieldTypeRequiredNotes
requestIdstringyes
shopDomainstringyes
contextContextyes
requestedPermissionsstring[]yes
status"dispatching" | "pending" | "granted" | "refused" | "unknown"yes
permissionVerification"not_verified"yes
providerCodestring | nullyes
nextAction"wait_for_merchant" | "verify_required_permissions" | "reconcile_before_retry" | "review_refusal" | "poll"yes
createdAtstring (date-time)yes
updatedAtstring (date-time)yes
requestMode"access" | "additional_permissions"noPersisted 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

NameInTypeRequiredNotes
requestIdpathstringyes

Request body application/json

Response 200

FieldTypeRequiredNotes
requestIdstringyes
shopDomainstringyes
contextContextyes
requestedPermissionsstring[]yes
status"dispatching" | "pending" | "granted" | "refused" | "unknown"yes
permissionVerification"not_verified"yes
providerCodestring | nullyes
nextAction"wait_for_merchant" | "verify_required_permissions" | "reconcile_before_retry" | "review_refusal" | "poll"yes
createdAtstring (date-time)yes
updatedAtstring (date-time)yes
requestMode"access" | "additional_permissions"noPersisted 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

NameInTypeRequiredNotes
limitqueryintegerno1–100, default 25
afterquerystringnoPass nextCursor from the previous page of this collection.. pattern ^[A-Za-z0-9_-]{1,128}$

Response 200

FieldTypeRequiredNotes
itemsobject[]yes0–100 items
nextCursorstring | nullyes

Each item:

FieldTypeRequiredNotes
idstringyespattern ^[A-Za-z0-9_-]{1,128}$
namestringyes
statusstring | nullyes

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

NameInTypeRequiredNotes
limitqueryintegerno1–100, default 25
afterquerystringnoPass nextCursor from the previous page of this collection.. pattern ^[A-Za-z0-9_-]{1,128}$

Response 200

FieldTypeRequiredNotes
itemsobject[]yes0–100 items
nextCursorstring | nullyes

Each item:

FieldTypeRequiredNotes
idstringyespattern ^[A-Za-z0-9_-]{1,128}$
shopDomainstringyes
statusstringyes

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

NameInTypeRequiredNotes
releaseIdpathstringyespattern ^[A-Za-z0-9_-]{1,128}$

Response 200

FieldTypeRequiredNotes
idstringyespattern ^[A-Za-z0-9_-]{1,128}$
masterAppIdstringyespattern ^[A-Za-z0-9_-]{1,128}$
statestringyes
createdAtstring (date-time)yes
updatedAtstring (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.