Examples
Example scripts for common use cases: add a product from its URL, weekly report, scheduled launch, subscriber backup.
Each example reads the API key from the HOPLA_API_KEY environment variable and fits in a single file. JavaScript examples run on Node.js 20 or later, without dependencies.
Add a product from its URL
Reproduces what the admin panel does when a product URL is pasted: fetch the title, price and photo, upload the photo to Hopla, create the block.
const api = 'https://app.hopla.page/api/v2';
const headers = { Authorization: `Bearer ${process.env.HOPLA_API_KEY}`, 'Content-Type': 'application/json' };
const call = async (method, path, body) => {
const r = await fetch(api + path, { method, headers, body: JSON.stringify(body) });
const json = await r.json();
if (!r.ok) throw new Error(json.error.message);
return json;
};
const url = process.argv[2]; // node add-product.mjs https://boutique.example.com/programme
const { preview } = await call('POST', '/fetch/preview', { url, image: 'share' });
const image = preview.image ? (await call('POST', '/media', { image: preview.image })).media.path : '';
const { block } = await call('POST', '/blocks', { type: 'product', title: preview.title, url, price: preview.price, image });
console.log(`Added "${block.title}", ${block.price || 'no price'}.`);product blocks require the Starter plan or higher.
Weekly report in Slack
Posts the weekly summary and the three most clicked links to a Slack channel every Monday. Requires a Slack incoming webhook URL in SLACK_WEBHOOK. A read-only key is enough.
const get = path => fetch(`https://app.hopla.page/api/v2${path}`, {
headers: { Authorization: `Bearer ${process.env.HOPLA_API_KEY}` },
}).then(r => r.json());
const { summary } = await get('/analytics/summary?period=7');
const { analytics } = await get('/analytics?period=7');
const top = analytics.blocks.toSorted((a, b) => b.clicks - a.clicks).slice(0, 3).map(b => `• ${b.title}: ${b.clicks} clicks`).join('\n');
await fetch(process.env.SLACK_WEBHOOK, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text: `${summary.sentence}\n${top}` }),
});Schedule it every Monday at 9 am with cron (0 9 * * 1 node weekly-report.mjs), a scheduled GitHub Action, or a Make or n8n scenario.
Schedule a launch
A featured link, visible from Monday 9 am to Sunday night, with a countdown before the start. Scheduling requires the Starter plan.
curl -X POST https://app.hopla.page/api/v2/blocks \
-H "Authorization: Bearer $HOPLA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "La masterclass est ouverte",
"url": "https://example.com/masterclass",
"featured": true,
"format": "card",
"startsAt": "2026-11-02T09:00:00+01:00",
"endsAt": "2026-11-08T23:59:00+01:00",
"countdown": true
}'Update a recurring link
A block at the top of the page whose URL changes regularly: latest episode, latest video, current offer. Its id is read from HOPLA_BLOCK_ID.
// node update-link.mjs "Épisode 12 : la reprise" https://example.com/episode-12
const [title, url] = process.argv.slice(2);
const response = await fetch(`https://app.hopla.page/api/v2/blocks/${process.env.HOPLA_BLOCK_ID}`, {
method: 'PATCH',
headers: { Authorization: `Bearer ${process.env.HOPLA_API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ title, url, visible: true }),
});
console.log(response.ok ? 'Link updated.' : (await response.json()).error.message);For a blog, podcast or YouTube channel, the feed and latest-video blocks update automatically, without a script: see Blocks.
Daily subscriber backup
Exports the email list to a dated CSV file every night. A read-only key is enough.
#!/bin/sh
mkdir -p ~/hopla
curl -sf "https://app.hopla.page/api/v2/subscribers?format=csv" \
-H "Authorization: Bearer $HOPLA_API_KEY" \
-o ~/hopla/subscribers-$(date +%F).csvGenerate a QR code for print
SVG scales without quality loss, whatever the print size.
curl "https://app.hopla.page/api/v2/qr-code?format=svg" \
-H "Authorization: Bearer $HOPLA_API_KEY" -o qr-hopla.svg