We use only the cookies needed to run the site and keep you signed in. No analytics, no advertising. Your answer covers anything optional we add later.

Cookie statement

Public API.

REST, read-only, base path /api/public/v1. It returns only entries an IPMERC admin has explicitly marked public, and every request needs an API key.

Access

Keys are issued by an IPMERC administrator. Email the operator to request access. There is no self-service signup, and only entries explicitly toggled public in the admin console are returned.

Authentication

Every request must include an Authorization: Bearer ipmerc_ header. The raw key is shown once at creation, and only its hash is stored. Revoked keys return 401.

Rate limits

  • 60 requests per minute per key
  • 3000 requests per hour per key
  • 200 requests per minute per IP, applied before auth

Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, the seconds until the window resets. On 429 a Retry-After header tells you when to retry.

Endpoints

Three read-only endpoints. Each returns the same entry shape.

GET/api/public/v1/entries

Paginated list of public entries. Query params: category, type (answer, drill, handout), lang (nl, en), limit (1 to 200, default 50), offset.

curl "https://ipmerc.com/api/public/v1/entries?limit=10" \
  -H "Authorization: Bearer ipmerc_..."

GET/api/public/v1/entries/:id

One public entry by id. Returns 404 for private or missing ids (existence of private entries is never leaked).

curl https://ipmerc.com/api/public/v1/entries/<uuid> \
  -H "Authorization: Bearer ipmerc_..."

GET/api/public/v1/search

Keyword search across title and body of public entries. Query params: q (required, 1 to 200 chars), type, lang, limit (1 to 50, default 20).

curl "https://ipmerc.com/api/public/v1/search?q=cold+call" \
  -H "Authorization: Bearer ipmerc_..."

Response shape

Every list endpoint wraps its results in data, with paging counters in meta.

{
  "data": [
    {
      "id": "uuid",
      "type": "answer" | "drill" | "handout",
      "title": "string",
      "questions": ["..."],
      "keywords": ["..."],
      "body": "markdown (answer/handout) | JSON-encoded { dialog, quiz } (drill)",
      "language": "nl" | "en",
      "source": "academy" | "imported" | "external" | "ipmerc",
      "category": { "id": "uuid", "slug": "...", "nameNl": "...", "nameEn": "..." },
      "version": 1,
      "createdAt": "ISO-8601",
      "updatedAt": "ISO-8601"
    }
  ],
  "meta": { "total": 170, "limit": 50, "offset": 0, "returned": 50 }
}

Questions

The six that arrive by email most often.

How do I get an API key?

Ask. Keys are issued by hand through the contact page, there is no self-service signup, and the raw key is shown once at creation. Only its hash is stored, so a lost key is replaced rather than recovered.

What is in the public set?

Only entries an IPMERC administrator has explicitly marked public. The rest of the knowledge base is not reachable through the API, and a request for a private entry returns 404 rather than 403, so the API never confirms that an entry exists.

What are the rate limits?

60 requests per minute and 3000 per hour per key, and 200 per minute per IP applied before authentication. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. A 429 includes Retry-After, which is the number of seconds to wait.

Will the response shape change?

The version is in the path. Anything that would break a consumer gets a new version rather than a change to /api/public/v1, and new optional fields can appear inside the existing shape. Write your client to ignore fields it does not know.

Can I cache or store what the API returns?

Cache it as long as you like for your own use. Redistribution and resale are a different question and need a written agreement, because the training material is licensed rather than open. The salary data at /salary-data is the exception: that is published under CC BY 4.0.

Something is broken. Who do I tell?

The contact page reaches a person. Include the endpoint, the query, the status code, and the time, and skip the key itself: we can find it from the request logs and you should never mail a key to anyone.

Errors

Failures use the standard status codes and never leak the existence of a private entry.

400invalid query parameters
401missing or revoked API key
404unknown id or category slug, also returned for private entries to avoid leaking existence
429rate limit exceeded, Retry-After header included
500internal error, logged on the server