Base URL
All API requests go to this base URL.Versioning
Build on v1, the endpoints under/api/v1. The original unversioned endpoints (/api/ping and /api/leads) are now the legacy API. They keep working, but they’re frozen and deprecated, so new features and fixes land in v1 only.
Already integrated with the legacy endpoints? See Migrating from the legacy API.
Headers
All requests must include these headers.Partner attribution
If you’re integrating on behalf of a partner, include their public ID in theX-Partner-Id header on pings. Juiced records the ping against that partner when the partner is linked to the source whose credentials you use, so it shows up in their ping logs. Lead posts ignore the header.
Authentication
The API supports two authentication methods.Basic Authentication
Use your source’s API key and secret, Base64-encoded in the formatapi_key:api_secret.
Bearer Token
Use a bearer token generated for your source.Endpoints
Ping-post workflow
The typical integration flow uses both endpoints.- Ping with partial lead data (at minimum, a zip code) to check for matching bids and get pricing.
- Post the full lead with the ping’s
idasping_idif the price is acceptable.
Source-specific fields
The exact fields available (and which ones are required) depend on your source and lead category configuration. The documentation here covers the standard fields, but your source may have additional requirements.For the exact API spec tailored to your source (including your credentials and all configured fields), visit Sources → [Your Source] → View API Spec in your Juiced admin dashboard. If it still shows
/api/ping or /api/leads, use the /api/v1/ paths instead.Safe retries
Network hiccups happen, and a lead you can’t confirm is a lead you’re tempted to send twice. Add atransaction_id to each lead post (your own order or lead number works well, up to 255 characters) and retries become safe. Transaction IDs are scoped to the source sending them, and test-mode posts are tracked separately from live ones.
- Same
transaction_id, same payload returns the original status and body again, without creating another lead. - Same
transaction_id, different payload returns409(idempotency_conflicton v1). - The first attempt is still processing returns
409with aRetry-Afterheader (idempotency_in_progresson v1). Wait and send the same request again. - The outcome couldn’t be confirmed returns
409(idempotency_reservedon v1). The lead may already have been delivered, so don’t resubmit it. It’s held for review.
transaction_id, so you can fix the payload and send it again with the same ID. A lead rejected for not matching its ping was still recorded, so its transaction_id stays taken.
Rate limits
The API accepts up to 240 requests a minute, counting pings and leads together. Past that, it returns429 with a Retry-After header giving the seconds to wait (rate_limited on v1).
Test mode
Turn on test mode from the source’s edit form to try your integration. While it’s on, these zip codes return fixed outcomes on both pings and posts.00001 is priced at 25 dollars and 00005 at 15, on both the ping and the lead. The other zips are priced at 0. Vendor sources get the ping price as price. Other sources get a single bid named Test Mode at that price on 00001 and 00005, and an empty bids list on the other zips. Lead statuses assume the source’s default status responses mapping.
With any other zip, pings are matched as usual (including pings to your partners), and leads are marked as test data and never distributed. Those leads are moved to Audit unless they’re duplicates or can’t be categorized. Stick to the zips above while you build, and turn test mode off before going live.
Errors
The API uses standard HTTP status codes. A ping that passes validation always returns200. A lead that passes validation returns 201 whatever its outcome, unless it doesn’t match its ping (422). Check the status in the body for the outcome.
Every v1 error uses the same envelope. Branch on error.code, which is stable, rather than on message.
Request IDs
Every v1 response, errors included, carries anX-Request-Id header such as req_01jbx8k6y3a5c7e9g1j3m5p7rt. Log it with your request, and quote it when you contact support so we can find the exact request.
Migrating from the legacy API
Deprecation headers
Every legacy ping and lead response carries two headers that announce its replacement.Deprecation is the date the legacy API was deprecated, as @ plus a Unix timestamp (RFC 9745). Link points to the v1 endpoint that replaces the one you called. There’s no Sunset header yet, which means no shutdown date has been set.
Moving from legacy to v1
- Change the path from
/api/pingto/api/v1/pingand from/api/leadsto/api/v1/leads. Credentials and field names stay the same, but ID values change (steps 2 and 4). - Read results from
data. A ping’sping_idandmessagebecomedata.idanddata.status, and itsprice(vendors) orbidsmove underdatatoo. A lead’slead_public_idandstatusbecomedata.idanddata.status, andlead_uuidis gone. Each bid’sid,customer_idandpartner_idbecome public IDs. - Update the values you compare against. Ping messages become
matched,no_match,duplicateandrejected, and the lead statussuccessbecomesaccepted. - Send the v1 ping’s
data.idasping_idon the lead and, if you echo a bid, itsbids[].idasbid_id. v1 rejects the UUIDs the legacy API returns, so post a legacy ping’s lead to the legacy API. - Handle errors by
error.coderather than by message.
Legacy errors
The legacy endpoints keep their original error bodies. Validation errors return422 with a message and an errors object keyed by field. Transaction conflicts (409) and a lead that doesn’t match its ping return a single error string. Everything else returns a message. See Submit a Lead (Legacy) for every legacy response.
