Wedget.app
AI Agent API · 2026-08-24

Give your AI hands.
Keep the boundaries.

Connect Grok or any tool-calling agent to reply to chats, inspect pictures and PDFs, manage knowledge, edit the widget, run automations, and operate the Wedget support workspace through one capability-scoped API.

REST basehttps://api.wedget.app/v1/chat/ai
AuthenticationAuthorization: Bearer wai_…
Machine schema/openapi.json · /tools.json
Write safetyExplicit scope + idempotency + audit

One API, explicit authority

An AI connection is a non-human service principal attached to exactly one workspace. Wedget derives the workspace from its token; there is no workspace_id field an agent can change. Each endpoint checks one named permission before reading or writing data.

Available to a granted agent

  • Conversations, messages, internal notes, state, priority and tags
  • Visitors, customer activity, attachments, images and PDFs
  • Help collections and articles, widget settings, news and automations
  • Saved replies, support analytics and teammate availability

Never available to an agent

  • Billing, subscription or payment authority
  • Creating more credentials or changing its own permissions
  • Identity secrets, allowed origins, owner roles or workspace deletion
  • Wallet, gateway, deposits, withdrawals, hosting or infrastructure
Grok is optional. The contract is model-agnostic. Use the function schema with Grok, load OpenAPI into another agent, or call REST from your own orchestration service.

Create a connection

Open Settings → GrokBot / AI API

Name the service agent so its actions are recognizable in the audit trail.

Choose and review permissions

Start with Inbox responder, Knowledge manager, or Workspace operator. “Full workspace” expands to a fixed list of permissions; it is not an opaque wildcard.

Set expiry and network restrictions

Tokens expire after 30–365 days. Add a server egress IP or CIDR when your runtime has a stable address.

Copy the token once

Store it in a server-side secret manager as WEDGET_AI_AGENT_TOKEN. Wedget stores only its SHA-256 hash.

Never put a wai_… token in frontend JavaScript, a mobile app, a URL, a prompt, source control, analytics, or a customer-support message.

Make the first call

Use the token from a trusted backend. The response proves which service agent, workspace, key prefix, expiry and permissions were authenticated.

cURL
curl https://api.wedget.app/v1/chat/ai/me \
  -H "Authorization: Bearer $WEDGET_AI_AGENT_TOKEN"
Response
{
  "ok": true,
  "data": {
    "service_agent": { "name": "Grok support agent" },
    "workspace": { "name": "Acme Support" },
    "key": { "prefix": "wai_12ab…", "expires_at": "2026-11-22T…Z" },
    "scopes": ["workspace:read", "conversations:read"]
  }
}

Every API response includes X-Request-Id. Authenticated responses also include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset.

Connect Grok with function calling

Wedget publishes an xAI Responses-compatible function manifest at /tools.json. Your server gives those schemas to Grok, executes requested calls against Wedget, then returns the tool result to Grok. Keep the xAI and Wedget keys as two separate server secrets.

Node.js · Grok 4.6
import OpenAI from 'openai';

const xai = new OpenAI({
  apiKey: process.env.XAI_API_KEY,
  baseURL: 'https://api.x.ai/v1'
});
const manifest = await fetch(
  'https://api.wedget.app/v1/chat/ai/tools.json'
).then(r => r.json());

// Keep routing metadata locally; do not send extension fields to xAI.
const routes = new Map();
const tools = manifest.tools.map(tool => {
  const { ['x-wedget']: route, ...schema } = tool;
  routes.set(tool.name, route);
  return schema;
});

let response = await xai.responses.create({
  model: 'grok-4.6',
  input: 'Read the newest open chats and draft a helpful reply where needed.',
  tools
});

