ORC API

Developer documentation

ORC rating data for your own software: how many certificates each country has, which certificates are active, the full rating data of a country's fleet or of a single boat, in JSON, RMS or CSV, and a certificate's polar for weather routing.

Base URL https://sas.orc.org/api/{key}/

Quick start

Every request is a GET to https://sas.orc.org/api/{key}/{endpoint}, with the parameters in the query string. To download the rating data of every active standard ORC certificate in Greece, as JSON:

Shell (curl)
curl -o GRE_ORC.json "https://sas.orc.org/api/$ORC_API_KEY/DownRMS?CountryId=GRE&Family=ORC&ext=json"
Python (requests)
import os
import requests

BASE = f"https://sas.orc.org/api/{os.environ['ORC_API_KEY']}"

r = requests.get(f"{BASE}/DownRMS",
                 params={"CountryId": "GRE", "Family": "ORC", "ext": "json"},
                 timeout=120)
r.raise_for_status()
for boat in r.json()["rms"]:
    print(boat["SailNo"], boat["YachtName"], boat["GPH"])
JavaScript (Node.js 18 or later, as an ES module)
const base = `https://sas.orc.org/api/${process.env.ORC_API_KEY}`;

const url = new URL(`${base}/DownBoatRMS_byrefno`);
url.search = new URLSearchParams({ RefNo: "03420004I82", ext: "json" });

const res = await fetch(url);
const body = await res.json();
if (!res.ok) throw new Error(body.errors.join("; "));
console.log(body.rms[0].YachtName, body.rms[0].GPH);

The examples read the key from an environment variable, ORC_API_KEY, so that it never ends up in your source code.

API keys

Getting a key

Keys belong to users of ORC Sailor Services. Register there if you have not already, sign in, and ask for API access on the Developers page, saying briefly what your project is and how it will use the API. ORC e-mails you its answer. Once access is granted, you make your own keys on the same page: as many as five active at a time, one per application, so that each can be replaced on its own. A key may be given an expiry date, and works to the end of that day (UTC). Every new key is announced by e-mail to your account's address.

A key looks like this: orc_ followed by 64 hexadecimal characters.

orc_3f9a1c07e52d4b8e9a61f0c3d7b2e4a58c19f6d03b7e2a4c5d8e1f0a9b3c6d27

You are shown the key once, when you make it. ORC keeps only a fingerprint of it and cannot look it up again: if you lose it, revoke it and make a new one.

Keeping it secret

The key identifies you: anyone who has it can use the API in your name.

  • Call the API from your server, never from a web page or an app you distribute. The API sends no CORS headers, so browsers refuse to let web pages on other sites read its responses.
  • Keep the key out of source control; read it from configuration or an environment variable.
  • The key is part of the URL, so it appears wherever URLs are recorded: server and proxy logs, error reports. Do not log full request URLs.
  • If a key may have leaked, revoke it on the Developers page and make a new one.

When a key stops working

A key is refused (401) once it is revoked (by you or by ORC), once its expiry date has passed if it was given one, or while API access is withdrawn from the account that holds it.

Making requests

GET https://sas.orc.org/api/{key}/{endpoint}?{parameters}
  • GET only. Any other method is answered with 405.
  • HTTPS. The key travels in the URL; always use https://.
  • Names are not case-sensitive, neither endpoint names nor parameter names: DownRMS and downrms, CountryId and countryid are the same. Nor are values that are codes: GRE or gre, DH or dh.
  • Patterns. Parameters marked pattern below match like SQL LIKE: % stands for any run of characters and _ for a single character; without either, the value must match in full. YachtName=PEG% finds PEGA and PEGASUS. Remember to URL-encode: % is written %25 in a query string.
  • Parameters that are not recognised are ignored. Parameters described as numbers must be numbers. The one exception is format, where a value the service does not know is an error rather than a different answer than you asked for.

Responses and errors

Four endpoints answer with a JSON document (RMS, activecerts, country-fleet, sssdataex) — and three of those four will answer XML instead, if you ask for it; the three Down… endpoints answer with a file, sent with a Content-Disposition: attachment header that names it, in the format you ask for with ext; advanced-polar answers with plain text. All text is UTF-8; dates are ISO 8601.

Status codes

