Group
The group_by parameter aggregates entities into groups and counts how many are in each group.
# Count works by type
https://api.openalex.org/works?group_by=type
Response:
{
"meta": {
"count": 246136992,
"groups_count": 15
},
"group_by": [
{
"key": "article",
"key_display_name": "article",
"count": 202814957
},
{
"key": "book-chapter",
"key_display_name": "book-chapter",
"count": 21250659
},
{
"key": "dissertation",
"key_display_name": "dissertation",
"count": 6055973
}
]
}
Group properties
Each group object contains:
| Property | Description |
|---|---|
key |
The OpenAlex ID or raw value for this group |
key_display_name |
The display name or raw value for this group |
count |
Number of entities in the group |
key vs key_display_name
When grouping by an OpenAlex entity, key is the ID and key_display_name is the display name:
# Group works by institution
https://api.openalex.org/works?group_by=authorships.institutions.id
Returns groups like:
{
"key": "https://openalex.org/I136199984",
"key_display_name": "Harvard University",
"count": 1234567
}
For non-entity values (like level), both key and key_display_name are the raw value.
Including unknowns
The “unknown” group (entities without a value) is hidden by default. Add :include_unknown to include it:
https://api.openalex.org/works?group_by=authorships.countries
https://api.openalex.org/works?group_by=authorships.countries:include_unknown
How “unknown” is keyed
The bucket’s key depends on the field type:
| Field type | Example | Unknown key |
|---|---|---|
| String / ID | primary_location.license, type |
"unknown" |
| Numeric (range) | apc_paid.value, cited_by_count |
-111 (sentinel) |
| Boolean | is_oa |
returned as the false bucket |
Numeric fields use the sentinel -111 because the aggregation bucket can’t mix a string key like "unknown" into a numeric series. Treat any -111 (or -111.0) bucket key as “unknown.”
What counts as “unknown”
A work is counted in the unknown bucket when the underlying field is missing or empty. For fields nested inside an array — for example authorships.institutions.type — the work is also counted as unknown when the array is present but empty (e.g. an authorship with no institutions). If you reproduce group_by counts in code by iterating the JSON, treat empty lists the same way to match the API’s totals.
Combining with filters
Group by and filter work together:
# Count work types for 2023 publications
https://api.openalex.org/works?filter=publication_year:2023&group_by=type
# Count open access status for a specific author
https://api.openalex.org/works?filter=author.id:A5023888391&group_by=open_access.is_oa
Paging
A grouped response returns at most 200 groups per page. To page through more, use cursor paging: start with cursor=* and follow meta.next_cursor until it’s null, exactly as you would for a list of results.
# First page of groups
https://api.openalex.org/works?group_by=authorships.author.id&per_page=200&cursor=*
# Next page: use the next_cursor value from the previous response
https://api.openalex.org/works?group_by=authorships.author.id&per_page=200&cursor=<next_cursor>
Note: Basic
page-based paging (page=2, …) is not supported withgroup_by— use cursor paging. When paging through groups, results are sorted bykey(not bycount).
Meta properties
| Property | Description |
|---|---|
meta.count |
Total entities matching the filter |
meta.groups_count |
Number of groups in current page (or null if none) |
Note: Due to technical limitations,
groups_countonly reports groups in the current page, not the total number of groups.