Get Started

From zero to your first ReelPlus API call in 5 minutes. Get a key, call the sandbox, read the funnel, handle limits, then go to production.


No store, no sales call. Everything on this page runs against the public sandbox: a demo store with 120 days of video, widget and order data. When you are done you will have pulled the store's funnel, found its best-selling videos, and seen how the API behaves when you push it too hard.

Get a key

Two ways in, both free:

Your own keyThe shared demo key
HowSign in with GitHub at the Developer Console, click Create keyCopy it from here
Rate limit60 requests per minute, yours alone60 per minute, shared with everyone
Usage pageEvery call, per endpoint, with status and latencyNo
RevokeAny time, from the consoleNever

The demo key, if you want to skip the sign-in:

rp_653f0a33f2bbf185566e8e9a11651a4fd3cfc5fe10c1694eef4d54b830c2d2cf

Keys start with rp_ and are sent as a Bearer token. The full key is shown once at creation; the console keeps only the first 12 characters and a hash.

Make your first call

The summary endpoint returns the store's whole funnel for the last 30 days. Replace the key with your own if you created one. No terminal at hand? The console playground sends the same request from the browser with your key and shows the response, the headers and the matching curl.

curl https://help.reelplus.app/api/v1/analytics/summary \
  -H "Authorization: Bearer rp_653f0a33f2bbf185566e8e9a11651a4fd3cfc5fe10c1694eef4d54b830c2d2cf"
const API_KEY = "rp_653f0a33f2bbf185566e8e9a11651a4fd3cfc5fe10c1694eef4d54b830c2d2cf";

const res = await fetch("https://help.reelplus.app/api/v1/analytics/summary", {
  headers: { Authorization: `Bearer ${API_KEY}` },
});
const { data, meta } = await res.json();
console.log(`${data.orders} orders, ${data.revenue} revenue since ${meta.start_date}`);
import requests

API_KEY = "rp_653f0a33f2bbf185566e8e9a11651a4fd3cfc5fe10c1694eef4d54b830c2d2cf"

res = requests.get(
    "https://help.reelplus.app/api/v1/analytics/summary",
    headers={"Authorization": f"Bearer {API_KEY}"},
)
body = res.json()
print(body["data"]["orders"], "orders,", body["data"]["revenue"], "revenue")

You get a 200 and this shape (your numbers will differ):

{
  "success": true,
  "data": {
    "impressions": 58700,
    "views": 15066,
    "clicks": 2046,
    "add_to_cart": 478,
    "orders": 145,
    "revenue": 21563.2,
    "ctr": 13.58,
    "cvr": 0.96
  },
  "meta": {
    "start_date": "2026-09-29T15:11:25.778Z",
    "end_date": "2026-10-29T15:11:25.778Z"
  }
}

Read the funnel

The eight numbers are one funnel, in order. Each step can only be reached through the one before it, so the numbers always shrink from left to right.

FieldMeaning
impressionsA widget was loaded on a page
viewsA video started playing
clicksA shopper clicked a product inside a video
add_to_cartA product was added to the cart from a video
ordersOrders attributed to a video interaction
revenueThe value of those orders, in the store currency
ctrclicks / views × 100
cvrorders / views × 100

Narrow the window with start_date and end_date (YYYY-MM-DD). The range you actually got is echoed back in meta, so a dashboard can label the tile correctly.

Find the videos that sell

The same funnel exists per video and per widget. This is the call behind "which video did the work":

curl "https://help.reelplus.app/api/v1/analytics/videos?sort_by=revenue&sort_order=desc&limit=5" \
  -H "Authorization: Bearer rp_653f0a33f2bbf185566e8e9a11651a4fd3cfc5fe10c1694eef4d54b830c2d2cf"

Each item carries the video (title, thumbnail, duration, tagged products) and its own metrics object. Lists are paginated: walk page=2, page=3, … until pagination.page equals pagination.total_pages. sort_by accepts views, clicks, impressions, add_to_cart, orders, revenue, title and created_at; anything else is a 400, not a silent default.

Swap videos for widgets to compare placements instead (the home carousel against the product page player), with widget_type=carousel|story|floating|productpage as a filter.

Handle limits and errors

Every authenticated response tells you where you stand:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 41
X-RateLimit-Reset: 1793286741

Past 60 requests in a minute you get 429 with Retry-After in seconds. Wait that long and retry; never retry a 401 (bad header) or 403 (unknown or revoked key), they need a fix on your side. Every error has the same envelope:

{ "success": false, "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Rate limit exceeded. Try again in 12 seconds." } }

Try it: send the first call above with the key changed to rp_wrong and you get 403 INVALID_API_KEY; drop the header and you get 401 UNAUTHORIZED. The full list of codes and a retry function in JavaScript and Python are in Errors & Rate Limits.

Go to production

Production API access is enabled per store on Enterprise plans, on request. Once it is enabled, keys are generated in Settings > API Access in the ReelPlus dashboard and the base URL is provided with the access. The contract is the one you just used; only the data becomes your store's.

A complete example: the Monday digest

Twenty lines that print the five best-selling videos of the last 7 days. Save as digest.mjs and run node digest.mjs.

const API_KEY = "rp_653f0a33f2bbf185566e8e9a11651a4fd3cfc5fe10c1694eef4d54b830c2d2cf";
const BASE = "https://help.reelplus.app/api/v1";

const end = new Date();
const start = new Date(end.getTime() - 7 * 24 * 60 * 60 * 1000);
const range = `start_date=${start.toISOString().slice(0, 10)}&end_date=${end.toISOString().slice(0, 10)}`;

const res = await fetch(`${BASE}/analytics/videos?${range}&sort_by=revenue&limit=5`, {
  headers: { Authorization: `Bearer ${API_KEY}` },
});
if (!res.ok) {
  const { error } = await res.json();
  throw new Error(`${res.status} ${error.code}: ${error.message}`);
}

const { data } = await res.json();
console.log(`Top videos, last 7 days (${res.headers.get("X-RateLimit-Remaining")} requests left this minute)`);
for (const [i, v] of data.entries()) {
  console.log(`${i + 1}. ${v.title}: ${v.metrics.orders} orders, ${v.metrics.revenue.toFixed(2)} revenue`);
}

From here, the two things people usually do next: pipe this into a Slack message, or drop the numbers into a Google Sheet next to ad spend.

Something in these docs does not match what the API returned? That is a bug on our side. Every promise on these pages is checked against the sandbox by an automated test before a deploy; tell us which one slipped.