Status Meaning
200 Success. A query that matches nothing is a success too: you get an empty list or a file with no certificates in it, not a 404. The exception is advanced-polar, where an empty answer could pass for a polar.
400 The request cannot be answered as asked; the message says why.
401 The key is missing, malformed, unknown, revoked or expired, or API access has been withdrawn from its account.
404 No such endpoint; the message lists the endpoints there are. For advanced-polar, also: no certificate with that RefNo.
405 A method other than GET.
500 The service failed. Try again later; if it persists, tell ORC.

Error body

Every error comes as JSON, with an errors array of messages:

HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=UTF-8

{
  "errors": [
    "Missing or invalid API key."
  ]
}

XML instead of JSON

format=xml on RMS, activecerts and sssdataex answers with the XML document ORC's older web service has long served for the same data, so that a program written against it can be pointed here unchanged. The rows carry the same column names and the same values as the JSON; only the wrapping differs.

GET /api/{key}/sssdataex?CountryId=GRE&VPPYear=2026&format=xml (one row, trimmed)
HTTP/1.1 200 OK
Content-Type: text/xml; charset=UTF-8

<?xml version="1.0" encoding="UTF-8"?>
<ROOT>
  <DATA>
    <ROW RowNum="1">
      <CountryId>GRE</CountryId>
      <dxtID>247085</dxtID>
      <RefNo>03420004HJ7</RefNo>
      <dxtDate>2026-03-12T14:30:45.000Z</dxtDate>
      <GPH>587.2</GPH>
      <Area_Sym></Area_Sym>
      …
    </ROW>
    …
  </DATA>
  <ERRORS/>
</ROOT>
  • Rows are ROW elements under DATA, numbered from 1 in RowNum, with one child element per column. RMS puts its certificate types and families beside them, in CTyp and CFam.
  • An empty column is an empty element (<Area_Sym></Area_Sym>) where the JSON has null, and a true/false column reads True or False.
  • Errors go in ERRORS, as ERROR elements, under the same status code the JSON answer would carry. The node is there, empty, when all went well.
  • The other endpoints have no XML answer. format=xml on country-fleet, advanced-polar or a Down… endpoint — whose format is already ext's to choose — is answered with 400.
  • format=json may be written out, and is what you get in any case. Any other value is a 400.

Families, types and countries

Certificate families

Wherever a parameter takes a Family, it accepts the number or the code, except activecerts, which takes only the number.

Number Code Family
1 ORC ORC Standard
2 SY Super Yacht
3 DH Double Handed
4 MU Multihull
5 NS Non Spinnaker
6 LI Light

Certificate types

Each certificate has a type within its family. The RMS endpoint returns this list as ctyp.

CertType RMSCode Name Family
2 INTL International 1 ORC
3 CLUB Club 1 ORC
12 JAYC J Class 1 ORC
4 SYIN Super Yacht Measured 2 SY
5 SYCL Super Yacht Declared 2 SY
1 SYCR Super Yacht Corinthian Spirit 2 SY
8 DHIN Double-Handed International 3 DH
9 DHCL Double-Handed Club 3 DH
6 MUIN Multihull International 4 MU
7 MUCL Multihull Club 4 MU
14 MUMC MOCRA 4 MU
10 NSIN Non-Spinnaker International 5 NS
11 NSCL Non-Spinnaker Club 5 NS
13 LITE Light 6 LI

Countries

Certificates are issued by national rating offices, identified by a three-letter CountryId such as GRE, ITA or USA. A few identifiers are not countries: SY_ for super yachts, MU_ for multihulls, ODD for one-design classes. The RMS endpoint tells you which countries have certificates, and every JSON rating file carries the list of rating offices as Countries.

Certificates and boats

Every certificate has a reference number, RefNo, unique to it: no two certificates share one, and a boat's next certificate gets a new one. A boat can hold several certificates over the years, in more than one family. ORC does not number boats; in general a boat is the issuing country together with its certificate file name: CountryId and dxtName (also called BIN).

Endpoints

Eight endpoints, each described below with its parameters and a sample answer.

GET/api/{key}/RMSJSON or XML

How many active certificates there are, by country, family, certificate type and VPP year, with totals. Use it to see which countries and years have data before downloading.

Parameters

Name Value Description
Family
optional
number or code Only this family. Without it, every family except super yachts.
RMSCode
optional
- A minus sign returns only the totals across certificate types (the rows whose CertType is null). CertType is accepted as the same parameter.
includesy
optional
yes When no Family is given, count super yachts too.
format
optional
code xml for the legacy XML document in place of JSON. The default is json; any other value is a 400.

