endcap
Log in Sign up

Guide

Everything you need to actually use Endcap, whether you run the marketplace or you're advertising on one.

Getting your account

Two ways to get one, depending on which applies to you:

Logging in

Go to /login, enter your email and password, and you'll land on your dashboard. Password reset exists as an API call, but outgoing email isn't configured on this account yet, so a reset link won't actually arrive — if you're locked out, contact whoever owns your account directly for now.

Your dashboard

After logging in you'll see:

Roles

RoleCan do
OwnerEverything: products, placements, campaigns, team members, billing, privacy requests, refunds.
ViewerSee everything an owner can see. Can't change anything.
AdvertiserCreate and manage only their own campaigns, and browse the product catalogue. No access to placements, billing, or other people's campaigns.

Using the API

There's no web interface yet for the things below — the API is the only way to do them today. Every request needs:

Authorization: Bearer YOUR_API_TOKEN
Accept: application/json
X-Tenant-Id: YOUR_TENANT_ID

X-Tenant-Id is only required if you belong to more than one marketplace — find both values on your dashboard.

One thing that trips people up: money amounts are always in minor units — pence, not pounds. £2.50 is 250.

Viewing your campaigns

curl https://endcap.co.uk/api/v1/campaigns \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Creating a campaign

Owners can create a campaign for anyone; advertisers always create one for themselves, regardless of what they submit.

curl -X POST https://endcap.co.uk/api/v1/campaigns \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Spring Sale",
    "advertiser_id": "acme-corp",
    "bid_minor": 25,
    "daily_budget_minor": 5000,
    "total_budget_minor": 100000,
    "currency": "GBP",
    "starts_at": "2026-09-08T00:00:00Z",
    "product_ids": ["<product-uuid>"]
  }'

That example bids 25p per click, capped at £50/day and £1,000 total.

Checking performance

curl https://endcap.co.uk/api/v1/reports/campaigns/CAMPAIGN_ID \
  -H "Authorization: Bearer YOUR_API_TOKEN"

Returns impressions, clicks, and spend, broken down by day.

Adding products to your catalogue (owners only)

curl -X POST https://endcap.co.uk/api/v1/products \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "sku-1234",
    "title": "Wireless Headphones",
    "vendor_id": "acme-corp",
    "url": "https://yourmarketplace.com/products/sku-1234",
    "price_minor": 4999,
    "currency": "GBP"
  }'

Setting up a placement (owners only)

A placement is a spot on your site where sponsored listings can appear — a search page, a category page, and so on.

curl -X POST https://endcap.co.uk/api/v1/placements \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"key": "search-results", "name": "Search results page", "maximum_ads": 3}'

Inviting people onto your account (owners only)

curl -X POST https://endcap.co.uk/api/v1/tenant-users \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Jane Smith", "email": "jane@example.com", "role": "advertiser"}'

role is one of owner, viewer, or advertiser. A brand-new email address gets sent a link to set their password — again, this needs outgoing email configured to actually arrive.

Refunding an invalid click (owners only)

curl -X POST https://endcap.co.uk/api/v1/ledger-entries \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type": "refund", "ad_event_id": 12345, "currency": "GBP", "reason": "Suspected bot traffic"}'

This reverses the charge, restores that campaign's budget by the same amount, and marks the click as refunded so it can't be refunded twice. One current gap: there's no listing endpoint yet that shows you individual ad_event_id values to find one — for now that needs a direct look at the data. Worth asking for if you'll use this regularly.

Embedding sponsored listings on your site

Once you have a placement and at least one active campaign, add this to your site:

<script src="https://endcap.co.uk/sdk.js"></script>
<script>
  const listings = new SponsoredListings({
    endpoint: 'https://endcap.co.uk',
    publisherKey: 'YOUR_PUBLISHER_KEY',
  });

  listings.request({ placement: 'search-results', query: 'running shoes', limit: 3 })
    .then(({ ads }) => {
      const container = document.querySelector('#sponsored-slot');
      ads.forEach(ad => listings.render(container, ad));
    });
</script>

render() gives you a plain, clearly-labelled "Sponsored" link — enough to get started. To show a product image or price instead, read the fields directly off each adtitle, url, image_url, price_minor, currency — and build your own markup rather than calling render().

By default, no visitor identifier is collected at all. If you want click measurement tied to a pseudonymous visitor ID instead, pass consentBasis: 'consent' and your own visitorId — but only once you've established a proper lawful basis, and consent where PECR requires it. See the Privacy & Cookie Notice.

Billing

Subscribing

curl -X POST https://endcap.co.uk/api/v1/billing/checkout \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"plan": "monthly"}'

plan is monthly or annual. The response includes a checkout_url — open it in a browser to enter payment details with Stripe.

Check your status any time with GET /api/v1/billing/subscription (also shown on your dashboard). Cancel with POST /api/v1/billing/cancel — this takes effect at the end of your current billing period, not immediately. If a payment fails, campaign and product management pauses until it's resolved, but your existing data stays visible the whole time.

Privacy requests

If someone asks you to access or delete the data Endcap holds about them (owners only):

curl -X POST https://endcap.co.uk/api/v1/privacy-requests \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type": "delete", "visitor_id": "their-visitor-id"}'

This doesn't act on anything yet — it sits pending until you've confirmed the person's identity yourself, outside Endcap, and then call:

curl -X PATCH https://endcap.co.uk/api/v1/privacy-requests/REQUEST_ID/verify \
  -H "Authorization: Bearer YOUR_API_TOKEN"

Only then is it actually processed.

What's not built yet

Being upfront about the current limits, rather than leaving you to discover them the hard way: