Skip to main content

API Migration: v1 → v2

The MANRS API has moved from api.manrs.org to observatory.manrs.org. V1 routes are still accessible at observatory.manrs.org/api for continuity, but are deprecated and will be removed in a future release.

All users are encouraged to update their base URL and migrate to the v2 routes at observatory.manrs.org/api/v2. This guide covers every v1 route, its v2 equivalent, and what has changed in the response.

warning

V1 routes are intentionally excluded from the API reference docs. Only v2 routes are documented going forward.

Breaking Changes

These changes affect every request.

ChangeV1V2
Hostapi.manrs.orgobservatory.manrs.org
Base pathhttps://api.manrs.org/...https://observatory.manrs.org/api/v2/...
Month format?month=202501 (YYYYMM)?month=2025-01-01T00:00:00Z (RFC3339)
Field namingsnake_case (anti_spoofing, member_since)camelCase (antiSpoofing, memberSince)
Participant IDid: 42 (legacy integer)id: "a3ffc8ac-…" (UUID string)
CSV exportSupported on net-ops and CDN conformanceNot supported
AuthAuthorization: Bearer <key>Unchanged
Month format

V1 parsed months as YYYYMM (e.g. 202501). V2 accepts a full RFC3339 timestamp. To request January 2025, pass ?month=2025-01-01T00:00:00Z. Only the year and month are used; the day and time components are ignored.


ASN Routes

List approved ASNs

GET /api/asns → GET /api/v2/asns

No change in behaviour or response shape. Returns { asns: [uint32] }.


List all ASN info

GET /api/asns/info → GET /api/v2/ases

V1 returned a slim { number, name, status, manrs, rir_status } shape per entry. V2 returns the full AS model. The combined rir_status field (sourced from NRO data) is no longer merged into the AS response — NRO allocation status is a separate concern. The manrs boolean flag is also absent in v2; use the participant directory instead.


Get single ASN info

GET /api/asns/info/{asID} → GET /api/v2/ases/{asn}

Same change as above — richer model, no rir_status or manrs boolean.


Get ASN conformance

GET /api/asns/conformance/{asn}?month=YYYYMM

GET /api/v2/scores/detailed?asn={asn}&month=2025-01-01T00:00:00Z

V1 returned category scores as integer percentages (0–100) plus trend directions. V2 /scores/detailed is a superset: category scores remain 0–100 integers in score.scores, per-action scores (M1–M9) are raw 0–1 floats in score.actions, and the full routing breakdown, ROV samples, and six-month history are included.

V1 fieldV2 equivalent
scores.filtering.valuescore.scores.filtering.value (0–100 int)
scores.anti_spoofing.valuescore.scores.antiSpoofing.value (0–100 int)
scores.coordination.valuescore.scores.coordination.value (0–100 int)
scores.routing_information_irrscore.scores.routingInformationIRR
scores.routing_information_rpkiscore.scores.routingInformationRPKI
scores.*.trendscore.trend.* (separate trend object)
incidents.m1score.incidents.routeLeaks
incidents.m2score.incidents.routeMisoriginations
incidents.m1cscore.incidents.routeLeaksAccomplice
incidents.m2cscore.incidents.routeMisoriginationsAccomplice
incidents.totalscore.incidents.total
manrs_statusCall GET /api/v2/participants?asn={asn}, read participants[0].status

Get ASN scores (all ASNs)

GET /api/asns/scores?month=YYYYMM

GET /api/v2/scores?month=2025-01-01T00:00:00Z

V1 returned raw 0–1 floats for category scores and used offset-based pagination (page, limit, total, pages). V2 returns 0–100 integers in scores[].scores and delivers the full result set without offset pagination.

V1 fieldV2 equivalent
datascores
data[].scores.*scores[].scores.* (values now 0–100 int)
data[].scores.filtering.value (raw float)scores[].scores.filtering.value (0–100 int)
data[].metrics.m1scores[].actions.m1 (raw float)
data[].metrics.m2scores[].actions.m2Grip (raw float)
data[].metrics.m3scores[].actions.m3 (raw float)
data[].metrics.m7irrscores[].actions.m7Irr (raw float)
data[].metrics.m7rpkiscores[].actions.m7Rpki (raw float)
page, limit, total, pagesNo offset pagination — full result returned

Filter the listing with asns, economies, region (RIR macro-region: africa, asia-pacific, north-america, latin-america, europe), and/or participantIDs.


Get scores for a specific ASN

GET /api/asns/scores/{asn}?month=YYYYMM

GET /api/v2/scores/detailed?asn={asn}&month=2025-01-01T00:00:00Z

V1 returned raw 0–1 floats in both scores.* and metrics.*. V2 /scores/detailed uses 0–100 integers in score.scores and raw 0–1 floats in score.actions.

The metrics key in V1 contained normalized per-action scores. In V2 those move to score.actions with renamed keys:

V1 metricsV2 score.actions
m1m1
m1cm1c
m2m2Grip
m2cm2cGrip
m3m4c_adminm3m4cAdmin
m5m5
m7irrm7Irr
m7rpkim7Rpki
m7rpkinm7RpkiN
m7conflictm7Conflict
m8m8
m9m9

New fields present only in V2: score.routing (full IRR/RPKI prefix breakdown), score.rovSamples, score.contactInfoValid, score.trend, and the six-month history array.


Conformance Routes

V1 returned a combined payload of participant directory data with pre-aggregated conformance scores in a single call. V2 unifies all programmes behind a single endpoint, filtered by type.

Participant IDs

V1 used a legacy integer id (e.g. "id": 42). V2 uses a UUID string (e.g. "id": "a3ffc8ac-0ea1-4d35-9e2a-906e34341191"). Update any stored ID references accordingly.

