Documentation

Here is how you integrate askVela into your website, shop, and systems. You can find all keys and URLs in the Dashboard under Settings.

1 · Embed widget

Add this snippet before the closing </body>-tag of your website. You can find the widgetKey under Settings → Embed widget (it determines which workspace the chats belong to).

<script>
  (function (w, d) {
    w.VelaConfig = {
      appUrl: "https://askvela.pro",
      widgetKey: "wk_dein_widget_key"
    };
    var s = d.createElement("script");
    s.src = w.VelaConfig.appUrl + "/widget.js";
    s.async = true;
    d.head.appendChild(s);
  })(window, document);
</script>

Position, brand color, logo, greeting, and proactive message are configured in the Dashboard — no code needed.

2 · Identify visitors (optional)

If a user is logged in, you can pass their name and email directly. This way your team immediately sees who is writing — and the customer data integration (see below) will find matching orders.

w.VelaConfig = {
  appUrl: "https://askvela.pro",
  widgetKey: "wk_dein_widget_key",
  name: "Max Mustermann",
  email: "max@example.com"
};

3 · Connect customer data & orders

In Settings → Customer data & orders a Lookup URL for your shop and optionally a Secret. Once a visitor's email is known, askVela calls your URL and shows the agent the returned data in the inbox.

Request from askVela to your shop

GET https://deinshop.de/api/vela-lookup?email=max@example.com

Header:
  X-askVela-Tenant: <deine Workspace-ID>
  X-askVela-Signature: <HMAC-SHA256(secret, email) als Hex>   # nur wenn Secret gesetzt

Expected response (JSON)

All fields are optional — return what you have.

{
  "customer": {
    "fields": [
      { "label": "Kunde seit", "value": "2023" },
      { "label": "Bestellungen", "value": "7" }
    ]
  },
  "orders": [
    {
      "id": "#1234",
      "status": "Versendet",
      "total": "49,99 €",
      "date": "2024-05-01",
      "url": "https://deinshop.de/orders/1234",
      "paymentIntent": "pi_123...",   // für KI-Erstattungen (Stripe)
      "amountCents": 4999,             // Bestellbetrag in Cent
      "currency": "eur"
    }
  ]
}

For AI refunds additionally supply per order paymentIntent (Stripe payment_intent/charge), amountCents and currency. The bot negotiates in tiers and creates a proposal; payment is only processed after agent approval in the inbox (Stripe key in settings).

Verify signature (recommended)

In your endpoint, verify that the request actually comes from askVela — using the same Secret:

// Node.js / Next.js
import crypto from "crypto";

export async function GET(req) {
  const url = new URL(req.url);
  const email = url.searchParams.get("email") || "";
  const sig = req.headers.get("x-vela-signature");
  const expected = crypto.createHmac("sha256", process.env.VELA_SECRET)
    .update(email).digest("hex");
  if (sig !== expected) return new Response("forbidden", { status: 403 });

  const orders = await db.orders.findByEmail(email); // deine Logik
  return Response.json({
    orders: orders.map(o => ({
      id: o.number, status: o.status, total: o.totalFormatted,
      date: o.date, url: o.adminUrl,
    })),
  });
}
// PHP
$email = $_GET['email'] ?? '';
$sig = $_SERVER['HTTP_X_VELA_SIGNATURE'] ?? '';
$expected = hash_hmac('sha256', $email, getenv('VELA_SECRET'));
if (!hash_equals($expected, $sig)) { http_response_code(403); exit('forbidden'); }
// … Bestellungen laden und als JSON ausgeben
Security: Only return data that your support team is allowed to see. askVela makes the request server-side (not from the browser) and truncates the response to a maximum of 20 orders.

4 · Connect a product catalog

Give the AI product knowledge for purchase advice, price/info questions and product cards in chat. You can maintain products manually in the dashboard (Products) or import them automatically via a product sync URL (Settings → Customer data & orders). On import, askVela calls your URL and creates or updates the products in the catalog (matched by external ID).

Request from askVela to your shop

GET https://deinshop.de/api/vela-products

Header:
  X-askVela-Tenant: <deine Workspace-ID>
  X-askVela-Timestamp: <Millisekunden-Zeitstempel>            # nur wenn Secret gesetzt
  X-askVela-Signature: <HMAC-SHA256(secret, "<tenantId>.<timestamp>") als Hex>

Expected response (JSON)

An array or an object with "products". Only "name" is required — everything else is optional.

{
  "products": [
    {
      "id": "SKU-123",                 // externe ID (für Sync/Updates)
      "name": "Super Duolingo (12 Monate)",
      "description": "Werbefrei, unbegrenzte Leben, …",
      "price": 24.99,                  // Euro-Dezimal – ODER "priceCents": 2499
      "currency": "eur",
      "imageUrl": "https://deinshop.de/img/super.png",
      "url": "https://deinshop.de/p/super-duolingo",
      "category": "Abos",
      "available": true
    }
  ]
}

Price as "price" (euro decimal) OR "priceCents" (cents). "id" serves as the external ID for later updates. Images/URLs must start with http(s).

Verify the signature (recommended)

If a secret is set, askVela signs over "<tenantId>.<timestamp>". Verify it in your endpoint:

