Akteora API docs

The widget: testimonials on any website

One snippet shows a brand's approved testimonials on any page: Shopify, WordPress, Webflow, Squarespace, or HTML you write yourself. It never calls the Akteora API. It reads a static document from Akteora's CDN, so a busy page costs you nothing, and it keeps working even if Akteora's API is down.

The snippet

Create a widget in the dashboard (or with POST /v1/widgets) and paste its snippet:

<div data-akteora-widget="wgt_01J8Z3Y4X5W6V7T8S9R0Q1P2N3" style="height:320px"></div>
<script src="https://cdn.akteora.com/w.js" async></script>

Shopify

In the theme editor, add a Custom Liquid section (or edit a template) and paste the snippet.

WordPress

Add a Custom HTML block and paste the snippet.

Webflow and Squarespace

Use an Embed element (Webflow) or a Code block (Squarespace).

What visitors get

On the free plan, widgets show a small "Collect testimonials with Akteora" link. Paid plans can switch it off (show_attribution: false); on the free plan that request is refused with 402 plan_limit_exceeded.

What a widget shows

Only testimonials that are approved and public, not rejected or deleted, and processed. Nothing else ever reaches the document, however the widget selects:

selection Shows
automatic The brand's newest approvals first; narrowed by tag_ids (any of them) and min_rating
manual Exactly submission_ids, in that order. A pick that is no longer public is skipped

At most max_items (up to 50). fields chooses what each card shows: avatar, name, title, company, rating, date. A field switched off is left out of the published document, not just hidden.

A video appears once its files are published (see Media), a few seconds after approval. When you approve, withdraw, edit or delete, the widget's document is rebuilt within a few seconds, then visitors' browsers may keep their copy for up to a minute.

How the widget changes over time

New layouts, looks and card options will be added. What already works keeps working:

The routes

GET /v1/widgets?brand_id=… A brand's widgets, newest first
POST /v1/widgets Create one. Only brand_id is required
GET /v1/widgets/{id} One widget, with its snippet
PATCH /v1/widgets/{id} Change settings. Within fields, only the fields given change
DELETE /v1/widgets/{id} Delete it. Its document goes within seconds; pages keep an empty box
POST /v1/widgets/preview The document a draft would publish, without saving anything
curl -X POST -H "$AUTH" -H 'content-type: application/json' \
  https://api.akteora.com/v1/widgets \
  -d '{ "brand_id": "brd_…", "layout": "carousel", "fields": { "date": true } }'

The response includes snippet, height, script_url, document_url, and published_at: null until the first publication a few seconds after creation.

The document

If you would rather draw testimonials yourself, read the widget's document_url. It is public, cached, has no credentials and no expiry, and is served with Access-Control-Allow-Origin: *.

{
  "version": 1,
  "widget_id": "wgt_01J8Z3Y4X5W6V7T8S9R0Q1P2N3",
  "generated_at": "2026-09-13T12:00:00.000Z",
  "layout": "carousel",
  "theme": "auto",
  "accent_color": "#0f766e",
  "fields": { "avatar": true, "name": true, "title": true, "company": true, "rating": true, "date": false },
  "attribution": true,
  "brand_name": "Northwind",
  "rating": { "average": 4.8, "count": 12 },
  "items": [
    {
      "kind": "video",
      "name": "Maria Garcia",
      "title": "Head of Operations",
      "company": "Northwind",
      "rating": 5,
      "date": null,
      "text": "It halved our onboarding time.",
      "video_url": "https://cdn.akteora.com/m/7kq2m9xwzr4tn8vbh3jp/video.mp4",
      "audio_url": null,
      "poster_url": "https://cdn.akteora.com/m/7kq2m9xwzr4tn8vbh3jp/poster.jpg",
      "duration_ms": 42000,
      "language": "en",
      "captions": [{ "start_ms": 0, "end_ms": 1800, "text": "It halved our onboarding time." }]
    }
  ]
}

What it promises: