channel=phone to the REST unlock endpoint
for an explicit phone lookup, and poll email_unlocked or phone_unlocked
for the requested channel. One contact uses one monthly unlock, even when both channels are requested.
This allowance is shared with investor email unlocks in the app. Existing contact access is preserved.
Reference
Synal REST API
A read-and-unlock JSON API over the funding events feed. All endpoints live under
/api/v1 and return JSON.
Base URL
https://app.synal.to/api/v1/funding_events
Authentication
Every request must include your secret API token as a bearer token in the
Authorization header. Grab or rotate your key on the
API key page after signing in.
curl -H "Authorization: Bearer YOUR_API_KEY" \ https://app.synal.to/api/v1/funding_events
A missing or unknown token returns 401 Unauthorized with
{ "error": "Invalid or missing API token" }.
Endpoints
/api/v1/funding_events
Latest funding events, newest first, paginated. Each event includes a
contacts_count so you can see which companies have
decision-maker contacts available.
Query parameters
page— page number (default1).per_page— results per page (default50, max100).
Response
{
"data": [
{
"id": 123,
"company_name": "Acme Inc",
"round": "Series A",
"amount": 12000000,
"investors": "…",
"source": "exa_funding",
"source_url": "…",
"status": "enriched",
"summary": "…",
"discovered_at": "2026-08-09T12:00:00Z",
"contacts_count": 3
}
],
"pagination": {
"page": 1,
"per_page": 50,
"total_pages": 20,
"total_count": 1000
}
}
/api/v1/funding_events/:id
A single event with its full company object and the
company's contacts. Unknown ids return
404 Not found.
Response
{
"data": {
"id": 123,
"company_name": "Acme Inc",
"…": "…",
"company": {
"id": 45,
"name": "Acme Inc",
"domain": "acme.com",
"industry": "…",
"employee_range": "…",
"hq_city": "…",
"hq_country": "…",
"total_funding": 20000000,
"website_url": "…",
"linkedin_url": "…"
},
"contacts": [ /* see Contact object */ ]
}
}
/api/v1/funding_events/:funding_event_id/contacts
Decision-maker contacts for the event's company. email and
phone stay hidden until the corresponding channel is unlocked for your account.
Contact object
{
"id": 77,
"first_name": "Jane",
"last_name": "Doe",
"title": "VP Engineering",
"seniority": "vp",
"city": "London",
"country": "GB",
"linkedin_url": "…",
"details_unlocked": false,
"email_unlocked": false,
"phone_unlocked": false,
"unlock_channel": "email",
"unlock_status": "idle"
// Each field appears only when its own *_unlocked flag is true.
// unlock_status is "idle", "processing", "no_result", or "failed" (see below).
}
Getting a contact's details
A contact's email and phone are
locked by default. Because the lookup runs in the background, retrieving them is a three-step flow:
-
Start the unlock.
POST /api/v1/contacts/:id/unlock— returns202withunlock_status: "processing"(or200with the details right away if it's already unlocked). -
Poll.
GET /api/v1/contacts/:id/unlockevery second or two whileunlock_statusis"processing". -
Read the details.
Once the requested
email_unlockedorphone_unlockedflag is true, the corresponding field is present on the Contact object.
A run that finishes at "no_result" found nothing (safe to retry, but
won't cost a credit unless new data becomes available); "failed" means
the lookup errored. Yearly plans include unlimited unlocks.
/api/v1/contacts/:id/unlock
Finds email by default. Send
channel=phone to request a phone number separately. The lookup runs in the background, so this returns
202 Accepted right away with
unlock_status: "processing" — poll the endpoint below until
the requested channel is unlocked or unlock_status settles.
It's a no-op (spends nothing, returns 200 with the details) if the
contact is already unlocked.
curl -X POST \ -H "Authorization: Bearer YOUR_API_KEY" \ https://app.synal.to/api/v1/contacts/77/unlock
/api/v1/contacts/:id/unlock
Returns the contact's current state so you can poll after kicking off an unlock. Keep polling while
unlock_status is "processing".
On success the requested channel’s *_unlocked flag becomes true
and that field appears;
"no_result" after a run means nothing was found (safe to retry) and
"failed" means the lookup errored.
curl \ -H "Authorization: Bearer YOUR_API_KEY" \ https://app.synal.to/api/v1/contacts/77/unlock
Errors
Errors return the matching HTTP status and a JSON body of the shape
{ "error": "…" }.
401 Unauthorized— missing or invalid API token.403 Forbidden— API access requires an active yearly plan.404 Not found— the requested record does not exist.
Find more contacts
Two decision-makers are discovered automatically.
GET the event's contacts and read discovery.token. POST that token to
/api/v1/funding_events/:id/contacts/discover to request the next two.
Poll the contacts GET while discovery.status is processing.
Each completed search returns a new token and more_available.
Repeated submissions of an old token do not buy another page. Discovery does not reveal email or phone.