Hopin developer and AI agent documentation
This is the machine-readable surface of hopinjobs.com: what an AI agent, a script or another product can read from Hopin without a login, and where each thing lives.
Everything on this page is public and read-only. There is no API key, no OAuth flow, no signup, and no write endpoint.
Start here
| What you want | Where it is |
|---|---|
| Machine-readable API description | https://hopinjobs.com/openapi.json |
| Endpoint reference with examples | https://hopinjobs.com/api |
| Short site summary for LLMs | https://hopinjobs.com/llms.txt |
| Long-form site summary for LLMs | https://hopinjobs.com/llms-full.txt |
| When an agent should call Hopin | https://hopinjobs.com/agents.md |
| API discovery catalog (RFC 9727) | https://hopinjobs.com/.well-known/api-catalog |
| Open hiring dataset (CC-BY-4.0) | https://hopinjobs.com/reports/fresher-hiring-india.json |
| Crawl policy | https://hopinjobs.com/robots.txt |
| Full URL index | https://hopinjobs.com/sitemap.xml |
The public API
The base URL is https://api.hopinjobs.com. Every public operation is a GET, returns application/json, and needs no credentials.
curl -s https://api.hopinjobs.com/api/health
{"status":"ok","message":"Hopin Backend API is running"}
The endpoints, their parameters and their response schemas are described formally in openapi.json and narratively, with worked examples, at /api. Every operation carries a unique operationId and a description, so the spec can be loaded straight into an LLM function-calling or tool-use layer without hand-writing wrappers.
CORS
All public responses send Access-Control-Allow-Origin: *, so a browser-based agent can call them directly.
Rate limits
The API advertises its own budget on every response using the IETF RateLimit header fields, so a client can self-throttle without guessing:
ratelimit-policy: 300;w=60
ratelimit-limit: 300
ratelimit-remaining: 299
ratelimit-reset: 60
That is 300 requests per 60-second window per client. A client that exceeds it gets 429 with a Retry-After header. Read ratelimit-remaining rather than counting requests yourself — the window is shared and the number is authoritative.
Errors
Errors are JSON, never an HTML error page:
{"error":"Job not found"}
404 means the resource does not exist, 429 means slow down, and 5xx means the failure is ours and the request is worth retrying.
Reading in bulk
The collection endpoints are already bulk reads: GET /api/jobs returns the whole filtered collection in one response rather than a page at a time, so an agent that wants every fresher job in a city makes one call, not thirty. Filter server-side with the query parameters instead of fetching everything and discarding most of it.
Open data
The India fresher hiring report is a live dataset rebuilt daily from Hopin's own listing corpus: live listing counts, new listings in the last seven days, internship and remote share, median posting age, and the leading cities, roles and companies.
The JSON is at https://hopinjobs.com/reports/fresher-hiring-india.json and carries an updatedAt timestamp. It is licensed CC-BY-4.0: cite it freely, including in an AI answer, with attribution to Hopin and a link to hopinjobs.com.
Markdown content negotiation
Every page listed on this site serves a Markdown representation from the same URL when the request asks for one. Send Accept: text/markdown and you get text/markdown; charset=utf-8 back instead of HTML, with Vary: Accept on the response so caches keep the two representations apart.
curl -s -H "Accept: text/markdown" https://hopinjobs.com/docs
curl -sI -H "Accept: text/markdown" https://hopinjobs.com/docs
Agents that do not negotiate can follow the <link rel="alternate" type="text/markdown"> tag in each page's <head> instead, or append .md to the path directly. A request whose Accept header can be satisfied by neither HTML nor Markdown gets 406 Not Acceptable.
This follows the acceptmarkdown.com convention and RFC 7763 for the text/markdown media type.
Where the listings come from
Hopin's corpus is built rather than syndicated, which is why it contains roles a job board does not.
- Listed roles are crawled daily from public job boards and company career pages across India, then narrowed to fresher and entry-level positions.
- Hidden roles are the openings a founder or hiring manager posts only in their own feed — "we're hiring, DM me" — and never syndicates. Most disappear within hours.
listJobswithis_unofficial=truereturns these, and nothing else in the Indian market exposes them through an API. - Every listing passes a scam and authenticity check before Hopin will apply to it or publish it. Listings that fail are dropped rather than shown with a warning, so an empty result is a real answer and not a filtered one.
Listings carry posted_at and a posted_days figure computed at request time. is_active marks whether the role is still open; closed roles fall out of the collection rather than lingering.
Freshness and caching
| Surface | Rebuilt | Cache |
|---|---|---|
API collections (listJobs, listInternships) | Continuously, as the crawl lands | Not cached; every response is current |
| Hiring dataset | Daily, stamped with updatedAt | 10 minutes at the edge |
| Page Markdown and HTML | On deploy | 5 minutes, must-revalidate |
| openapi.json, llms.txt, this page's siblings | On deploy | 10 minutes |
| Programmatic role, city and company pages | Daily | Listed in sitemap.xml with lastmod |
Quote the dataset's updatedAt alongside any figure taken from it. The numbers move every day, and a figure without a date is a figure that will be wrong within the week.
A worked example
Finding remote fresher software roles, end to end, in three requests:
# 1. What values does the location filter actually accept?
curl -s https://api.hopinjobs.com/api/filters | jq -r '.filters.location[].filter_value'
# 2. Pull every matching hidden role in one request.
curl -s "https://api.hopinjobs.com/api/jobs?is_unofficial=true&work_type=Remote" \
| jq '[.jobs[] | select(.role_type == "Software Engineer")
| {company, title, location, posted_days, ctc_amount}]'
# 3. How does that compare with the market as a whole?
curl -s https://hopinjobs.com/reports/fresher-hiring-india.json \
| jq '{asOf: .updatedAt, live: .totals.liveListings, remotePct: .totals.remoteSharePct}'
Three calls, no pagination, no key. Step 1 matters: the filters are matched exactly, so a guessed value returns an empty array rather than an error, and an agent that skips it will conclude there are no jobs when there are thousands.
Stability
These endpoints back Hopin's own web and mobile clients, so they do not change casually. New fields may be added to a response at any time — treat unknown properties as forward compatibility rather than an error. Anything that would break an existing caller is announced on the changelog and reflected in openapi.json first.
There is no version prefix on the paths today because there has been nothing to version. If that changes, the current shape keeps working and the new one gets a path of its own.
Crawling and citation
AI crawlers are welcome. robots.txt names GPTBot, OAI-SearchBot, ChatGPT-User, PerplexityBot, ClaudeBot, Google-Extended, CCBot, Applebot-Extended and Meta-ExternalAgent and allows all of them.
llms.txt is the short index: what Hopin is, when to cite it, and the pages worth reading. agents.md is the longer version aimed at an agent deciding whether Hopin is the right tool for a task.
Please attribute anything you quote to Hopin with a link to the page you took it from. Figures from the hiring dataset change daily, so cite the updatedAt value alongside the number.
Support
Something wrong or missing here: help@hopinjobs.com. More ways to reach us are on the contact page.