Version
Fetch the current object and compare its version with the stored one. A higher version is the first and cheapest signal of change.
An OSMPID carries an object's version and the timestamp of its newest child. So when the map moves underneath your reference, a single request can say exactly what changed.
Paste an OSMPID or pick an example. Checked against current OSM state by the service.
OSM identifiers like node/2641352539 are source-local — they
name a record inside one system. They say nothing about whether the thing they point at still
means what it meant when you stored it.
An OSM Persistent ID closes that gap. It combines the source-local reference with version and timestamp semantics, so a service can decide — using only current OSM data — whether the referenced object has meaningfully changed since you recorded it.
No historical snapshots, no diff history, no attic data. The check relies only on what OSM serves today.
The OSM element class — node, way, or relation. Determines how deep the recursive child check must go.
The OSM object's source-local numeric ID. Together with the type it locates the object in the OSM database.
The object version at the time of recording, written @N. A differing current version is the first signal of change.
ISO-8601 UTC timestamp of the most recent child element, found by recursing the dependency tree. Omitted for nodes, which have no children.
url-encoded key[=value] pairs that pin the semantic meaning. If an expected key disappears, the object is considered semantically changed.
Resolve the object by type and id, then walk three checks in order. Any one of them flips the reference to changed.
Fetch the current object and compare its version with the stored one. A higher version is the first and cheapest signal of change.
A way recurses into its member nodes; a relation into all members, ways and relations alike. If
any child's timestamp is newer than latest_child_timestamp, the
object changed. Cycles are guarded by tracking visited elements.
If the OSMPID pins tag keys or values, those must still be present. A vanished amenity key means the object
changed semantically — even at the same version.
Every part carries meaning. Main parts are separated by a semicolon; the version is appended to
the id with @; tags follow a ?, url-encoded and joined by &.
The validate endpoint always returns a definite verdict. Only an unparseable string is an error;
every real-world object state resolves with 200 OK.
| Result | Status | Reason |
|---|---|---|
| Unchanged | 200 OK | Version, children and tags all match. |
| Changed | 200 OK | Version, a child element or a tag changed. A new OSMPID is returned. |
| Deleted | 200 OK | The object is no longer visible. |
| Unknown | 200 OK | This type + id never existed. |
| Malformed | 422 | The string failed to parse. |
One GET, one url-encoded id. The response carries a Last-Modified header
with the computed latest timestamp — ready to become the next latest_child_timestamp.
GET /validate?id=way%2F2641352539%407%3B2026-03-12T10%3A15%3A00Z%3Famenity # decoded → way/2641352539@7;2026-03-12T10:15:00Z?amenity
{
"status": "changed",
"permanent_id": "way/2641352539@8;2026-03-28T14:22:00Z?amenity",
"element_type": "way",
"element_id": 2641352539,
"version": 8,
"latest_child_timestamp": "2026-03-28T14:22:00Z",
"changed_reason": {
"version_changed": true,
"child_changed": true,
"tag_changed": false
}
}