Alerts and saved searches

An alert emails you new works that match a search, daily, weekly or monthly. An alert always belongs to a saved search: save the search, give it an alert, and OpenAlex checks it on schedule and emails you what’s new since the last email. Everything you can do on the website (save, rename, turn an alert on or off, change how often, delete) you can do through this API, so a script or an AI agent can set up and manage alerts for you.

Quick start

Create a saved search with a weekly alert in one request:

curl -X POST https://api.openalex.org/saved-searches \
  -H "Authorization: Bearer $OPENALEX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Microplastics in drinking water",
    "url": "https://api.openalex.org/works?filter=title_and_abstract.search:microplastic%20AND%20%22drinking%20water%22",
    "alert": { "frequency": "weekly" }
  }'
{
  "id": "kwGHZstvJNb9nfZiNAipqw",
  "name": "Microplastics in drinking water",
  "description": "",
  "entity_type": "works",
  "url": "https://openalex.org/works?filter=title_and_abstract.search:microplastic%20AND%20%22drinking%20water%22&id=kwGHZstvJNb9nfZiNAipqw",
  "api_url": "https://api.openalex.org/works?filter=title_and_abstract.search:microplastic%20AND%20%22drinking%20water%22",
  "alert": {
    "frequency": "weekly",
    "last_sent_at": null,
    "next_check_at": "2026-10-09T13:05:00Z"
  },
  "cannot_alert": null,
  "created_date": "2026-10-02",
  "updated_date": "2026-10-02T13:05:00.000000"
}

The response is 201 Created with a Location header pointing at the new saved search. The first email covers works added to OpenAlex after you created the alert.

Authentication

All requests go to https://api.openalex.org with your API key, as ?api_key= or an Authorization: Bearer <api_key> header. Managing saved searches and alerts costs no credits. Each key acts as its owner: an agent using your key manages your saved searches and alerts, and emails go to your account’s address. Organization keys can’t own saved searches; use a personal key.

The saved search object

FieldTypeNotes
idstringAssigned by OpenAlex.
namestring1 to 400 characters. Used as the alert email’s subject.
descriptionstringUp to 400 characters. May be empty.
entity_typestringWhat the search returns, from its URL: works, authors, sources and so on. Only works searches can have an alert.
urlstringThe search on openalex.org. Open it to see the results in the website.
api_urlstringThe same search on api.openalex.org, without your key. Call it to see what the search matches today.
alertobject or nullnull means no alert. See below.
cannot_alertobject or nullWhy this search can’t have an alert, as { "code", "message" }, or null if it can.
created_date, updated_datestringAs on every entity: the date it was saved (YYYY-MM-DD), and the datetime of its last change (ISO 8601, UTC). The deprecated user.openalex.org/me/saved-searches routes still say created_at and updated_at.

The alert object:

FieldTypeNotes
frequencystringdaily, weekly or monthly.
last_sent_atstring or nullWhen the last email went out. null until the first one. An alert sends only when there are new works, so a quiet search can go a long time without one.
next_check_atstringWhen OpenAlex next looks for new works.

Endpoints

MethodPathDoes
GET/saved-searchesList your saved searches.
POST/saved-searchesCreate a saved search, with or without an alert.
GET/saved-searches/{id}Get one.
PATCH/saved-searches/{id}Change any of name, description, url, alert.
DELETE/saved-searches/{id}Delete it and its alert.

These first lived at https://user.openalex.org/me/saved-searches, which still works (Bearer header only there) but is deprecated.

List

GET /saved-searches?has_alert=true&page=1&per_page=50

has_alert=true lists only searches with an alert (your alerts); false, only those without. Newest first. per_page defaults to 25 and is at most 100.

{
  "meta": { "count": 3, "page": 1, "per_page": 50 },
  "results": [ { "id": "…", "name": "…", "alert": { "frequency": "weekly", … }, … } ]
}

Create

POST /saved-searches with:

FieldRequiredNotes
urlyesThe search, as an api.openalex.org or openalex.org URL: https://api.openalex.org/works?filter=…&search=…, or an OQL query, https://api.openalex.org/?oql=works where …. Your key, paging and select are dropped; the filter, search and sort are kept. The url and api_url you get back are normalized (re-encoded), so don’t compare them to what you sent as strings.
nameyes
descriptionno
alertno{ "frequency": "weekly" } to create the alert at the same time; frequency is required inside it (daily, weekly or monthly, any case). Omit or null for no alert.