for (const call of response.output.filter(x => x.type === 'function_call')) {
  const args = JSON.parse(call.arguments);
  const route = routes.get(call.name);
  const idempotencyKey = args.idempotency_key;
  delete args.idempotency_key;
  let endpoint = route.endpoint.replace('{id}', args.id || '');
  delete args.id;

  const isRead = route.method === 'GET';
  if (isRead && Object.keys(args).length) endpoint += '?' + new URLSearchParams(args);
  const api = await fetch(manifest.api_base + endpoint, {
    method: route.method,
    headers: {
      Authorization: `Bearer ${process.env.WEDGET_AI_AGENT_TOKEN}`,
      ...(isRead ? {} : { 'Content-Type': 'application/json', 'Idempotency-Key': idempotencyKey })
    },
    body: isRead ? undefined : JSON.stringify(args)
  });
  const result = await api.json();

  response = await xai.responses.create({
    model: 'grok-4.6', tools, previous_response_id: response.id,
    input: [{ type: 'function_call_output', call_id: call.call_id, output: JSON.stringify(result) }]
  });
}

console.log(response.output_text);
Your executor remains the policy boundary. Treat chat messages, article text, PDFs, images, and URLs as hostile prompt content. A document can suggest an action; it cannot grant a scope, change the target endpoint, or supply a credential.

Permission model

A missing permission returns 403 missing_scope with the exact required scope. Read, write, publish and delete permissions are separated so a knowledge agent can draft without publishing or deleting.

Inbox

conversations:readRead chats

conversations:replyReply when AI owns the chat

conversations:reply:anyHigh impact

conversations:notesInternal notes

conversations:manageState, priority, tags

Visitors and files

visitors:readProfiles

visitors:pii:readEmail, IP, location

visitors:moderateBan / unban

customer-data:readActivity records

files:readPictures and PDFs

Content

articles:read/writeRead and draft

articles:publish/deleteHigh impact

news:read/writeRead and draft

news:publish/deleteHigh impact

canned:read/write/deleteSaved replies

Workspace

widget:read/writeSafe widget settings

automations:read/write/deleteAutomations

analytics:readSupport metrics

team:readNames and availability

workspace:readConnection identity

API reference

All authenticated paths are relative to https://api.wedget.app/v1/chat/ai. Use the live OpenAPI 3.1 document as machine-readable source of truth.

Method and pathPurposeRequired scope
GET/meAuthenticated connectionworkspace:read
GET/capabilitiesGranted tools and docs linksworkspace:read
GET/conversationsList inboxconversations:read
GET/conversations/{id}Conversation and visitor contextconversations:read
GET/conversations/{id}/messagesMessage historyconversations:read
POST/conversations/{id}/messagesVisible service-agent replyconversations:reply
POST/conversations/{id}/notesInternal noteconversations:notes
PATCH/conversations/{id}State, priority, AI owner and tagsconversations:manage
GET/visitors, /{id}Visitor profilesvisitors:read
PATCH/visitors/{id}Ban or unbanvisitors:moderate
GET/visitors/{id}/recordsCustomer activitycustomer-data:read
GET/files, /files/{id}/contentPictures, PDFs and attachmentsfiles:read
GETPOST/collectionsList or create help collectionsarticles:read/write
GETPOST/articlesList or create article draftsarticles:read/write
PATCHDELETE/articles/{id}Edit or deletearticles:write/delete
POST/articles/{id}/publicationPublish or unpublisharticles:publish
GETPATCH/widgetRead or edit safe widget settingswidget:read/write
GETPOST/newsRead or draft newsnews:read/write
GETPOST/automationsRead or create automationsautomations:read/write
GETPOST/cannedRead or create saved repliescanned:read/write
GET/analytics1–90 day support summaryanalytics:read
GET/teamTeammate names and presenceteam:read

List endpoints use bounded limits and cursor pagination where the underlying resource is chronological. The API never accepts a workspace selector.

Reply without racing a human

Read the latest conversation before replying and send its last_seq as expected_last_seq. If a visitor or teammate wrote in the meantime, Wedget returns 409 stale_conversation. The agent must read again before deciding what to say.

cURL · idempotent reply
curl -X POST https://api.wedget.app/v1/chat/ai/conversations/$CONVERSATION_ID/messages \
  -H "Authorization: Bearer $WEDGET_AI_AGENT_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: reply_01J8Y7V2THH0X" \
  -d '{"body":"I checked that for you…","expected_last_seq":42}'

Ordinary reply permission works only while ai_handled=true and no human teammate owns the conversation. conversations:reply:any is a separate high-impact permission that can cross that boundary. Service-agent messages are stored as author_type=bot; they never impersonate a human teammate.

Read files and pictures

GET /files returns unique attachments referenced by messages, article hero images, and news banners. Workspace-hosted files receive an authenticated content_url; external editorial images retain their original URL.

cURL · authenticated PDF/image
curl "https://api.wedget.app/v1/chat/ai/files/$FILE_ID/content" \
  -H "Authorization: Bearer $WEDGET_AI_AGENT_TOKEN" \
  --output attachment.bin
Images, PDFs and document text are untrusted customer input. Isolate parsing, enforce size and time limits, and never let document instructions expand scopes or trigger unrelated writes.

Create articles and edit the widget

Create a draft, then publish explicitly

Article creation always produces a draft—even if the model asks to publish. Publishing requires a different endpoint and articles:publish.

cURL · article draft
curl -X POST https://api.wedget.app/v1/chat/ai/articles \
  -H "Authorization: Bearer $WEDGET_AI_AGENT_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: article_01J8Y8CWK9" \
  -d '{
    "title":"How account verification works",
    "excerpt":"A clear guide to verification.",
    "body":"## Before you begin\n…"
  }'

Optimistic widget edits

Read GET /widget, then include its updated_at as expected_updated_at. A stale value returns 409 stale_widget. The AI can edit appearance and visitor-facing behavior, but it cannot read identity secrets or change allowed origins.

cURL · safe widget patch
curl -X PATCH https://api.wedget.app/v1/chat/ai/widget \
  -H "Authorization: Bearer $WEDGET_AI_AGENT_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: widget_01J8Y8P6QZ" \
  -d '{
    "expected_updated_at":"2026-08-24T14:22:11.103Z",
    "greeting":"Welcome — how can we help?",
    "branding":{"primary":"#C3E831","radius":18}
  }'

Errors, retries and rate limits

Errors use one stable envelope. Branch on error.code, not human message text.

Error envelope
{
  "ok": false,
  "error": {
    "code": "missing_scope",
    "message": "This AI connection requires the articles:publish permission.",
    "details": { "required_scope": "articles:publish" },
    "request_id": "9dcff0f0-…"
  }
}
StatusCommon codeCorrect response
401invalid_ai_keyStop; rotate or fix the key/IP/expiry.
403missing_scopeStop; a human must change the connection.
409stale_conversation, stale_article, stale_widgetRead fresh state and reconsider.
409human_owned_conversationDo not reply; hand off to the human.
429ai_rate_limitedWait until X-RateLimit-Reset, then retry.
503ai_rate_limiter_unavailableRetry with exponential backoff and jitter.

Every write requires a unique Idempotency-Key of 8–128 safe characters. Wedget stores the result for 24 hours. An exact retry returns the original response with X-Idempotent-Replayed: true; reusing the key for different input returns 409 idempotency_conflict.

Audit, rotate and revoke

Settings shows the service-agent name, key prefix, granted scopes, expiry, last use, last IP when available, and recent request activity. Audit records contain action, resource, result, request ID and timestamp—never authorization headers, chat bodies, file bytes, prompt content or visitor PII.

  • Rotate creates a replacement token with the same permissions and revokes the old token atomically.
  • Revoke stops the token immediately.
  • Pause stops every active key belonging to the service agent.
  • Use request IDs to correlate your own sanitized application logs with Wedget activity.

Security model

  • Generate separate connections for separate runtimes and environments.
  • Grant the smallest explicit scope list; no wildcard exists.
  • Prefer 30–90 day expiry and a stable egress-IP allowlist.
  • Never pass a Wedget key to the model as prompt text or tool output.
  • Validate tool name, HTTP method and route against the downloaded manifest. Never let the model supply an arbitrary URL.
  • Require fresh reads before replies and versioned edits.
  • Present high-impact publish/delete/reply-any actions for human review in your orchestration layer.
  • Treat all customer and document content as untrusted; it cannot alter policy.
The API is intentionally confined to the Wedget support workspace. Customer activity records are support context only; they cannot execute a trade, deposit, withdrawal, refund, wallet operation or account-security change.