Response

data.rows holds the counts. A null in Family, CertType or VPPYear marks a total over that column: the row with both CertType and VPPYear null is the country's total for the family. LastUpdate is when the country last issued a certificate in that family. data.ctyp and data.cfam are the certificate types and families; readme is a short plain-text note.

GET /api/{key}/RMS?Family=ORC (trimmed)
{
  "data": {
    "rows": [
      { "CountryId": "GRE", "Family": 1, "CertType": 2, "VPPYear": 2026, "CertCount": 15,
        "CountryName": "Greece", "LastUpdate": "2026-03-18T15:49:08.000Z",
        "CertName": "International", "RMSCode": "INTL" },
      { "CountryId": "GRE", "Family": 1, "CertType": 3, "VPPYear": 2026, "CertCount": 84,
        "CountryName": "Greece", "LastUpdate": "2026-03-18T15:49:08.000Z",
        "CertName": "Club", "RMSCode": "CLUB" },
      { "CountryId": "GRE", "Family": 1, "CertType": null, "VPPYear": null, "CertCount": 99,
        "CountryName": "Greece", "LastUpdate": "2026-03-18T15:49:08.000Z",
        "CertName": null, "RMSCode": null },
      …
    ],
    "ctyp": [ { "CertType": 2, "CertName": "International", "RMSCode": "INTL", "Family": 1,
                "Title": "International", "StatCode": null }, … ],
    "cfam": [ { "Family": 1, "FamilyName": "ORC Standard" }, … ]
  },
  "readme": "…"
}

GET/api/{key}/activecertsJSON or XML

The active certificates that match every criterion given, one row each: who the boat is and which certificate it holds, without the rating data. Use it to find the RefNo of a boat's certificate, then fetch its data with DownBoatRMS_byrefno or its polar with advanced-polar.

Parameters

All optional, combined with AND.

Name Match Description
Family number Family number, 1–6. Codes such as ORC are not accepted here and match nothing.
VPPYear number VPP year of the certificate, e.g. 2026.
CountryId exact Issuing country.
RefNo exact Certificate reference number.
YachtName pattern Boat name.
SailNo pattern Sail number, as on the certificate, e.g. GRE-970.
Class pattern Boat type or class.
format
optional
code xml for the legacy XML document in place of JSON. The default is json; any other value is a 400.

With no parameters you get every active certificate there is: several thousand rows. Filter by country and year whenever you can.

Response

GET /api/{key}/activecerts?CountryId=GRE&Family=1&VPPYear=2026 (trimmed)
{
  "data": {
    "rows": [
      {
        "Family": 1,
        "CountryId": "GRE",
        "dxtID": 246855,
        "RefNo": "03420004HB1",
        "dxtDate": "2026-03-10T16:44:39.000Z",
        "dxtName": "GR803.dxt",
        "YachtName": "FAETHON",
        "SailNo": "GRE-803",
        "VPPYear": 2026,
        "CertType": 3,
        "Expiry": "2026-12-31T00:00:00.000Z",
        "IsOd": false,
        "Class": "MOODY 30",
        "CertName": "Club",
        "FamilyName": "ORC Standard"
      },
      …
    ]
  }
}
Field Meaning
RefNo The certificate's reference number, unique to it.
dxtID ORC's internal number for this particular certificate.
dxtName Certificate file name.
dxtDate When the certificate was issued.
Expiry When it expires.
IsOd Whether it is a one-design certificate.
CertType, CertName, Family, FamilyName The certificate's type and family.

GET/api/{key}/DownRMSfile

The rating data of every active certificate of one family in a country: what a scoring program loads before an event.

Parameters

Name Value Description
CountryId
required
exact Issuing country.
Family
default ORC
number or code The family.
VPPYear
optional
number Only certificates of this VPP year. Give it with rms and csv: see the note on the header row.
ext
default rms
json, rms, csv The format.

Response

A file named {CountryId}_{Family}.{ext}, e.g. GRE_ORC.json. As JSON it holds rms, the certificates, plus Countries and ScoringOptions (see JSON). A country with no certificates gives an empty rms list.

Request
GET https://sas.orc.org/api/{key}/DownRMS?CountryId=GRE&Family=ORC&VPPYear=2026&ext=json

GET/api/{key}/DownBoatRMSfile

The rating data of one boat: the newest active certificate that matches every criterion given. It never returns more than one certificate.

Parameters

Name Match Description
RefNo pattern Certificate reference number. When given, all the criteria below except ext are ignored.
CountryId pattern Issuing country. NatAuth is accepted as the same parameter.
YachtName pattern Boat name.
SailNo pattern Sail number, e.g. GRE-970.
dxtName pattern Certificate file name. .dxt is added unless the value already ends with .dxt or %. BIN is accepted as the same parameter.
Family number or code The family; default ORC.
ext json, rms, csv The format; default rms.

With loose criteria many certificates can match, and you get the newest of them, which may not be the boat you meant. Give enough to identify the boat, or better, its RefNo, and check YachtName and SailNo in the answer.

Response

A file named ORC.{ext}. As JSON: rms with the one certificate, plus Countries and ScoringOptions. When nothing matches, rms is empty (in rms and csv, only the header row is there).

Request
GET https://sas.orc.org/api/{key}/DownBoatRMS?CountryId=GRE&SailNo=GRE-970&ext=json

GET/api/{key}/DownBoatRMS_byrefnofile

The rating data of the certificate with this reference number, whether or not it is still active. A RefNo belongs to one certificate only, so the file holds at most one.

Parameters

Name Value Description
RefNo
required
exact Certificate reference number.
ext
required
json, rms, csv The format. There is no default here: without ext the file is empty.
VPPYear
optional
number Return the certificate only if it is of this VPP year.

Response

A file named {RefNo}.{ext}. As JSON it holds only rms, without Countries and ScoringOptions. An unknown RefNo, or a certificate of another VPP year than the one asked for, gives {"rms":[]}.

Request
GET https://sas.orc.org/api/{key}/DownBoatRMS_byrefno?RefNo=03420004I82&ext=json

GET/api/{key}/advanced-polarplain text

The polar of one certificate: the boat's speed at each true wind speed and angle, worked out from the certificate's rating data, in the tab-separated table that weather routing software reads. It is the same polar ORC's weather routing service sends to PredictWind.

Parameters

Name Value Description
RefNo
required
exact The certificate's reference number, active or not.

Response

text/plain; charset=UTF-8, sent as it is, not as a download. No header row; one line per true wind speed in knots: first 1, 2 and 3 knots, extended below the lowest wind speed on the certificate, then each wind speed of the certificate. Each line is the wind speed followed by pairs of true wind angle (degrees) and boat speed (knots), in order of angle, all separated by tabs. Lines end with LF, and decimals use a point. The angles are not the same on every line, since the best beat and gybe angles change with the wind.

Errors come as JSON like everywhere else. A RefNo with no certificate gives 404.

GET /api/{key}/advanced-polar?RefNo=03420004HB5 (lines 4 to 11 left out)
1	0	0	47.7	0.91	52	1.01	60	1.14	75	1.24	90	1.19	110	1.14	120	1.09	135	0.93	138.7	0.88	150	0.7	165	0.58	180	0.53
2	0	0	47.7	1.8	52	1.98	60	2.21	75	2.39	90	2.29	110	2.22	120	2.13	135	1.83	138.7	1.75	150	1.41	165	1.16	180	1.07
3	0	0	47.7	2.67	52	2.9	60	3.2	75	3.43	90	3.31	110	3.24	120	3.12	135	2.71	138.7	2.59	150	2.13	165	1.76	180	1.61
…
24	0	0	40.2	7.27	52	7.97	60	8.25	75	8.77	90	9.29	110	10.12	120	10.98	135	11.62	150	10.62	164.9	9.71	165	9.67	180	9.3

GET/api/{key}/country-fleetJSON

The boats of one country, one row each: who the boat is, from its newest certificate, whether that certificate is still active or not. Use it for a list of a country's boats; activecerts is the one to use for certificates that are currently valid.

Parameters

Name Match Description
CountryId
required
exact Issuing country. Not needed when search is a reference number, which names one certificate in the whole database; given with one anyway, it is ignored.
search
optional
text Finds the boat someone is choosing: a whole reference number — 11 characters, looked up among every certificate there is — or else a boat name or sail number, matched anywhere inside either, within the country. A search answers at most 100 rows. Without it, the whole country comes back, however many boats that is.

Response

One row per boat, in order of dxtName. A boat is its country and its certificate file name together, so a boat appears once however many certificates it has held. VPPYear is the VPP year of the certificate the row was taken from, and the rest is as that certificate has it; Designer and Builder can be null. A country with no boats gives an empty list.

A search that is a reference number answers with certificates instead of boats, in the same columns — so one boat can come back more than once, and a number that was issued twice and corrected answers with every certificate that carries it (the correction adds -2 or -3). Part of a reference number is not one: it is matched against names and sail numbers like any other text. Searches are not case-sensitive, and % and _ in a search are matched as themselves, not as wildcards. A reference number that matches no certificate falls back to the name and sail number, so a sail number of 11 characters still finds its boat — but only when a country was given, since there is no fleet to search without one.

more says whether a search had more to give: true means it matched over 100 boats and you are seeing the first 100, in dxtName order — ask the user for a longer search rather than a longer list. A whole country is never cut, and answers "more": false.

GET /api/{key}/country-fleet?CountryId=GRE (trimmed)
{
  "data": {
    "rows": [
      {
        "CountryId": "GRE",
        "dxtName": "GR016.dxt",
        "YachtName": "AETHER",
        "SailNo": "GRE-016",
        "VPPYear": 2026,
        "Class": "DEHLER 30 OD",
        "Designer": "JUDEL FRIEDRICH / VROELIJK ROLF",
        "Builder": "DEHLER"
      },
      …
    ],
    "more": false
  }
}

GET/api/{key}/sssdataexJSON or XML

The scratch-sheet data of one country and VPP year: each certificate's identity with the measurements and single numbers a scratch sheet shows — GPH, CDL, APHD, TMF_Inshore, ILCWA, the displacements, the sail areas and the rest, 41 columns in all.

Parameters

Name Value Description
CountryId
required
exact Issuing country.
VPPYear
required
number VPP year of the certificate, e.g. 2026.
family
optional
number Family number, 1–6. Anything else is ignored, and every family comes back.
override
optional
code Certificate type. International is IMS here, not the INTL of RMSCode; the others are the same codes (CLUB, DHIN, DHCL, NSIN, NSCL, SYIN, SYCL, SYCR, MUIN, MUCL, MUMC, JAYC, LITE). A code it does not know is ignored, and every type comes back.
sort
optional
columns The order of the rows: column names separated by commas, each with an optional DESC (GPH DESC, Class,SailNo). A sort naming a column the answer has not got is ignored.
format
optional
code xml for the legacy XML document in place of JSON. The default is json; any other value is a 400.

Response

One row per certificate. A country and year with none gives an empty list. Without sort the order is the database's own, which is not guaranteed: ask for the order you want.

GET /api/{key}/sssdataex?CountryId=GRE&VPPYear=2026&override=IMS (one row, trimmed)
{
  "data": {
    "rows": [
      {
        "CountryId": "GRE",
        "dxtID": 247085,
        "RefNo": "03420004HJ7",
        "VPPYear": 2026,
        "dxtName": "GR046.dxt",
        "YachtName": "OPTIMUM 4",
        "Class": "DEHLER 30 OD",
        "SailNo": "GRE-046",
        "Club": "NOK",
        "dxtDate": "2026-03-12T14:30:45.000Z",
        "Override": "IMS",
        "Division": "R",
        "GPH": 587.2,
        "Family": 1,
        "CertType": 2,
        …
        "CDL": 8.893,
        "APHD": 527.9946
      },
      …
    ]
  }
}

Rating data formats

The Down… endpoints give the same data in three formats. JSON is the one to use in new software; rms and csv exist for programs that already read them.

json

UTF-8, without a byte order mark. One object per certificate in rms, each with a few hundred fields. When metric is true, measurements are in metres, square metres and kilograms.

