Vicket Documentation

API Endpoints

Last updated March 8, 2026

Use the Vicket public support API directly without the scaffold package.

The recommended way to integrate support pages is the scaffold package (npx @vicket/create-support). However, if you prefer to build your own UI or integrate from a stack not covered by the templates, you can call the public support API directly.

Authentication

All endpoints live under /api/v1/public/support and require a website API key sent via the X-Api-Key header.

curl -H "X-Api-Key: YOUR_WEBSITE_API_KEY" \
     https://api.vicket.app/api/v1/public/support/init

Never expose your API key in client-side code. Route calls through a server-side proxy (BFF) that injects the key.

Endpoints

Initialize support page

Retrieves templates, articles, FAQs, and website info in a single call.

GET /api/v1/public/support/init

Rate limit: 30 requests/minute per website.

Response:

{
  "success": true,
  "data": {
    "website": { "name": "My App" },
    "templates": [
      {
        "id": "tpl_...",
        "name": "Bug Report",
        "description": "Report a bug",
        "questions": [
          {
            "id": "q_...",
            "label": "Describe the issue",
            "type": "TEXTAREA",
            "required": true,
            "order": 1,
            "options": []
          }
        ]
      }
    ],
    "articles": [
      { "id": "art_...", "title": "Getting Started", "slug": "getting-started", "content": "<p>...</p>" }
    ],
    "faqs": [
      { "id": "faq_...", "question": "How do I reset my password?", "answer": "Go to..." }
    ]
  }
}

Create a ticket

POST /api/v1/public/support/tickets

Rate limit: 10 requests/minute per website.

JSON body (no file uploads):

{
  "email": "user@example.com",
  "title": "Cannot log in",
  "templateId": "tpl_...",
  "answers": {
    "q_1": "I see a blank page",
    "q_2": "Chrome 120"
  }
}

Multipart body (with file uploads):

Send a multipart/form-data request with:

  • A data field containing the JSON payload (same structure as above, with "__isFile:true" as the value for file questions)
  • File fields named files[QUESTION_ID] for each uploaded file

Response (201):

{
  "success": true,
  "data": {
    "email_limit_reached": false,
    "warning": null
  }
}

Get ticket thread

Retrieves a ticket with its messages, attachments, and form answers.

GET /api/v1/public/support/ticket?token=SECURE_TOKEN

Rate limit: 30 requests/minute per website.

The token is the secure access token sent to the reporter via email when the ticket is created.

Response:

{
  "success": true,
  "data": {
    "id": "tick_...",
    "title": "Cannot log in",
    "status": { "label": "Open" },
    "priority": { "label": "Low" },
    "messages": [
      {
        "id": "msg_...",
        "content": "<p>I see a blank page</p>",
        "author_type": "reporter",
        "created_at": "2026-03-08T10:00:00Z",
        "attachments": []
      }
    ],
    "answers": [
      {
        "id": "ans_...",
        "question_label": "Browser",
        "answer": "Chrome 120",
        "attachments": []
      }
    ]
  }
}

Error codes:

  • ticket-link-expired (410): The token has expired. A new link is automatically sent to the reporter.

Reply to a ticket

POST /api/v1/public/support/ticket/messages?token=SECURE_TOKEN

Rate limit: 10 requests/minute per website.

JSON body (no attachments):

{
  "content": "Thanks, I will try clearing my cache."
}

Multipart body (with attachments):

Send a multipart/form-data request with:

  • A data field containing { "content": "..." }
  • File fields named files for each attachment

Response (201):

{
  "success": true,
  "data": {
    "id": "msg_...",
    "content": "Thanks, I will try clearing my cache.",
    "author_type": "reporter",
    "created_at": "2026-03-08T12:00:00Z"
  }
}

Get a public article

GET /api/v1/public/support/articles/{slug}

Returns a published article by its slug.

Response:

{
  "success": true,
  "data": {
    "id": "art_...",
    "title": "Getting Started",
    "slug": "getting-started",
    "content": "<p>...</p>"
  }
}

Error format

All error responses follow the same structure:

{
  "success": false,
  "error": "Human-readable message",
  "error_code": "machine-readable-code"
}

Common HTTP status codes: 400 (validation), 401 (invalid token/key), 410 (expired link), 429 (rate limit).

Question types

Template questions returned by /init use these type values:

TypeExpected answer value
TEXTString
TEXTAREAString
SELECTString (selected option value)
CHECKBOXBoolean
DATEISO date string
FILEFile upload (use multipart)

On this page