AI Assistant

Manage OpenRouter keys, conversations, and MCP tool execution

GET /admin/api/ai/key

Check whether the authenticated user has a personal OpenRouter API key, and whether the shop has a shared OpenRouter integration key configured.

PUT /admin/api/ai/key

Save or clear the authenticated user's personal OpenRouter API key. Pass null (or omit api_key) to clear. The key is encrypted with AES-256-GCM before being stored.

GET /admin/api/ai/key/resolve

Resolve the effective OpenRouter API key and default model for the authenticated user. Tries the personal key first, then falls back to the shop-wide OpenRouter integration key. Used by the chat UI and inline-AI hooks to issue completions without a second round-trip.

GET /admin/api/ai/conversations

List all AI conversations owned by the authenticated user, most-recently-updated first. Conversations inactive for more than 30 days are auto-purged on list.

POST /admin/api/ai/conversations

Create a new AI conversation. Title defaults to "New conversation" when absent or blank.

GET /admin/api/ai/conversations/{id}

Get a single conversation with all its messages in chronological order.

PATCH /admin/api/ai/conversations/{id}

Rename a conversation.

DELETE /admin/api/ai/conversations/{id}

Delete a conversation and all its messages.

POST /admin/api/ai/conversations/{id}/messages

Append one or more messages to an existing conversation. Typically called after a chat turn to persist the user message and the assistant's reply together.

GET /admin/api/ai/tools

List all MCP tools available to the AI assistant in OpenAI function-calling format. Each tool is scoped to the user's role permissions. Schemas are pre-cleaned for OpenAI and Anthropic compatibility.

POST /admin/api/ai/tool-execute

Execute a named MCP tool and return its text output. Tool name normalization is automatic — uppercase names, dotted prefixes, or non-alphanumeric characters are stripped during match. String "true"/"false" values in arguments are coerced to booleans.

POST /admin/api/ai/upload

Upload an HTML file or ZIP archive for the AI assistant to read. Single HTML files up to 500 KB are returned as-is. ZIP archives up to 5 MB are scanned; all .html/.htm/.css/.js entries are extracted. Returned files are typically passed back to the assistant as context for theme-porting conversations.

GET /admin/api/ai/key

Check whether the authenticated user has a personal OpenRouter API key, and whether the shop has a shared OpenRouter integration key configured.

Response 200

{
  "has_key": true,
  "has_shop_key": false
}

Example

curl "https://yourshop.zeroshop.io/admin/api/ai/key" \
  -H "Authorization: Bearer zspat_..."
PUT /admin/api/ai/key

Save or clear the authenticated user's personal OpenRouter API key. Pass null (or omit api_key) to clear. The key is encrypted with AES-256-GCM before being stored.

Request Body

{
  "api_key": "sk-or-v1-..."
}

Response 204

Example

curl -X PUT "https://yourshop.zeroshop.io/admin/api/ai/key" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"api_key": "sk-or-v1-..."}'
GET /admin/api/ai/key/resolve

Resolve the effective OpenRouter API key and default model for the authenticated user. Tries the personal key first, then falls back to the shop-wide OpenRouter integration key. Used by the chat UI and inline-AI hooks to issue completions without a second round-trip.

Response 200

{
  "api_key": "sk-or-v1-...",
  "model": "openai/gpt-4o-mini",
  "system_prompt": ""
}

Example

curl "https://yourshop.zeroshop.io/admin/api/ai/key/resolve" \
  -H "Authorization: Bearer zspat_..."
GET /admin/api/ai/conversations

List all AI conversations owned by the authenticated user, most-recently-updated first. Conversations inactive for more than 30 days are auto-purged on list.

Response 200

[
  {
    "id": "f3b2c1e4-1234-4abc-9def-0123456789ab",
    "owner_id": 42,
    "title": "Pricing strategy ideas",
    "created_at": "2026-04-10T10:00:00Z",
    "updated_at": "2026-04-15T14:30:00Z"
  },
  {
    "id": "a1b2c3d4-5678-4def-9abc-fedcba987654",
    "owner_id": 42,
    "title": "New conversation",
    "created_at": "2026-04-08T09:00:00Z",
    "updated_at": "2026-04-08T09:15:00Z"
  }
]

Example

curl "https://yourshop.zeroshop.io/admin/api/ai/conversations" \
  -H "Authorization: Bearer zspat_..."
POST /admin/api/ai/conversations

Create a new AI conversation. Title defaults to "New conversation" when absent or blank.

Request Body

{
  "title": "Pricing strategy ideas"
}

Response 201

{
  "id": "f3b2c1e4-1234-4abc-9def-0123456789ab"
}

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/ai/conversations" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"title": "Pricing strategy ideas"}'
GET /admin/api/ai/conversations/{id}

Get a single conversation with all its messages in chronological order.

Parameters

Name Type Required Description
id string required Conversation UUID

Response 200

