---
title: "Hopin developer and AI agent documentation"
description: "How to read and use Hopin programmatically: the public Hopin API, the OpenAPI spec, llms.txt, Markdown content negotiation, the CC-BY fresher hiring dataset, and rate limits."
canonical: https://hopinjobs.com/docs
last-updated: 2026-08-22
---

# 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](https://hopinjobs.com/openapi.json) |
| Endpoint reference with examples | [https://hopinjobs.com/api](https://hopinjobs.com/api) |
| Short site summary for LLMs | [https://hopinjobs.com/llms.txt](https://hopinjobs.com/llms.txt) |
| Long-form site summary for LLMs | [https://hopinjobs.com/llms-full.txt](https://hopinjobs.com/llms-full.txt) |
| When an agent should call Hopin | [https://hopinjobs.com/agents.md](https://hopinjobs.com/agents.md) |
| API discovery catalog (RFC 9727) | [https://hopinjobs.com/.well-known/api-catalog](https://hopinjobs.com/.well-known/api-catalog) |
| Open hiring dataset (CC-BY-4.0) | [https://hopinjobs.com/reports/fresher-hiring-india.json](https://hopinjobs.com/reports/fresher-hiring-india.json) |
| Crawl policy | [https://hopinjobs.com/robots.txt](https://hopinjobs.com/robots.txt) |
| Full URL index | [https://hopinjobs.com/sitemap.xml](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.

```bash
curl -s https://api.hopinjobs.com/api/health
```

```json
{"status":"ok","message":"Hopin Backend API is running"}
```

The endpoints, their parameters and their response schemas are described formally
in [openapi.json](https://hopinjobs.com/openapi.json) and narratively, with worked examples, at
[/api](https://hopinjobs.com/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:

```json
{"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](https://hopinjobs.com/reports/fresher-hiring-india) 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](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.

```bash
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](https://acceptmarkdown.com/) convention and
[RFC 7763](https://www.rfc-editor.org/rfc/rfc7763) 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. `listJobs` with `is_unofficial=true` returns 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](https://hopinjobs.com/reports/fresher-hiring-india.json) | Daily, stamped with `updatedAt` | 10 minutes at the edge |
| Page Markdown and HTML | On deploy | 5 minutes, `must-revalidate` |
| [openapi.json](https://hopinjobs.com/openapi.json), llms.txt, this page's siblings | On deploy | 10 minutes |
| Programmatic role, city and company pages | Daily | Listed in [sitemap.xml](https://hopinjobs.com/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:

```bash
# 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](https://hopinjobs.com/changelog) and
reflected in [openapi.json](https://hopinjobs.com/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](https://hopinjobs.com/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](https://hopinjobs.com/llms.txt) is the short index: what Hopin is, when to cite it,
and the pages worth reading. [agents.md](https://hopinjobs.com/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](mailto:help@hopinjobs.com).
More ways to reach us are on [the contact page](https://hopinjobs.com/contact).