// Node.js / Next.js
import crypto from "crypto";

export async function GET(req) {
  const ts = req.headers.get("x-vela-timestamp") || "";
  const tenant = req.headers.get("x-vela-tenant") || "";
  const sig = req.headers.get("x-vela-signature");
  const expected = crypto.createHmac("sha256", process.env.VELA_SECRET)
    .update(tenant + "." + ts).digest("hex");
  if (sig !== expected) return new Response("forbidden", { status: 403 });

  const products = await db.products.findActive(); // deine Logik
  return Response.json({
    products: products.map(p => ({
      id: p.sku, name: p.name, description: p.summary,
      price: p.price, currency: "eur",
      imageUrl: p.image, url: p.url, category: p.category,
      available: p.stock > 0,
    })),
  });
}
Security: askVela calls the URL server-side and imports up to 500 products per sync. Only return product data that can be shown publicly.

5 · Custom Actions (the AI takes action)

Let the AI trigger real operations instead of just advising — e.g. cancel a subscription, change an address, track a shipment. Define the allowed actions under Settings → AI & data → Custom Actions (name, key, parameters, optional approval requirement). When the AI triggers an action, askVela calls your endpoint with a signed request.

Request from askVela to your endpoint

askVela sends the action key and only the defined parameters.

POST https://deinshop.de/api/vela-action

Header:
  X-askVela-Tenant: <deine Workspace-ID>
  X-askVela-Timestamp: <Millisekunden-Zeitstempel>            # nur wenn Secret gesetzt
  X-askVela-Signature: <HMAC-SHA256(secret, "<tenantId>.<timestamp>.<body>") als Hex>

Body:
{
  "action": "cancel_subscription",     // [key] aus deiner Aktions-Definition
  "params": { "orderId": "#1234" },    // nur die definierten Parameter
  "conversationId": "clx…",
  "contact": { "email": "max@example.com" },
  "executionId": "clx…"
}

Expected response (JSON)

Return "ok": true. An optional "message" is shown to the customer in the chat.

{
  "ok": true,
  "message": "Abo zum 31.05. gekündigt."   // optional – wird dem Kunden im Chat angezeigt
}

Verify the signature (recommended)

If a secret is set, askVela signs "<tenantId>.<timestamp>.<body>". Verify it in your endpoint:

// Node.js / Next.js
import crypto from "crypto";

export async function POST(req) {
  const raw = await req.text();
  const ts = req.headers.get("x-vela-timestamp") || "";
  const tenant = req.headers.get("x-vela-tenant") || "";
  const sig = req.headers.get("x-vela-signature");
  const expected = crypto.createHmac("sha256", process.env.VELA_SECRET)
    .update(tenant + "." + ts + "." + raw).digest("hex");
  if (sig !== expected) return new Response("forbidden", { status: 403 });

  const { action, params } = JSON.parse(raw);
  // … Aktion ausführen (z.B. Abo kündigen) …
  return Response.json({ ok: true, message: "Erledigt ✅" });
}
Security: Only run the defined actions and check server-side whether the operation is allowed for this customer. With "requires approval", an agent confirms it in the inbox first.

6 · Outbound webhooks

askVela sends events to your system (CRM, Slack, Zapier, your own backend). Set the URL, an optional secret, and the events you want under Settings → Email & hours → Outbound webhooks (no selection = all events).

Available events

Request from askVela to your system

POST https://deinsystem.de/api/vela-webhook

Header:
  X-askVela-Tenant: <deine Workspace-ID>
  X-askVela-Event: lead.captured
  X-askVela-Timestamp: <Millisekunden-Zeitstempel>
  X-askVela-Signature: <HMAC-SHA256(secret, "<timestamp>.<body>") als Hex>   # nur wenn Secret gesetzt

Body:
{
  "event": "lead.captured",
  "createdAt": "2026-06-05T12:00:00.000Z",
  "tenantId": "clx…",
  "data": { "conversationId": "clx…", "email": "max@example.com" }
}

Verify the signature (recommended)

If a secret is set, askVela signs "<timestamp>.<body>". Verify it using the raw body:

// Node.js / Next.js
import crypto from "crypto";

export async function POST(req) {
  const raw = await req.text();
  const ts = req.headers.get("x-vela-timestamp") || "";
  const sig = req.headers.get("x-vela-signature");
  const expected = crypto.createHmac("sha256", process.env.VELA_SECRET)
    .update(ts + "." + raw).digest("hex");
  if (sig !== expected) return new Response("forbidden", { status: 403 });

  const { event, data } = JSON.parse(raw);
  // … Event verarbeiten (CRM, Slack, …) …
  return Response.json({ ok: true });
}
Security: Respond quickly with 2xx. askVela delivers best-effort (8s timeout) — make processing idempotent based on the event data.

7 · Email notifications (Resend)

So that visitors receive a branded email with a link back to the chat when there are new replies:

  1. Sign up at resend.com and verify your sender domain.
  2. Create an API key.
  3. Under Settings → Email notifications enter the key, sender (From), and reply address (Reply-To).

Emails are only sent when an agent replies while the visitor has closed the chat and an email is on file. Nothing is sent without a key.

No workspace yet?

Get started for free