Webhooks
The Serply REST API does not currently support outbound webhooks. There is no endpoint for registering a callback URL, and the API does not push events to your application.
Serply's endpoints are synchronous: you make a request, and the results come
back in that same response. There is no job queue to be notified about and no
search.completed event, because the search has already completed by the time
the call returns.
If you need to be notified when something on the web changes, you build that loop on your side. The pattern is below.
Polling instead
Run your query on a schedule, compare against what you saw last time, and act only on the difference:
import json
import time
from pathlib import Path
import requests
HEADERS = {
'X-Api-Key': 'YOUR_API_KEY',
'X-Proxy-Location': 'US', # pin the region - see the warning below
}
STATE = Path('seen.json')
def search(query, num=10):
r = requests.get(
f'https://api.serply.io/v1/search/q={query}&num={num}',
headers=HEADERS,
timeout=15,
)
r.raise_for_status()
return r.json().get('results', [])
def check(query):
seen = set(json.loads(STATE.read_text())) if STATE.exists() else set()
new = [item for item in search(query) if item['link'] not in seen]
if new:
notify(new) # Slack, email, a database write - whatever you need
STATE.write_text(json.dumps(sorted(seen | {i['link'] for i in new})))
return new
while True:
check('your+query+here')
time.sleep(900) # every 15 minutes
Storing the state is the part that matters. Without it you re-alert on the same results every cycle, and the notifications stop being read.
Always pin X-Proxy-Location when monitoring
This is the detail that breaks most polling loops, and it is not obvious.
If you omit X-Proxy-Location, your request is served from whichever proxy is
available, and the response comes back with device_region set to an empty
string. Most consecutive calls then return the same results - until one is
served from a different country, at which point you get an entirely different
SERP.
In testing, six identical queries three seconds apart returned the same nine results five times, and on the sixth returned a German result set sharing zero links with the previous five. A monitor built on that will announce that 100% of its results are new, then revert on the next cycle.
Pinning the header removes the problem completely. The same six-run test with
X-Proxy-Location: US returned identical results every time:
HEADERS = {
'X-Api-Key': 'YOUR_API_KEY',
'X-Proxy-Location': 'US',
}
Any change in results is then a real change in the SERP, which is the only thing worth alerting on. See Google Search for the full list of accepted regions.
Why polling is cheaper than it sounds
Credits are consumed per successful, uncached request. Cached responses cost
nothing, and most endpoints cache for several minutes - Reddit endpoints cache
for 10 minutes, and the Reddit comments response tells you directly with a
cached field.
The practical effect is that polling faster than the cache window does not cost more. A monitor that checks every minute pays for roughly the same number of credits as one that checks every ten, because the intervening calls are served from cache.
That also means there is little value in polling very aggressively: you will receive the cached response until the window expires. Match your interval to how quickly the underlying data actually changes - for most search and news monitoring, 15 minutes to an hour is plenty.
Handling failures in a long-running loop
A polling loop runs unattended, so it needs to survive the transient errors a one-off script can ignore:
502means the upstream fetch or parse failed. It is transient - retry before treating it as an outage.- A
200response with an emptyresultsarray is usually the same transient failure rather than a genuine "no results". Retry once or twice before recording that state, or your loop will alert on results "disappearing" and then "reappearing" on the next cycle. 429means you hit the rate limit. Back off and retry.
See the Errors guide for the full error format.
If you need push delivery
Some use cases genuinely need push rather than poll - high query volumes, or alerting where a 15-minute delay is too long. If that describes your setup, contact support and describe the workload; requirements like this help prioritize what gets built.