Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Identify and link research organizations via the ROR registry API
.claude/skills/brycewang-stanford-ror-organization-api/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | -8% | 0% |
| case-03 | ✗→✓ | ▲ Improved | -54% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 24% | 0% |
| case-20 | ✓→✓ | = Same ✓ | 102% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 68% | 0% |
ROR is the community-led registry of open persistent identifiers for research organizations worldwide — 110,000+ entries covering universities, research institutes, government agencies, hospitals, and companies. The API enables affiliation disambiguation, institutional search, and metadata retrieval. Essential for bibliometrics, funder compliance, and research analytics. Free, no authentication required.
https://api.ror.org/v2bash# Text search curl "https://api.ror.org/v2/organizations?query=MIT" # Affiliation matching (fuzzy match for messy affiliation strings) curl "https://api.ror.org/v2/organizations?affiliation=Dept+of+CS,+Massachusetts+Inst+of+Technology" # Filter by country curl "https://api.ror.org/v2/organizations?query=university&filter=locations.geonames_details.country_code:US" # Filter by organization type curl "https://api.ror.org/v2/organizations?query=research&filter=types:facility"
bash# Retrieve full record curl "https://api.ror.org/v2/organizations/https://ror.org/042nb2s44" # Also works with just the ID portion curl "https://api.ror.org/v2/organizations/042nb2s44"
| Parameter | Description | Example | |-----------|-------------|---------| | query | Text search | query=Harvard | | affiliation | Fuzzy affiliation match | affiliation=MIT Cambridge MA | | filter | Faceted filtering | filter=types:education | | page | Page number (1-based) | page=2 |
| Type | Description | |------|-------------| | education | Universities, colleges | | facility | Research facilities, labs | | healthcare | Hospitals, medical centers | | company | Companies with research activities | | government | Government agencies | | nonprofit | Non-profit research organizations | | funder | Funding agencies | | archive | Archives, libraries |
json{ "number_of_results": 3, "items": [ { "id": "https://ror.org/042nb2s44", "names": [ {"value": "Massachusetts Institute of Technology", "types": ["ror_display"]}, {"value": "MIT", "types": ["acronym"]} ], "types": ["education"], "locations": [ { "geonames_details": { "country_code": "US", "country_name": "United States", "name": "Cambridge" } } ], "external_ids": [ {"type": "isni", "all": ["0000 0001 2341 2786"]}, {"type": "grid", "all": ["grid.116068.8"]}, {"type": "wikidata", "all": ["Q49108"]} ], "links": [{"type": "website", "value": "https://www.mit.edu/"}], "relationships": [ {"id": "https://ror.org/01a8ajp77", "label": "Lincoln Laboratory", "type": "child"} ], "status": "active", "established": 1861 } ] }
pythonimport requests BASE_URL = "https://api.ror.org/v2/organizations" def search_organizations(query: str, country: str = None, org_type: str = None) -> list: """Search ROR for research organizations.""" params = {"query": query} filters = [] if country: filters.append( f"locations.geonames_details.country_code:{country}") if org_type: filters.append(f"types:{org_type}") if filters: params["filter"] = ",".join(filters) resp = requests.get(BASE_URL, params=params) resp.raise_for_status() data = resp.json() results = [] for org in data.get("items", []): display_name = next( (n["value"] for n in org.get("names", []) if "ror_display" in n.get("types", [])), org.get("names", [{}])[0].get("value", ""), ) acronyms = [n["value"] for n in org.get("names", []) if "acronym" in n.get("types", [])] loc = org.get("locations", [{}])[0].get("geonames_details", {}) results.append({ "ror_id": org.get("id"), "name": display_name, "acronyms": acronyms, "types": org.get("types", []), "country": loc.get("country_name"), "city": loc.get("name"), "established": org.get("established"), }) return results def match_affiliation(affiliation_string: str) -> dict: """Disambiguate a messy affiliation string to a ROR record.""" resp = requests.get( BASE_URL, params={"affiliation": affiliation_string}, ) resp.raise_for_status() items = resp.json().get("items", []) if items and items[0].get("chosen"): return items[0].get("organization", {}) return items[0] if items else {} def get_organization(ror_id: str) -> dict: """Get full ROR record for an organization.""" resp = requests.get(f"{BASE_URL}/{ror_id}") resp.raise_for_status() return resp.json() # Example: find German research institutes orgs = search_organizations("Max Planck", country="DE", org_type="facility") for o in orgs: print(f"{o['name']} ({', '.join(o['acronyms'])}) " f"— {o['city']}, {o['country']} (est. {o['established']})") # Example: disambiguate messy affiliations result = match_affiliation( "Dept. of Computer Sci., Stanford Univ., CA, USA") print(f"Matched: {result.get('id')} — " f"{result.get('names', [{}])[0].get('value')}")
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-20 | pass→pass | 6,211 | 2,913 | -53% | 1 | 1 | 0% | 1,063 | 2,143 | +102% | 0 | 0 | — |
case-01 | pass→pass | 15,258 | 17,343 | +14% | 1 | 1 | 0% | 2,539 | 4,257 | +68% | 0 | 0 | — |
case-02 | fail→pass | 20,450 | 13,898 | -32% | 1 | 1 | 0% | 5,090 | 4,685 | -8% | 0 | 0 | — |
case-03 | fail→pass | 51,888 | 10,950 | -79% | 1 | 1 | 0% | 7,793 | 3,619 | -54% | 0 | 0 | — |
case-04 | pass→pass | 3,626 | 1,938 | -47% | 1 | 1 | 0% | 450 | 1,981 | +340% | 0 | 0 | — |
case-05 | pass→pass | 10,552 | 3,170 | -70% | 1 | 1 | 0% | 1,637 | 2,165 | +32% | 0 | 0 | — |
case-06 | pass→pass | 16,358 | 7,343 | -55% | 1 | 1 | 0% | 2,573 | 2,921 | +14% | 0 | 0 | — |
case-07 | pass→pass | 8,695 | 3,110 | -64% | 1 | 1 | 0% | 1,264 | 2,126 | +68% | 0 | 0 | — |
case-08 | pass→pass | 3,536 | 1,844 | -48% | 1 | 1 | 0% | 598 | 2,014 | +237% | 0 | 0 | — |
case-09 | pass→pass | 6,714 | 2,958 | -56% | 1 | 1 | 0% | 1,191 | 2,123 | +78% | 0 | 0 | — |
case-10 | pass→pass | 14,955 | 4,906 | -67% | 1 | 1 | 0% | 2,280 | 2,732 | +20% | 0 | 0 | — |
case-11 | fail→pass | 12,201 | 3,864 | -68% | 1 | 1 | 0% | 1,925 | 2,389 | +24% | 0 | 0 | — |
case-12 | pass→pass | 7,731 | 4,757 | -38% | 1 | 1 | 0% | 1,451 | 2,675 | +84% | 0 | 0 | — |
case-13 | pass→pass | 4,078 | 2,127 | -48% | 1 | 1 | 0% | 614 | 2,083 | +239% | 0 | 0 | — |
case-14 | pass→pass | 9,010 | 11,143 | +24% | 1 | 1 | 0% | 1,555 | 3,312 | +113% | 0 | 0 | — |
case-15 | pass→pass | 5,492 | 2,554 | -53% | 1 | 1 | 0% | 860 | 2,037 | +137% | 0 | 0 | — |
case-16 | pass→pass | 14,178 | 11,318 | -20% | 1 | 1 | 0% | 2,263 | 3,963 | +75% | 0 | 0 | — |
case-17 | pass→pass | 11,191 | 5,319 | -52% | 1 | 1 | 0% | 2,055 | 2,814 | +37% | 0 | 0 | — |
case-18 | pass→pass | 5,362 | 3,901 | -27% | 1 | 1 | 0% | 770 | 2,344 | +204% | 0 | 0 | — |
case-19 | pass→pass | 6,973 | 2,776 | -60% | 1 | 1 | 0% | 1,064 | 2,205 | +107% | 0 | 0 | — |
case-21 | pass→pass | 18,901 | 18,949 | +0% | 1 | 1 | 0% | 3,154 | 4,811 | +53% | 0 | 0 | — |
case-22 | pass→pass | 17,087 | 14,847 | -13% | 1 | 1 | 0% | 2,663 | 4,152 | +56% | 0 | 0 | — |
case-23 | pass→pass | 20,349 | 21,524 | +6% | 1 | 1 | 0% | 3,896 | 5,049 | +30% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +13 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.