One base URL, one header, 9 endpoints. Everything is a GET request and everything answers in the same shape.
base url · https://sensecollect.com
Create a key in the dashboard, then send it as x-api-key. Nothing else is required — no SDK, no OAuth, no per-source credentials.
curl "https://sensecollect.com/v1/maps/search?query=dentists&location=Berlin&limit=25" \
-H "x-api-key: $SENSECOLLECT_KEY"Keys look like sc_live_… and are shown once at creation. Send them in the x-api-key header, or as a bearer token if that fits your client better. Revoking a key in the dashboard takes effect on the next call.
x-api-key: sc_live_YOUR_KEYAuthorization: Bearer sc_live_YOUR_KEYEvery data endpoint answers with the same envelope, and every item in data uses the same record shape regardless of source. Fields a source cannot fill come back empty rather than missing, so your parser never branches on source.
{
"success": true,
"request_id": "req_9f2a…",
"status": "completed",
"source": "google_maps",
"endpoint": "/v1/maps/search",
"job_id": "6c1f…",
"credits_used": 5,
"credits_remaining": 295,
"count": 50,
"data": [ … ]
}{
"id": "ChIJ0xT4…",
"type": "place" | "review" | "post",
"source": "google_maps" | "amazon_reviews" | "tiktok",
"title": "Mitte Dental Studio",
"url": "https://maps.google.com/…",
"content": "Dentist",
"published_at": "2026-05-02T09:14:00.000Z" | null,
"author": { "name": "", "handle": "", "url": "" },
"contact": { "phone": "", "email": "", "website": "" },
"location": { "address": "" },
"metrics": { "rating": 4.6, "reviews": 42 },
"raw": { … original source fields … }
}The same catalog is available as JSON at GET /v1/sources, with no key required.
Every business a map search returns for a niche and place, enriched with the contact fields you need to actually reach them.
/v1/maps/searchfrom 5 creditsBusinesses matching a query and location, with phone, email, website, rating, and review count.
querystringrequiredlocationstringlimitintegerenrichbooleanhttps://sensecollect.com/v1/maps/search?query=dentists&location=Berlin&limit=50
/v1/maps/no-websitefrom 5 creditsThe same search, pre-filtered to businesses with no website on file — the standard web-design lead list.
querystringrequiredlocationstringlimitintegerhttps://sensecollect.com/v1/maps/no-website?query=restaurants&location=Hamburg
Reviews for any public ASIN as flat records — rating, text, date, reviewer — ready for sentiment work or objection mining.
/v1/amazon/reviewsfrom 12 creditsReviews for one or more ASINs in the unified record shape.
asinstringrequiredlimitintegerhttps://sensecollect.com/v1/amazon/reviews?asin=B09G9FPHY6&limit=25
/v1/amazon/complaintsfrom 12 creditsThe same run, filtered server-side to 1- and 2-star reviews so you get the complaints without paging the rest.
asinstringrequiredlimitintegerhttps://sensecollect.com/v1/amazon/complaints?asin=B09G9FPHY6
Posts for a hashtag or topic with creator, caption, and engagement counts — the raw material for trend and creator research.
/v1/tiktok/hashtagfrom 15 creditsPosts for one or more hashtags, with plays, likes, comments, and shares.
hashtagstringrequiredlimitintegerhttps://sensecollect.com/v1/tiktok/hashtag?hashtag=fitnesscoach&limit=100
/v1/tiktok/searchfrom 15 creditsGive it a plain-language topic; SenseCollect resolves the hashtags and returns the posts.
querystringrequiredlimitintegerhttps://sensecollect.com/v1/tiktok/search?query=ai%20fitness%20coaches
Balance, catalog, and job polling. These never cost credits, so you can wire up monitoring without paying for it.
/v1/accountfreeRemaining credits and the email the key belongs to.
https://sensecollect.com/v1/account
/v1/sourcesfreeMachine-readable list of every source, endpoint, parameter, and price.
https://sensecollect.com/v1/sources
/v1/jobs/{id}freeFetch a run started with async=true, or one that outlived the synchronous request budget.
idstringrequiredhttps://sensecollect.com/v1/jobs/6c1f…
Collection happens against the live source, so a large pull can take longer than one HTTP request. Pass async=true to get a job id immediately, then poll /v1/jobs/{id}. A synchronous call that outlives its request budget returns the same 202 body, so a single code path handles both.
curl "https://sensecollect.com/v1/tiktok/hashtag?hashtag=fyp&limit=500&async=true" \
-H "x-api-key: $SENSECOLLECT_KEY"{
"success": true,
"status": "running",
"job_id": "6c1f…",
"poll_url": "/v1/jobs/6c1f…",
"credits_used": 15
}Errors keep the envelope and add a machine-readable code. When a run fails upstream, the credits are already back on your account by the time you read the response.
| code | status | meaning |
|---|---|---|
| missing_api_key | 401 | No key on the request. |
| invalid_api_key | 401 | Unknown or revoked key. |
| invalid_request | 400 | A required parameter is missing or unusable. |
| insufficient_credits | 402 | The call costs more than the account has left. |
| not_found | 404 | No such run on this account. |
| upstream_failed | 502 | The source run failed. Credits refunded. |
| internal_error | 500 | Something broke on our side. |
Credits are deducted when a run starts and refunded in full if it fails. Every response carries credits_used and credits_remaining, and GET /v1/account reports the balance for free.