Saving the same search twice returns 409 with code saved_search_exists and the existing search’s id in existing_id; the order of parameters, paging and sort don’t make two searches different. So retrying a create is safe, but a 409 doesn’t mean your alert exists: the earlier save may have had none. After a 409, PATCH the existing_id with the alert you wanted. You can have up to 100 saved searches.

Update

PATCH /saved-searches/{id} with any of name, description, url, alert. Fields you leave out don’t change.

{ "alert": { "frequency": "monthly" } }   // add an alert, or change its frequency
{ "alert": null }                          // turn the alert off, keep the saved search

Changing frequency keeps the alert’s history: the next check is the last check plus the new interval. Turning an alert on for a search saved earlier makes its first email cover works added since the search was saved (or since its last email); an alert created together with its search starts from now.

Delete

DELETE /saved-searches/{id} returns 204 No Content. The alert goes with it.

Which searches can have an alert

An alert needs a works search that can gain new works:

SearchAlert?code when refused
Works, by filter or searchYes
Works in a collection of authors, institutions, sources or another typeYes, while you can read the collectioncollection_not_found
collection: with a collection that isn’t of worksNo: collection: takes only collections of works; use the field for that type (below)collection_type_mismatch
Works with no filter or search at allNo: it would send every new worksearch_is_empty
Works in a collection of works (collection:col_…)No: a collection of works is a fixed list and never gains new worksworks_collection_cannot_alert
Semantic search (search.semantic, or OQL is similar to)No: it can’t be limited to newly added workssemantic_search_cannot_alert
OQL (https://api.openalex.org/?oql=works where …)Yes, if it returns worksalert_requires_works_search
Authors, sources or any type but worksNo: alerts send worksalert_requires_works_search

To alert on works from a collection of something other than works, filter by that type’s field with the collection’s id as the value:

Collection ofFilter
Authorsauthorships.author.id:col_…
Institutionsauthorships.institutions.lineage:col_… (the institution and its parts)
Sources (journals, repositories)primary_location.source.id:col_…
Publishersprimary_location.source.publisher_lineage:col_…
Fundersfunders.id:col_…
Topicstopics.id:col_…

For example https://api.openalex.org/works?filter=authorships.institutions.lineage:col_abc123. See Collections for every field.

Every saved search says whether it can have an alert in cannot_alert, so check that before offering one. If a collection in an alert’s search is deleted, or its owner makes it private again, the alert turns off (alert becomes null) and you get an email saying which collection.

Errors

Errors return JSON with a stable code to branch on, a message to show people, and error, a short title for the HTTP status (the same shape as api.openalex.org):

{
  "error": "Bad Request",
  "code": "works_collection_cannot_alert",
  "message": "Alerts aren't available for a works collection: it's a fixed list of works, so it never gains new ones. To hear about new works, filter by a collection of authors, institutions or sources instead."
}
StatuscodeMeaning
400invalid_bodyThe body isn’t a JSON object.
400invalid_urlurl isn’t an OpenAlex search URL.
400invalid_fieldA field is missing, unknown, the wrong type or too long; message names it.
400invalid_frequencyalert.frequency is missing or isn’t daily, weekly or monthly.
400one of the codes in the table aboveThis search can’t have an alert.
401unauthorizedMissing or invalid key.
403too_many_saved_searchesYou have 100 already.
404not_foundNo saved search with that id is yours.
409saved_search_existsYou already saved this search; existing_id names it.

For agents

  • Check what the user already has first (GET /saved-searches?has_alert=true): the same topic written another way is a different search to the API.
  • Show the user what an alert will send before creating it: call the search’s api_url with your key and sort=publication_date:desc, and show a few titles. (A search on a private collection matches nothing without the owner’s key.)
  • Name the alert after what the user asked for; it’s the email’s subject line.
  • Use has_alert=true to answer “what alerts do I have?”, and PATCH with "alert": null to stop one without losing the saved search.
  • Branch on code, never on message; messages may change.

Last updated

View as Markdown