Network Operators

GET /api/conformance/net-ops

GET /api/v2/scores/conformance?type=netops

V1 supported Accept: text/csv for CSV output. V2 returns JSON only.

Key field renames between v1 and v2 net-ops rows:

V1 fieldV2 field
id (int64)id (UUID string)
areas_servedregions
ASNsasns
member_sincememberSince
anti_spoofingantiSpoofing
routing_informationroutingInformation
score_irrscoreIRR
score_rpkiscoreRPKI
measurement_datemeasurementDate (top-level response field, present only when type=netops)

IXPs

GET /api/conformance/ixps

GET /api/v2/scores/conformance?type=ixp

Key field renames between v1 and v2 IXP rows:

V1 fieldV2 field
id (int64)id (UUID string)
areas_servedregions
member_sincememberSince
promote_routingpromoteRouting
promote_isp_actionspromoteISPActions
promote_display_manrspromoteDisplayMANRS
promote_incentivespromoteIncentives

V1 returned { prevent, promote_routing, promote_isp_actions } derived from participant status. V2 maps directly:

V1 valueV2 status
conformantconformant
pendingpending
non-conformantnon-conformant

IXP info

GET /api/ixps/info

GET /api/v2/participants?type=ixp&status=approved

V1 returned { name, abbreviation, ids: [{ ixf_id, peering_db_id }] }. V2 returns the full Participant model which includes name, abbreviation, ixfID, and peeringDBID directly on each participant record.


CDNs

GET /api/conformance/cdns

GET /api/v2/scores/conformance?type=cdn

V1 supported Accept: text/csv for CSV output. V2 returns JSON only.

Key field renames between v1 and v2 CDN rows:

V1 fieldV2 field
id (int64)id (UUID string)
ASNsasns
member_sincememberSince
anti_spoofingantiSpoofing
routing_informationroutingInformation
routing_information.IRRroutingInformation.irr
routing_information.RPKIroutingInformation.rpki
filtering.ROVfiltering.rov
filtering.AS-SETfiltering.asSet
MANRS_adoptionmanrsAdoption

Vendors

GET /api/conformance/vendors

GET /api/v2/scores/conformance?type=vendor

Key field renames between v1 and v2 vendor rows:

V1 fieldV2 field
id (int64)id (UUID string)
member_sincememberSince
solution_filteringsolutionFiltering
solution_anti_spoofingsolutionAntiSpoofing
solution_filtering_ixpsolutionFilteringIXP
solution_protect_l2solutionProtectL2
technical_resourcestechnicalResources
hands_onhandsOn

V1 values (implemented, planned, not implemented) are unchanged in V2.


Country / Economy Routes

GET /api/countries/scores/{economy}?month=YYYYMM

GET /api/v2/scores/summary?economies={economy}&month=2025-01-01T00:00:00Z (aggregate readiness + statistics)
GET /api/v2/scores?economies={economy}&month=2025-01-01T00:00:00Z (per-ASN rows)

V1 required authentication (apiKey). The /scores/summary endpoint is public in V2.

For the rolled-up economy aggregate, use /scores/summary with economies set to one or more ISO-2 codes (it also accepts a region slug for UN regions / sub-regions / RIRs). It returns the readiness key figures — each with its mean value and a per-severity breakdown carrying both count and percentage — plus the underlying incidents, culprits, irr, rpki, and rov statistics. For the individual ASN rows (each with its category/action scores and incident counts), use /scores?economies=.


ROA Routes

ROA history (raw ROAs)

GET /api/roa-history?asn=&tal=&sourceDate=

GET /api/v2/roas?asn=&source=&sourceDate=

Same underlying data. Both use cursor-based pagination via pageToken. The tal query parameter is renamed to source in V2. Note that the V1 display name RIPE maps to the canonical source name RIPENCC in V2 — pass source=RIPENCC when querying for RIPE NCC ROAs.


All ROA validation stats (paged)

GET /api/roas?page=&limit=

GET /api/v2/roa-stats

Same underlying data — daily RPKI validation outcomes per prefix/ASN pair (valid, unknown, invalidASN, invalidLength). Key differences:

  • Pagination: V1 used offset-based ?page=&limit=. V2 uses cursor-based pagination via pageToken.
  • IPv4/IPv6 split: V1 returned separate v4 and v6 arrays, each containing nested { asn: {number, name}, country: {name, code}, roa: {prefix, state} } objects. V2 returns a flat stats[] array — filter by ipVersion if a split is needed.
  • State casing: V1 used invalid_asn / invalid_length (snake_case). V2 uses invalidASN / invalidLength (camelCase).
  • Endpoint supports the same filters: asn, sourceDate, and IP prefix.

ROA validation stats by ASN

GET /api/roas/asn/{asn} → GET /api/v2/roa-stats?asn={asn}

V1 returned per-prefix validation records split into v4/v6 arrays. V2 returns the same flat per-prefix records via /roa-stats?asn={asn} with an ipVersion field on each record.

Aggregate vs records

GET /api/v2/stats/roas?asn={asn} is a different endpoint that returns aggregate counts (total valid/unknown/invalid), not individual prefix records. Use /roa-stats?asn={asn} for the per-prefix data equivalent to the v1 route.


ROA validation stats by country

GET /api/roas/country/{country} → GET /api/v2/roa-stats?economy={country}

V1 returned per-prefix records split into v4/v6 arrays for all ASNs in the country. V2 returns the same flat per-prefix records via /roa-stats?economy={country}.

Aggregate vs records

GET /api/v2/stats/roas?economy={country} returns aggregate counts for the scope, not individual prefix records.