Using the public API

Automate MartechFlow with the versioned public API: authenticate with a bearer key, list feeds, read runs and exports, trigger refreshes, and handle pagination and rate limits.

Using the public API

Basics: base URL and authentication

The public API is versioned and lives under /api/v1. Authenticate every request with your API key as a bearer token in the Authorization header. There is no separate login step for the API.

A key authenticates as your whole organization, so every endpoint operates on your org's feeds. Read endpoints need a read (or read-and-write) key; the refresh endpoint needs a read-and-write key.

  1. 1Create an API key in Settings (see Create an API key).
  2. 2Send it on every request as: Authorization: Bearer mtf_live_...
  3. 3Call endpoints under https://your-base-url/api/v1/.

Endpoints

The surface is intentionally small and stable, decoupled from internal changes so your integration does not break when we evolve the database.

  • GET /api/v1/feeds: list your org's feeds (paginated). Each feed includes id, name, status, schedule (cron, or null for manual), project_id, and timestamps.
  • GET /api/v1/feeds/:id: one feed's details.
  • GET /api/v1/feeds/:id/runs: the feed's run history with status, trigger, product stats, error, and timing.
  • GET /api/v1/feeds/:id/exports: the feed's output feeds, each with its channel, format, status, item count, last-built time, and the stable public pull URL channels fetch.
  • POST /api/v1/feeds/:id/refresh: trigger a refresh (re-ingest). Requires a write key. Returns 202 Accepted with the queued feed id.

Example requests

List feeds:

  • curl -H "Authorization: Bearer mtf_live_xxx" https://your-base-url/api/v1/feeds
  • Read a feed's exports (to get pull URLs): curl -H "Authorization: Bearer mtf_live_xxx" https://your-base-url/api/v1/feeds/FEED_ID/exports
  • Trigger a refresh (needs a write key): curl -X POST -H "Authorization: Bearer mtf_live_xxx" https://your-base-url/api/v1/feeds/FEED_ID/refresh

Pagination

The feeds list is cursor-paginated. Pass an optional limit (default 50, maximum 200) and an opaque cursor. The response includes a nextCursor; pass it back as the cursor to get the next page, and stop when nextCursor is null.

Cursors are opaque keyset tokens, not page numbers. Do not construct or parse them yourself; just echo back the nextCursor value you received.

  • First page: GET /api/v1/feeds?limit=100
  • Next page: GET /api/v1/feeds?limit=100&cursor=THE_NEXT_CURSOR
  • A tampered or invalid cursor returns an empty page rather than an error.

Rate limits and scopes

Each key is rate-limited per fixed one-minute window (600 requests per minute by default). Exceeding it returns 429 Too Many Requests with a Retry-After header telling you how many seconds until the window resets. Back off and retry after that.

Operation access is enforced by scope: a read-only key calling a write endpoint gets 403 Forbidden. Hitting a write endpoint that your key supports but with a missing or invalid key returns 401 Unauthorized.

  • 401 Unauthorized: missing, invalid, expired, or revoked key.
  • 403 Forbidden: the key lacks the scope for that operation (for example a read key calling refresh).
  • 404 Not Found: the feed id is not in your organization or does not exist.
  • 429 Too Many Requests: rate limit hit; honor Retry-After.

Behavior to expect

A refresh you trigger via the API is a manual run; it appears in run history with a manual trigger and does not change the feed's schedule. It is queued and processed asynchronously, which is why it returns 202 rather than waiting for the refresh to finish.

Triggering a refresh updates your output files at their stable pull URLs, but the ad channels still fetch on their own schedule. The API refreshes your data; the channels decide when to pull it. Refreshing the same feed repeatedly does not stack up duplicate work at the queue level.

Questions

How do I authenticate?

Send your API key as a bearer token on every request: Authorization: Bearer mtf_live_.... Create the key in Settings first. There is no cookie or session for the API.

Why am I getting a 403 when I try to refresh a feed?

The refresh endpoint requires a read-and-write key. A read-only key can list and read but cannot trigger refreshes, so it returns 403 Forbidden. Create a write key for automation that refreshes feeds.

What is the rate limit?

By default 600 requests per minute per key, in a fixed one-minute window. Over the limit you get 429 with a Retry-After header. Wait the indicated seconds and retry.

How does pagination work?

The feeds list uses an opaque cursor. Request with limit (up to 200), read nextCursor from the response, and pass it back as cursor for the next page. Stop when nextCursor is null. Do not build cursors by hand.

Does an API refresh push my feed to Google or Meta instantly?

No. A refresh rebuilds your output files at their stable pull URLs. The channels fetch those URLs on their own cadence, so the new data goes live when the channel next pulls.

Where do I get the pull URL for a channel?

Call GET /api/v1/feeds/:id/exports. Each export includes its stable public pull URL along with its channel, format, status, and item count.

Ready to try it?

Start free, no credit card. Your first feed can be live in minutes.

Start free