Open Source Projects — entry 004 of 8

Drupal.org

Verified Jul 2026

Drupal.org exposes its community project and node data through a legacy Drupal 7 REST endpoint (`drupal.org/api-d7/node.json`); a live unauthenticated GET returned a 200 JSON body with `Access-Control-Allow-Origin: *`, resolving cors "unknown" to "yes". It's a free community resource run by the nonprofit Drupal Association, with no authentication or paid tier for reading published project data.

Drupal.org exposes its own project/issue/user data through a legacy Drupal 7 REST endpoint. A live GET to `/node.json?limit=1` returned a 200 JSON body with `self`/`first`/`last`/`next` pagination links plus a `list` array of full node objects, and `access-control-allow-origin: *` with `access-control-allow-methods: GET, OPTIONS` confirmed keyless cross-origin access — both reconfirmed by this run's own probe.

cmsopen-sourcecommunitydrupalkeyless
AuthenticationNone requiredCall it straight away — no key, no signup.
HTTPSSupportedTraffic is encrypted in transit.
CORSEnabledCallable directly from browser JavaScript.
PricingFreeNo paid tier — free for the documented use case.
FormatsJSONResponses can be requested as JSON.

GreatAPIs Score

Score74out of 100
Authentication25/25No authentication required
Pricing20/20Free to use
Docs0/20No docs or spec available
Formats9/15Single response format
Freshness20/20Verified within 6 months

Embed this badge

Scored 74 on greatapis.com
<a href="https://greatapis.com/api/drupal-org/"><img src="https://greatapis.com/badge/drupal-org.svg" alt="Scored 74 on greatapis.com"></a>

Auth quickstart

  1. No API key or signup required to read published node data — every probe in this file returned real records with no auth header sent at all.
Stored keyNo key stored

Your key is stored only in this browser (localStorage) and sent directly to the API — never to greatapis.

List the oldest surviving node

GEThttps://www.drupal.org/api-d7/node.json?limit=1

200 application/json

{"self":"https:\/\/www.drupal.org\/api-d7\/node?limit=1","first":"https:\/\/www.drupal.org\/api-d7\/node?limit=1\u0026page=0","last":"https:\/\/www.drupal.org\/api-d7\/node?limit=1\u0026page=2203092","next":"https:\/\/www.drupal.org\/api-d7\/node?limit=1\u0026page=1","list":[{"body":{"value":"\u003Cp\u003Ethe \u0022teaser\u0022 \/ \u0022read more\u0022 handling doesnt work properly - the index page shows \/complete\/ articles, not just teasers and the \u0022read more\u0022 link.\u003C\/p\u003E\n\u003Cp\u003Ereason: function node($node, $main = 0) in sunflower.theme is missing something like\u003C\/p\u003E\n\u003Cpre class=\u0022codeblock\u0022\u003E\u003Ccode class=\u0022language-php\u0022\u003Eif ($main \u0026amp;\u0026amp; $node-\u0026gt;teaser) {\n  echo check_output($node-\u0026gt;teaser, 1);\n}\nelse {\n  echo check_output($node-\u0026gt;body, 1);           \n}\n\n\u003C\/code\u003E\u003C\/pre\u003E\u003Cp\u003E(this is from unconed.theme)\u003C\/p\u003E","summary":"","format":"1"},"taxonomy_vocabulary_9":[],"field_issue_status":"7","field_issue_priority":"200","field_issue_category":"1","field_issue_component":"Code","field_issue_assigned":{"uri":"https:\/\/www.drupal.org\/api-d7\/user\/2","id":"2","resource":"user"},"field_project":{"uri":"https:\/\/www.drupal.org\/api-d7\/node\/3060","id":"3060","resource":"node"},"field_issue_files":[],"field_issue_related":[],"field_issue_version":null,"field_issue_last_status_change":"1008695516","field_issue_parent_link":[],"field_issue_related_links":[],"flag_project_issue_follow_user":[{"uri":"https:\/\/www.drupal.org\/api-d7\/user\/2","id":2,"resource":"user"},{"uri":"https:\/\/www.drupal.org\/api-d7\/user\/8","id":8,"resource":"user"}],"nid":"15","vid":"2897929","is_new":false,"type":"project_issue","title":"sunflower.theme: incorrect \u0022teaser\u0022 \/ \u0022read more\u0022 handling","language":"und","url":"https:\/\/www.drupal.org\/project\/drupal\/issues\/15","edit_url":"https:\/\/www.drupal.org\/node\/15\/edit","status":"1","promote":"0","sticky":"0","created":"1008695516","changed":"1010515673","author":{"uri":"https:\/\/www.drupal.org\/api-d7\/user\/8","id":"8","resource":"user","name":"ax"},"comment":"2","comments":[{"uri":"https:\/\/www.drupal.org\/api-d7\/comment\/287095","id":287095,"resource":"comment"},{"uri":"https:\/\/www.drupal.org\/api-d7\/comment\/287096","id":287096,"resource":"comment"}],"comment_count":"2","comment_count_new":false,"feeds_item_guid":null,"feeds_item_url":null,"feed_nid":null,"flag_flag_tracker_follow_user":[],"flag_tracker_follower_count":"2","has_new_content":null,"last_comment_timestamp":"1741978025"}]}

Captured byte-for-byte from this run's live probe, reconfirmed stable on a repeat call a second later (same node id 15 both times — the default listing sorts node id ascending, and 15 is one of the lowest surviving ids). The `last`/`next` page numbers (2203092/1) will drift upward over time as new nodes are created; the node object shape and the pagination envelope are what's stable. Note every URL and `/` inside the body is JSON-escaped as `\/`, and HTML entities inside the issue body text (`\u003Cp\u003E`, `\u0026amp;`) are Unicode-escaped rather than left as raw `<`/`&` — real behavior of Drupal 7's JSON serializer, not a formatting artifact of this capture.

Developer reference

Base URLhttps://www.drupal.org/api-d7

Gotchas & limits

  • The pagination links the API itself returns aren't directly usable: `next` above is `https://www.drupal.org/api-d7/node?limit=1&page=1` — note the missing `.json` suffix. A live GET to that exact bare URL returned `HTTP 404` with `content-type: text/html; charset=utf-8` (a rendered Drupal 404 page, not a JSON error) — `.json` must be re-inserted before the URL the API gave you will actually work.
  • An unrecognized `type` filter doesn't error, it returns an empty result set: a live GET to `/node.json?type=zzznotarealtype&limit=1` returned `HTTP 200` with body `{"self":"https:\/\/www.drupal.org\/api-d7\/node?type=zzznotarealtype\u0026limit=1","first":"https:\/\/www.drupal.org\/api-d7\/node?type=zzznotarealtype\u0026limit=1\u0026page=0","last":"https:\/\/www.drupal.org\/api-d7\/node?type=zzznotarealtype\u0026limit=1\u0026page=0","list":[]}` — the full pagination envelope is present even though nothing matched.
  • A nonexistent node id doesn't 404, it returns a near-empty stub object: a live GET to `/node/999999999.json` returned `HTTP 200` with body `{"comments":[],"body":[],"flag_flag_tracker_follow_user":[]}` — three empty arrays and nothing else, not an error envelope and not the 404 a REST client would expect for a missing resource.
  • Every URL embedded in a response body comes back JSON-escaped: the `self`/`first`/`last`/`next` links and every nested `uri` field above render slashes as `\/` (e.g. `https:\/\/www.drupal.org\/api-d7\/node?limit=1`) — valid JSON, but a client doing naive string matching against an un-escaped URL will miss.