One certificate (trimmed)
{
  "rms": [
    {
      "NatAuth": "GRE",
      "BIN": "GR1925",
      "CertNo": "01969",
      "RefNo": "03420004HB7",
      "SailNo": "GRE-1925",
      "YachtName": "STELLA",
      "Class": "SUN ODYSSEY 42i SD",
      "Builder": "JEANNEAU",
      "Designer": "LOMBARD",
      "C_Type": "CLUB",
      "Family": "ORC",
      "Division": "C",
      "IssueDate": "2026-03-10T17:00:24.885Z",
      "LOA": 12.526,
      "Dspl_Sailing": 9550,
      "CDL": 9.435,
      "GPH": 660.8,
      "APHD": 578,
      "APHT": 1.0381,
      "OSN": 635.9,
      "TMF_Inshore": 0.8141,
      "TMF_Offshore": 0.9435,
      "TND_Offshore_Low": 804,
      "TN_Offshore_Low": 0.7463,
      …
      "GRE_S_AP_TOD": …,
      "Allowances": {
        "WindSpeeds": [4, 6, 8, 10, 12, 14, 16, 20, 24],
        "WindAngles": [52, 60, 75, 90, 110, 120, 135, 150],
        "R52":  [1228.4, 825.3, 658.9, 572.6, 521.1, 493.2, 480, 474.7, 480.6],
        …
        "Beat": [1973.3, 1312.9, 1031, 881.5, 790.7, 740, 719.5, 714.7, 737.9],
        …
      }
    }
  ],
  "Countries": [
    { "CountryId": "ORC", "Name": "Offshore Racing Congress" },
    { "CountryId": "AUS", "Name": "Australia" },
    …
  ],
  "ScoringOptions": [
    { "Families": ["ORC", "SY", "DH", "Mu", "NS", "LI"], "CountryId": "ORC",
      "Kind": "TOD", "Fieldname": "APHD", "Name": "All Purpose" },
    { "Families": ["ORC", "SY", "DH", "NS"], "CountryId": "GRE",
      "Kind": "PCS", "Fieldname": "OC", "Name": "Coastal/Long Distance" },
    …
  ]
}

The certificate

  • Identity: NatAuth (issuing country), BIN, CertNo, RefNo, SailNo, YachtName, Class, Builder, Designer, Club, C_Type (certificate type code), Family, Division, IssueDate.
  • Measurements: LOA, IMSL, Draft, MB, Dspl_Sailing, Dspl_Measurement, WSS, the sail areas Area_Main, Area_Jib, Area_Sym, Area_Asym, CrewWT, Age_Year, CDL.
  • Single-number ratings, as printed on the certificate: GPH, APHD and APHT, OSN, TMF_Inshore and TMF_Offshore, the triple numbers TND_… (time on distance) and TN_… (time on time) for offshore and inshore, low, medium and high wind, and the predicted-course values Pred_Up_… and Pred_Down_….
  • National options: fields prefixed with a country, such as US_…, IRL_… or GRE_…, are ratings for that country's own scoring options.
  • Allowances: time allowances in seconds per mile. Each array has one value per wind speed in WindSpeeds (knots). R52 to R150 are for each true wind angle in WindAngles (degrees); Beat and Run are the upwind and downwind VMG allowances, BeatAngle and GybeAngle the optimum angles; WL, CR and OC are the course models used by Performance Curve Scoring.

Countries and ScoringOptions

Countries lists the rating offices. ScoringOptions lists the scoring options each office offers (CountryId ORC for the international ones): Kind is TOD (time on distance), TOT (time on time) or PCS (Performance Curve Scoring), and Fieldname names the certificate field that holds the value to score with, or for PCS the array in Allowances. Families lists the families the option applies to.

rms

The fixed-width text format read by scoring programs: a header row naming the columns, then one line per certificate. UTF-8 with a byte order mark, CRLF line ends.

NATCERTN.FILE_ID SAILNUMB    NAME                    TYPE              BUILDER           DESIGNER          YEAR …
GRE00764 GR2115  GRE-2115    SELINI                  HALLBERG-RASSY 382HALLBERG-RASSY    ENDERLEIN         1984 …

csv

The same columns, comma-separated, with a header row; text values that need it are in double quotes, and numbers use a point as the decimal separator. UTF-8 with a byte order mark, CRLF line ends.

Give VPPYear with rms and csv. Certificates from VPP 2025 onwards carry allowances for 4 knots of wind, in extra columns. The header row of a DownRMS or DownBoatRMS_byrefno file names those columns only when the request gives a VPPYear of 2025 or later; without it, the header is shorter than the rows. DownBoatRMS and the json format are not affected.

Good practice

  • Download what you need, and keep it. Filter by country, family and VPP year, and cache the files you fetch rather than asking again for every page view. Certificates change only when one is issued or revised.
  • Allow time for large files. A country file can take a few seconds; set your HTTP timeout accordingly.
  • Read fields by name and ignore the ones you don't know. New fields are added from time to time, such as the 4-knot allowances in 2025.
  • Treat an empty result as an answer. No match gives 200 with an empty list, not an error, except from advanced-polar.
  • Requests are recorded per key and endpoint.

Last updated 21 September 2026.