Documentation menu
Realtime API
Receive real-time event updates from all supported Wikimedia projects using the streaming (firehose) endpoint, or via batch files that are generated hourly with changes throughout the day.
Streaming returns server-sent events (SSE) by default, or NDJSON when you pass the Accept: application/x-ndjson header. Batch files return NDJSON in a compressed tarball (.tar.gz).
At a glance
- Base URLs:
https://realtime.enterprise.wikimedia.com(stream) andhttps://api.enterprise.wikimedia.com(hourly batches) - Auth: JWT Bearer access token (Authentication)
- Formats: SSE default; NDJSON via the
Accept: application/x-ndjsonheader; batches are .tar.gz - Response model: RealtimeArticle
- Access: paid - contact sales
- Status: Realtime Firehose and Batch endpoints are fully released. Wikidata Realtime and Wikidata Batch endpoints are in beta.
Endpoints
/v2/articlesStream article changes as they happenGETPOST/v2/wikidataStream Wikidata changes as they happenBetaGETPOST/v2/batches/{date}/{hour}List all batch files for a given hour and dateGETPOST/v2/batches/{date}/{hour}/{identifier}Receive info for one batch fileGETPOST/v2/batches/{date}/{hour}/{identifier}/downloadDownload one batch fileHEADGET/v2/batches/{date}/{hour}/wikidataList all Wikidata batch files for a given hour and dateBetaGETPOST/v2/batches/{date}/{hour}/wikidata/{identifier}Receive info for one Wikidata batch fileBetaGETPOST/v2/batches/{date}/{hour}/wikidata/{identifier}/downloadDownload one Wikidata batch fileBetaHEADGET
Batch downloads also answer HEAD requests, so you can inspect a batch's size before downloading it. Wikidata endpoints are currently in beta with no SLA.
Worked examples
Streaming the firehose
Connect to Streaming Article Updates with curl -N (unbuffered) and a filter so you only receive events from English Wikipedia. This example requests NDJSON with the Accept: application/x-ndjson header; SSE is the default when the header is omitted.
The stream is long-lived: you will continue getting data streamed to you until you close the connection yourself. It stays open even past your access token's 24-hour expiry, as long as the token was valid at the moment you opened the connection.
The stream also answers a GET request with the same parameters in the query string: one filters parameter per filter, each a JSON object, and one fields parameter per field, URL-encoded. The second example sends the same filter that way and asks for two fields; curl -G --data-urlencode writes the encoded form, shown in the comment.
curl -N 'https://realtime.enterprise.wikimedia.com/v2/articles' \ -H 'Content-Type: application/json' \ -H 'Accept: application/x-ndjson' \ -H 'Authorization: Bearer ACCESS_TOKEN' \ --data '{ "filters": [{ "field": "is_part_of.identifier", "value": "enwiki" }] }'curl -N -G 'https://realtime.enterprise.wikimedia.com/v2/articles' \ -H 'Accept: application/x-ndjson' \ -H 'Authorization: Bearer ACCESS_TOKEN' \ --data-urlencode 'filters={"field":"is_part_of.identifier","value":"enwiki"}' \ --data-urlencode 'fields=name' \ --data-urlencode 'fields=is_part_of.identifier'# sends ?filters=%7B%22field%22%3A%22is_part_of.identifier%22%2C%22value%22%3A%22enwiki%22%7D&fields=name&fields=is_part_of.identifierOne event, trimmed:
{ "event": { "identifier": "c49d6b93-030e-422b-a904-19fcfd821aca", "type": "update", "date_created": "2026-04-22T07:24:01.47645Z", "date_published": "2026-04-22T07:24:03.546408Z", "partition": 15, "offset": 3465731 }, "name": "MasterChef (American TV series) season 4", "identifier": 39462622, "date_modified": "2026-04-22T07:23:59Z", "in_language": { "identifier": "en" }, "is_part_of": { "identifier": "enwiki" }, "namespace": { "identifier": 0 }, "version": { "identifier": 1350500106, "editor": { "name": "Magitroopa" }, "number_of_characters": 49662 }}event.type says what happened to the article. Use event.partition and event.offset to resume listening at the right place if the connection drops.
Retrieving hourly batches
Batch files are generated hourly with the changes made throughout the day. Before downloading a batch, check that it is available with the Hourly Batch Files Available endpoint.
This example request lists the batches available for August 26, 2025 at 00:00 UTC; to the right is one item of the listing response. size is the batch file's size in decimal megabytes, bytes divided by 1,000,000, to three decimals, and unit_text is always MB for batches. For the exact byte count, request Project Updates (Batch) Headers and read Content-Length.
curl 'https://api.enterprise.wikimedia.com/v2/batches/2025-08-26/00' \ -H 'Authorization: Bearer ACCESS_TOKEN'{ "identifier": "afwiki_namespace_0", "version": "5a3358f08767bd7d88b9f7e8b54358fc", "date_modified": "2026-04-22T06:04:03.479199084Z", "is_part_of": { "identifier": "afwiki" }, "in_language": { "identifier": "af" }, "namespace": { "identifier": 0 }, "size": { "value": 1.418, "unit_text": "MB" }}Fetch the tarball itself from the Hourly Batch File Download endpoint, using the identifier from the listing. Batch identifiers use the same <language><project_code>_namespace_<number> format as snapshots, scoped to a specific date and hour in the URL path; see Identifiers.
Wikidata batches
Wikidata changes ship as their own hourly batches, addressed by items or properties instead of a project identifier. Hourly Wikidata Batch Files Available lists both batches for a given date and hour, Wikidata Hourly Batch File Info reports one file's size, and Wikidata Hourly Batch File Download returns a tar.gz file. Each line is a wikidata_article, with the same schema as Wikidata snapshots. Downloading a snapshot and then ingesting every hourly batch since that first download ensures you always have an up-to-date copy of the Main Graph without the need for a constant open connection to the Realtime Stream.
curl --location 'https://api.enterprise.wikimedia.com/v2/batches/2026-09-02/05/wikidata/items/download' \ -H 'Authorization: Bearer ACCESS_TOKEN' \ --output wikidata_items_2026-09-02_05.tar.gzEvent types
Every article event has one of three event.type values:
- An
updateevent type is sent when an article is created, its content is updated, or its name or namespace is changed. - A
deleteevent type is sent when an article has been deleted. - A
visibility-changeevent type is sent when the visibility of an article's editor, comment, or content is changed by community volunteers
Visibility-change events only occur in Realtime. They do not change the content of an article, so they're not tracked as a revision in the On-demand or Snapshot APIs.
Parallel consumption
Using the parts request parameter, you can open more than one parallel connection to the Realtime API. Each connection targets a subset of data partitions, also called a part. The maximum allowed number of parallel connections to the Realtime API is 10. Valid values for parts are 0 through 9.
If you only want to open one connection that listens to all parts at the same time, you do not need to use parts. When you don't pass the parts parameter, the default behavior of the API is to listen to all parts at the same time.
Example POST Request using cURL to connect to the Streaming Article Updates, using filter to receive only updates from English Wikipedia, listening to all parts:
curl --location 'https://realtime.enterprise.wikimedia.com/v2/articles' \--header 'Content-Type: application/json' \--header 'Authorization: Bearer ACCESS_TOKEN' \--data '{ "filters": [ { "field": "is_part_of.identifier", "value": "enwiki" } ], "parts": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}'Reconnecting to the Realtime API
Realtime updates are stored for a rolling 48 hours, meaning you can use a timestamp within the last 48 hours of reconnecting to reopen a connection and get up to speed with any updates you might have missed. For the background on how parallel connections and restart support fit together, see our blog post Realtime API Parallel Connections and Restart Support. If you know the timestamp of when your connection to the Realtime stream was closed, you can easily reconnect using one of these two methods:
Use since
This is the simplest and recommended method to reconnect to the Realtime stream. Save the latest timestamp you received for each event.partition while you were connected to the streaming endpoint. We recommend using event.date_published for this. Pass the last timestamp you received in the since parameter for all partitions to ensure you don't miss any events. If you use since to reconnect, you may receive events from some partitions that you already obtained in your previous connection. Therefore we recommend recording the IDs of incoming events to discard duplicate events, ensuring idempotence.
Example POST request using cURL asking for all Realtime streaming updates for English Wikipedia since the timestamp 2025-04-15T15:33:50Z.
curl --location 'https://realtime.enterprise.wikimedia.com/v2/articles' \--header 'Content-Type: application/json' \--header 'Authorization: Bearer ACCESS_TOKEN' \--data '{ "filters": [ { "field": "is_part_of.identifier", "value": "enwiki" } ], "since":"2025-04-15T15:33:50Z"}'If you use the since parameter you cannot specify parts. The since parameter will automatically apply to all parts at the same time. If you try to pass since while also using the parts parameter, you will receive the following error message:
{ "status": 422, "message": "for parallel consumption, specify either offsets or time-offsets (since_per_partition) parameter"}Use since_per_partition
Where the since parameter only takes one timestamp as input, since_per_partition allows you to define different timestamps for different partitions, so you can start consuming data from different timestamps in different partitions when reconnecting. This is useful if you are using parts to consume subsets of partitions, whether you're doing this with one or multiple parallel connections.
The simplest and recommended way to reconnect with since_per_partition is to open a single connection. For every partition, find the last event.date_published value you received before you disconnected. When reconnecting, send the request parameter parts with the value [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] and the since_per_partition object with key-value pairs mapping every part to a corresponding event.date_published value, or any other RFC 3339 format timestamp.
The advantage of using since_per_partition over using since is that the chances of receiving duplicate events are much lower, as you are supplying precise timestamps per partition. This makes it much less likely that you will receive events that you had already received before reconnection.
Example request with since_per_partition:
curl --location 'https://realtime.enterprise.wikimedia.com/v2/articles' \--header 'Content-Type: application/json' \--header 'Authorization: Bearer ACCESS_TOKEN' \--data '{ "filters": [ { "field": "is_part_of.identifier", "value": "enwiki" } ], "parts": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], "since_per_partition": { "0": "2023-06-05T12:00:00Z", "1": "2023-06-05T12:00:00Z", "2": "2023-06-05T12:00:00Z", [...], }}'Response model
Realtime endpoints return the RealtimeArticle model. Realtime endpoints return fields that are not available in the article model in the event object: date_published, partition, and offset are only populated in Realtime. event.type:visibility-change only occurs on Realtime endpoints.
See also
- Snapshot API - download entire projects as compressed NDJSON tarballs.
- Identifiers - the batch identifier format, and every other one in the API.
- Status Codes - the HTTP responses these endpoints return.
- Credibility Signals - use visibility and other signals to decide what content to trust.