UpWolf Developers

Connect your portal to UpWolf

You expose a small read-only JSON feed of your listings. UpWolf reads it, writes the ad, renders the creative, launches the campaign on Meta — and switches it off when the listing is filled. Nothing is pushed to you, nothing runs on your servers.

1You expose a feed Two endpoints are enough to start: what is live, and the detail of one listing.
2We read it on a schedule Pull only, every few minutes. You never call us, though you can if you want it faster.
3Creative and campaign Ad copy and image are generated from your text, then the campaign goes live on your ad account.
4And it stops itself Listing closed or filled up? The campaign pauses within minutes instead of spending the rest of the budget.

See it working in one command

A reference feed that satisfies the whole contract runs on this domain. Point curl, your browser or your own client at it — and later point your own implementation at the validator to see how far you got.

shell
# co je právě teď živé
curl -s "https://upwolf.com/dev/sandbox/feed/offers" \
  -H "Authorization: Bearer sandbox-demo-token"

# detail jedné nabídky
curl -s "https://upwolf.com/dev/sandbox/feed/offers/DEMO-1001" \
  -H "Authorization: Bearer sandbox-demo-token"
php
<?php
$ch = curl_init('https://upwolf.com/dev/sandbox/feed/offers/DEMO-1001');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['authorization: Bearer sandbox-demo-token'],
]);
$offer = json_decode(curl_exec($ch), true);

echo $offer['name'], ' — ', $offer['company']['name'], "\n";
javascript
const res = await fetch('https://upwolf.com/dev/sandbox/feed/offers/DEMO-1001', {
  headers: { authorization: 'Bearer sandbox-demo-token' },
});
const offer = await res.json();

console.log(offer.name, '—', offer.company.name);

Five endpoints, and you can ship them one at a time

Two are required — without them there is nothing to advertise. The rest decide how well the campaigns work, and each one has a written consequence when it is missing. While you are still building an endpoint, answer 404: we treat that as "not implemented yet", detect what exists and degrade the rest.

Endpoint Level What it gives us Without it
GET offers required Everything that is live right now, in one response. Nothing works without it.
GET offers/{external_id} required Everything needed to write the ad and aim it. Nothing works without it.
GET offers?updated_since={iso8601}&page={n} recommended Which offers changed since a given moment — identity and version only. Creative is never refreshed after an offer is edited.
GET campaign-candidates?updated_since={iso8601}&page={n} recommended Which offers should get a campaign, with what budget and for how long. No campaign is ever created automatically — every one has to be pushed to our API or created by hand.
GET offers/{external_id}/applications-stats?from={iso8601} recommended How many responses an offer collected since a given moment. Campaigns run for the full window and spend the whole budget even on offers that were filled long ago, and the guard that skips campaigns for offers filling up organically never fires.

Building it with an AI tool?

Then hand it the machine-readable contract instead of this page. All three describe exactly what the sandbox above returns, because they are generated from the same definition.

shell
# celý kontrakt v jednom souboru (konvence, endpointy, pole, degradace)
curl -s https://upwolf.com/dev/feed.md

# OpenAPI 3.1
curl -s https://upwolf.com/dev/openapi.json

# JSON Schema jednotlivých zdrojů
curl -s https://upwolf.com/dev/schema/Offer

What to do next

One thing we cannot read from a feed: which listings should actually get money spent on them. That is your business decision, and it travels in the campaign candidates endpoint. Everything else we can work out ourselves.