{
  "id": "f3b2c1e4-1234-4abc-9def-0123456789ab",
  "owner_id": 42,
  "title": "Pricing strategy ideas",
  "created_at": "2026-04-10T10:00:00Z",
  "updated_at": "2026-04-15T14:30:00Z",
  "messages": [
    {
      "id": "msg-uuid-1",
      "conversation_id": "f3b2c1e4-1234-4abc-9def-0123456789ab",
      "role": "user",
      "content": "Should I run a Black Friday sale this year?",
      "token_count": 12,
      "created_at": "2026-04-10T10:00:05Z"
    },
    {
      "id": "msg-uuid-2",
      "conversation_id": "f3b2c1e4-1234-4abc-9def-0123456789ab",
      "role": "assistant",
      "content": "Based on last year's orders, yes — your Q4 revenue peaked...",
      "token_count": 245,
      "created_at": "2026-04-10T10:00:10Z"
    }
  ]
}

Example

curl "https://yourshop.zeroshop.io/admin/api/ai/conversations/f3b2c1e4-1234-4abc-9def-0123456789ab" \
  -H "Authorization: Bearer zspat_..."
PATCH /admin/api/ai/conversations/{id}

Rename a conversation.

Parameters

Name Type Required Description
id string required Conversation UUID

Request Body

{
  "title": "Q4 promo planning"
}

Response 204

Example

curl -X PATCH "https://yourshop.zeroshop.io/admin/api/ai/conversations/f3b2c1e4-1234-4abc-9def-0123456789ab" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"title": "Q4 promo planning"}'
DELETE /admin/api/ai/conversations/{id}

Delete a conversation and all its messages.

Parameters

Name Type Required Description
id string required Conversation UUID

Response 204

Example

curl -X DELETE "https://yourshop.zeroshop.io/admin/api/ai/conversations/f3b2c1e4-1234-4abc-9def-0123456789ab" \
  -H "Authorization: Bearer zspat_..."
POST /admin/api/ai/conversations/{id}/messages

Append one or more messages to an existing conversation. Typically called after a chat turn to persist the user message and the assistant's reply together.

Parameters

Name Type Required Description
id string required Conversation UUID

Request Body

{
  "messages": [
    {
      "role": "user",
      "content": "Summarise today's orders.",
      "token_count": 8
    },
    {
      "role": "assistant",
      "content": "You had 12 orders today totalling $2,345...",
      "token_count": 180
    }
  ]
}

Response 200

{
  "message_ids": [
    "msg-uuid-1",
    "msg-uuid-2"
  ]
}

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/ai/conversations/f3b2c1e4-1234-4abc-9def-0123456789ab/messages" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"role": "user", "content": "Hi", "token_count": 1}]}'
GET /admin/api/ai/tools

List all MCP tools available to the AI assistant in OpenAI function-calling format. Each tool is scoped to the user's role permissions. Schemas are pre-cleaned for OpenAI and Anthropic compatibility.

Response 200

[
  {
    "type": "function",
    "function": {
      "name": "list_products",
      "description": "List products in the shop, optionally filtered by category or search term.",
      "parameters": {
        "type": "object",
        "properties": {
          "search": {
            "type": "string",
            "description": "Optional case-insensitive search on product name"
          },
          "category_id": {
            "type": "integer",
            "description": "Optional filter by category ID"
          }
        }
      }
    }
  }
]

Example

curl "https://yourshop.zeroshop.io/admin/api/ai/tools" \
  -H "Authorization: Bearer zspat_..."
POST /admin/api/ai/tool-execute

Execute a named MCP tool and return its text output. Tool name normalization is automatic — uppercase names, dotted prefixes, or non-alphanumeric characters are stripped during match. String "true"/"false" values in arguments are coerced to booleans.

Request Body

{
  "tool_name": "list_products",
  "arguments": {
    "search": "winter"
  }
}

Response 200

{
  "result": "Found 3 products matching 'winter':\n- Winter Jacket ($89.99)\n- Winter Boots ($129.99)\n- Winter Scarf ($24.99)",
  "is_error": false
}

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/ai/tool-execute" \
  -H "Authorization: Bearer zspat_..." \
  -H "Content-Type: application/json" \
  -d '{"tool_name": "list_products", "arguments": {"search": "winter"}}'
POST /admin/api/ai/upload

Upload an HTML file or ZIP archive for the AI assistant to read. Single HTML files up to 500 KB are returned as-is. ZIP archives up to 5 MB are scanned; all .html/.htm/.css/.js entries are extracted. Returned files are typically passed back to the assistant as context for theme-porting conversations.

Parameters

Name Type Required Description
file file required HTML file (max 500 KB) or ZIP archive (max 5 MB).

Response 200

{
  "files": [
    {
      "filename": "index.html",
      "content": "<!DOCTYPE html><html>..."
    },
    {
      "filename": "style.css",
      "content": "body { font-family: sans-serif; }"
    }
  ]
}

Example

curl -X POST "https://yourshop.zeroshop.io/admin/api/ai/upload" \
  -H "Authorization: Bearer zspat_..." \
  -F "file=@theme.zip"

We value your privacy

We use cookies for essential site functionality and, with your consent, analytics to understand how our platform is used. No personal data is shared with third parties. See our Privacy Policy for details.