<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Noble Ronin</title>
    <description>The latest articles on DEV Community by Noble Ronin (@ronin13).</description>
    <link>https://dev.to/ronin13</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4027486%2F6ad6877d-ae73-4dab-8cfd-d6f408944c56.png</url>
      <title>DEV Community: Noble Ronin</title>
      <link>https://dev.to/ronin13</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ronin13"/>
    <language>en</language>
    <item>
      <title>Clinical Trials Data Has a Free JSON API — Every Study on ClinicalTrials.gov, No Key Required</title>
      <dc:creator>Noble Ronin</dc:creator>
      <pubDate>Mon, 03 Aug 2026 06:47:49 +0000</pubDate>
      <link>https://dev.to/ronin13/clinical-trials-data-has-a-free-json-api-every-study-on-clinicaltrialsgov-no-key-required-1pek</link>
      <guid>https://dev.to/ronin13/clinical-trials-data-has-a-free-json-api-every-study-on-clinicaltrialsgov-no-key-required-1pek</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjkckjufuysaawpwtsi3v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjkckjufuysaawpwtsi3v.png" alt="Clinical Trials Data Has a Free JSON API" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've ever needed to know which drugs are in trial for a given condition, who's sponsoring a study, or whether a trial is still recruiting, you don't need to scrape the ClinicalTrials.gov website. The US National Library of Medicine runs an official &lt;strong&gt;v2 API&lt;/strong&gt; over its registry of &lt;strong&gt;500,000+ studies&lt;/strong&gt; — free, public, and &lt;strong&gt;keyless&lt;/strong&gt;. No sign-up, no token, no rate-limit tier to unlock.&lt;/p&gt;

&lt;h2&gt;
  
  
  The base
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://clinicaltrials.gov/api/v2/studies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything is a &lt;code&gt;GET&lt;/code&gt; against that one endpoint with different query parameters — no auth header, no API key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://clinicaltrials.gov/api/v2/studies?query.cond=diabetes&amp;amp;pageSize=5"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Query parameters
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Param&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;query.cond&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Condition / disease (Essie expression syntax).&lt;/td&gt;
&lt;td&gt;&lt;code&gt;query.cond=lung+cancer&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;query.intr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Intervention / drug / treatment.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;query.intr=semaglutide&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;query.spons&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lead sponsor or collaborator name.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;query.spons=Pfizer&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;query.term&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Free-text search across fields (same expression syntax).&lt;/td&gt;
&lt;td&gt;&lt;code&gt;query.term=obesity+AND+phase2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;filter.overallStatus&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Comma-separated status filter.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;filter.overallStatus=RECRUITING&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pageSize&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Studies per page — default &lt;strong&gt;10&lt;/strong&gt;, max &lt;strong&gt;1000&lt;/strong&gt;. Always set it explicitly.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pageSize=100&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pageToken&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cursor for the next page, taken from &lt;code&gt;nextPageToken&lt;/code&gt; in the previous response — &lt;strong&gt;not&lt;/strong&gt; a numeric offset.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pageToken=abc123&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;countTotal&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Set &lt;code&gt;true&lt;/code&gt; on the first request to get a &lt;code&gt;totalCount&lt;/code&gt; in the response.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;countTotal=true&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fields&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Comma-separated field list, to shrink the payload when you don't need everything.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fields=NCTId,BriefTitle,OverallStatus&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Recruiting trials for a specific drug, with a total count&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://clinicaltrials.gov/api/v2/studies?query.intr=semaglutide&amp;amp;filter.overallStatus=RECRUITING&amp;amp;pageSize=20&amp;amp;countTotal=true"&lt;/span&gt;

&lt;span class="c"&gt;# Trials sponsored by a specific company&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://clinicaltrials.gov/api/v2/studies?query.spons=Pfizer&amp;amp;pageSize=50"&lt;/span&gt;

&lt;span class="c"&gt;# Free-text search, narrower payload via `fields`&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://clinicaltrials.gov/api/v2/studies?query.term=obesity+AND+phase2&amp;amp;fields=NCTId,BriefTitle,OverallStatus,LeadSponsorName"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A response looks like this (field names abbreviated for readability — the real payload nests everything under &lt;code&gt;protocolSection&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"studies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"protocolSection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"identificationModule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"nctId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NCT07091500"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"briefTitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GLP-1 Receptor Agonist for Obesity"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"statusModule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"overallStatus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RECRUITING"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"sponsorCollaboratorsModule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"leadSponsor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Example University"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nextPageToken"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJ2IjoxfQ"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"totalCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1234&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(The &lt;code&gt;1234&lt;/code&gt; above is a placeholder — run the &lt;code&gt;countTotal=true&lt;/code&gt; call yourself to get the live figure for your query; it changes as new trials are registered.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Page through everything
&lt;/h2&gt;

&lt;p&gt;Pagination is &lt;strong&gt;cursor-based&lt;/strong&gt;, not offset-based — grab &lt;code&gt;nextPageToken&lt;/code&gt; from each response and pass it back as &lt;code&gt;pageToken&lt;/code&gt; until the field is absent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://clinicaltrials.gov/api/v2/studies?query.cond=diabetes&amp;amp;pageSize=1000&amp;amp;pageToken=eyJ2IjoxfQ"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What's in a study record
&lt;/h2&gt;

&lt;p&gt;Each study nests into modules — the ones people actually query for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identity&lt;/strong&gt; — &lt;code&gt;nctId&lt;/code&gt;, &lt;code&gt;briefTitle&lt;/code&gt;, &lt;code&gt;officialTitle&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Status &amp;amp; design&lt;/strong&gt; — &lt;code&gt;overallStatus&lt;/code&gt;, &lt;code&gt;phases&lt;/code&gt;, &lt;code&gt;studyType&lt;/code&gt;, &lt;code&gt;enrollmentInfo.count&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dates&lt;/strong&gt; — &lt;code&gt;startDateStruct&lt;/code&gt;, &lt;code&gt;completionDateStruct&lt;/code&gt;, &lt;code&gt;lastUpdatePostDateStruct&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sponsors&lt;/strong&gt; — &lt;code&gt;leadSponsor.name&lt;/code&gt;, &lt;code&gt;collaborators[].name&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clinical&lt;/strong&gt; — &lt;code&gt;conditions[]&lt;/code&gt;, &lt;code&gt;interventions[]&lt;/code&gt; (typed, e.g. &lt;code&gt;DRUG: Semaglutide&lt;/code&gt;), &lt;code&gt;briefSummary&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eligibility&lt;/strong&gt; — &lt;code&gt;sex&lt;/code&gt;, &lt;code&gt;minimumAge&lt;/code&gt;, &lt;code&gt;maximumAge&lt;/code&gt;, &lt;code&gt;healthyVolunteers&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Geography&lt;/strong&gt; — &lt;code&gt;contactsLocationsModule.locations[]&lt;/code&gt; (country, facility)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnbyx6mswdmiw55xi47ld.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnbyx6mswdmiw55xi47ld.png" alt="Query the ClinicalTrials.gov API without an account" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The only two rules
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Be reasonable with volume — there's no published hard rate limit for anonymous use, but batch and cache rather than hammering the endpoint.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;pageToken&lt;/code&gt;, not a numeric offset, to page — the API doesn't support jumping to page N.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's the whole thing. No account, no key, no scraping the SPA frontend (which just serves bootstrap JS to a screen-scraper anyway).&lt;/p&gt;




&lt;p&gt;If you'd rather skip the module-nesting, the pagination loop and flattening the response yourself, the &lt;a href="https://apify.com/ponderable_hydrometer/clinicaltrials-scraper" rel="noopener noreferrer"&gt;ClinicalTrials.gov Scraper&lt;/a&gt; on Apify wraps exactly these endpoints — condition/intervention/sponsor/status filters in, one flat row per study out.&lt;/p&gt;

&lt;p&gt;📌 Full endpoint cheatsheet (copy-paste reference): &lt;strong&gt;&lt;a href="https://github.com/noble-ronin/clinicaltrials-api" rel="noopener noreferrer"&gt;github.com/noble-ronin/clinicaltrials-api&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>healthcare</category>
      <category>data</category>
      <category>webscraping</category>
    </item>
    <item>
      <title>Earthquake Data Has a Free JSON API — Every Quake on Earth, No Key Required</title>
      <dc:creator>Noble Ronin</dc:creator>
      <pubDate>Mon, 27 Jul 2026 06:35:21 +0000</pubDate>
      <link>https://dev.to/ronin13/earthquake-data-has-a-free-json-api-every-quake-on-earth-no-key-required-hch</link>
      <guid>https://dev.to/ronin13/earthquake-data-has-a-free-json-api-every-quake-on-earth-no-key-required-hch</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd6047mwnbprb77dunyza.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd6047mwnbprb77dunyza.png" alt="Earthquake Data Has a Free JSON API" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've ever needed earthquake data — for a mapping app, a risk model, a news feed, or just a hobby dashboard — you don't need to scrape &lt;code&gt;earthquake.usgs.gov&lt;/code&gt;'s web pages, and you don't need a paid data vendor. The USGS runs the &lt;strong&gt;FDSN Event Web Service&lt;/strong&gt;, a free, &lt;strong&gt;keyless&lt;/strong&gt; JSON API over its entire global earthquake catalogue, updated continuously.&lt;/p&gt;

&lt;p&gt;No sign-up. No API key. No token. It's a public US government service and it's meant to be hit directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The base
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://earthquake.usgs.gov/fdsnws/event/1/query
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ask for GeoJSON and you get a standard &lt;code&gt;FeatureCollection&lt;/code&gt; — one &lt;code&gt;Feature&lt;/code&gt; per earthquake, each with a &lt;code&gt;geometry.coordinates&lt;/code&gt; (&lt;code&gt;[longitude, latitude, depthKm]&lt;/code&gt;) and a &lt;code&gt;properties&lt;/code&gt; object carrying everything else:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&amp;amp;starttime=2026-07-01&amp;amp;minmagnitude=4.5&amp;amp;limit=5"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each feature's &lt;code&gt;properties&lt;/code&gt; block includes &lt;code&gt;mag&lt;/code&gt;, &lt;code&gt;magType&lt;/code&gt;, &lt;code&gt;place&lt;/code&gt;, &lt;code&gt;time&lt;/code&gt; / &lt;code&gt;updated&lt;/code&gt; (epoch ms), &lt;code&gt;tsunami&lt;/code&gt; (0/1 flag), &lt;code&gt;alert&lt;/code&gt; (PAGER level: &lt;code&gt;green&lt;/code&gt;/&lt;code&gt;yellow&lt;/code&gt;/&lt;code&gt;orange&lt;/code&gt;/&lt;code&gt;red&lt;/code&gt;), &lt;code&gt;sig&lt;/code&gt; (significance score), &lt;code&gt;felt&lt;/code&gt; (number of "did you feel it?" reports), &lt;code&gt;cdi&lt;/code&gt;/&lt;code&gt;mmi&lt;/code&gt; (intensity), &lt;code&gt;status&lt;/code&gt; (&lt;code&gt;automatic&lt;/code&gt;/&lt;code&gt;reviewed&lt;/code&gt;), &lt;code&gt;type&lt;/code&gt; (&lt;code&gt;earthquake&lt;/code&gt;, &lt;code&gt;quarry blast&lt;/code&gt;, …), plus a &lt;code&gt;detail&lt;/code&gt; URL for the full per-event record.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filtering
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Param&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;starttime&lt;/code&gt; / &lt;code&gt;endtime&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Time window, ISO or &lt;code&gt;YYYY-MM-DD&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;starttime=2026-07-01&amp;amp;endtime=2026-07-27&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;minmagnitude&lt;/code&gt; / &lt;code&gt;maxmagnitude&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Magnitude range&lt;/td&gt;
&lt;td&gt;&lt;code&gt;minmagnitude=5.0&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;minlatitude&lt;/code&gt;/&lt;code&gt;maxlatitude&lt;/code&gt;/&lt;code&gt;minlongitude&lt;/code&gt;/&lt;code&gt;maxlongitude&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Bounding-box search&lt;/td&gt;
&lt;td&gt;&lt;code&gt;minlatitude=32&amp;amp;maxlatitude=42&amp;amp;minlongitude=-125&amp;amp;maxlongitude=-114&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;latitude&lt;/code&gt;/&lt;code&gt;longitude&lt;/code&gt;/&lt;code&gt;maxradiuskm&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Circle search around a point&lt;/td&gt;
&lt;td&gt;&lt;code&gt;latitude=35.4&amp;amp;longitude=139.7&amp;amp;maxradiuskm=200&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;mindepth&lt;/code&gt; / &lt;code&gt;maxdepth&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Depth range, km&lt;/td&gt;
&lt;td&gt;&lt;code&gt;maxdepth=70&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alertlevel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PAGER alert filter&lt;/td&gt;
&lt;td&gt;&lt;code&gt;alertlevel=orange&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;orderby&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;time&lt;/code&gt;, &lt;code&gt;time-asc&lt;/code&gt;, &lt;code&gt;magnitude&lt;/code&gt;, &lt;code&gt;magnitude-asc&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;orderby=magnitude&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;format&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;geojson&lt;/code&gt; (recommended), &lt;code&gt;csv&lt;/code&gt;, &lt;code&gt;xml&lt;/code&gt;, &lt;code&gt;text&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;format=geojson&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Every M4.5+ quake in the last window, newest first&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&amp;amp;minmagnitude=4.5&amp;amp;orderby=time"&lt;/span&gt;

&lt;span class="c"&gt;# California bounding box, this month&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&amp;amp;starttime=2026-07-01&amp;amp;minlatitude=32&amp;amp;maxlatitude=42&amp;amp;minlongitude=-125&amp;amp;maxlongitude=-114"&lt;/span&gt;

&lt;span class="c"&gt;# Within 200km of Tokyo, magnitude 5+&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&amp;amp;latitude=35.4&amp;amp;longitude=139.7&amp;amp;maxradiuskm=200&amp;amp;minmagnitude=5"&lt;/span&gt;

&lt;span class="c"&gt;# Only quakes that triggered a PAGER alert (orange/red = significant humanitarian impact)&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&amp;amp;alertlevel=orange"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's also a rolling set of pre-built summary feeds if you just want "what's happening right now" without building a query — &lt;code&gt;https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/{significant,4.5,2.5,1.0,all}_{hour,day,week,month}.geojson&lt;/code&gt; — e.g. &lt;code&gt;.../summary/4.5_day.geojson&lt;/code&gt; for every M4.5+ quake in the last 24 hours. Same GeoJSON shape as the query endpoint, refreshed every few minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes &amp;amp; gotchas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keyless, no rate-limit registration&lt;/strong&gt; — just be reasonable with request volume; it's a shared public service.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;format=geojson&lt;/code&gt; is the easiest to work with; &lt;code&gt;format=text&lt;/code&gt; gives a pipe-delimited feed if you want something grep-friendly.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;status&lt;/code&gt; starts as &lt;code&gt;automatic&lt;/code&gt; right after an event and flips to &lt;code&gt;reviewed&lt;/code&gt; once a seismologist confirms it — for anything safety-critical, filter on &lt;code&gt;status=reviewed&lt;/code&gt; or expect revisions.&lt;/li&gt;
&lt;li&gt;Depth and magnitude type (&lt;code&gt;magType&lt;/code&gt;) vary by network — &lt;code&gt;mww&lt;/code&gt;, &lt;code&gt;ml&lt;/code&gt;, &lt;code&gt;mb&lt;/code&gt; etc. aren't directly comparable across all ranges; don't average them naively.&lt;/li&gt;
&lt;li&gt;Circle search (&lt;code&gt;latitude&lt;/code&gt;/&lt;code&gt;longitude&lt;/code&gt;/&lt;code&gt;maxradiuskm&lt;/code&gt;) and bounding-box search are mutually exclusive — pick one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4vfbb7y935bkco0dgez9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4vfbb7y935bkco0dgez9.png" alt="Earthquake feed structure" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Related
&lt;/h2&gt;

&lt;p&gt;Full endpoint reference + copy-paste table: &lt;strong&gt;&lt;a href="https://github.com/noble-ronin/usgs-earthquake-api" rel="noopener noreferrer"&gt;noble-ronin/usgs-earthquake-api&lt;/a&gt;&lt;/strong&gt; on GitHub.&lt;/p&gt;

&lt;p&gt;Want the filtered rows without building the query string yourself? The &lt;a href="https://apify.com/ponderable_hydrometer/earthquakes-scraper" rel="noopener noreferrer"&gt;Earthquake Data Scraper&lt;/a&gt; on Apify wraps this same endpoint — set magnitude/time/bbox in a form, get clean rows out, schedule it as a live alert feed.&lt;/p&gt;

</description>
      <category>api</category>
      <category>gis</category>
      <category>webscraping</category>
      <category>data</category>
    </item>
    <item>
      <title>I Pulled Live Jobs Straight From OpenAI, Stripe, Airbnb and Bosch — Each Took One API Call</title>
      <dc:creator>Noble Ronin</dc:creator>
      <pubDate>Sat, 25 Jul 2026 07:26:37 +0000</pubDate>
      <link>https://dev.to/ronin13/i-pulled-live-jobs-straight-from-openai-stripe-airbnb-and-bosch-each-took-one-api-call-3od5</link>
      <guid>https://dev.to/ronin13/i-pulled-live-jobs-straight-from-openai-stripe-airbnb-and-bosch-each-took-one-api-call-3od5</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwl47x9tjdhtiy15mnbvr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwl47x9tjdhtiy15mnbvr.png" alt="Live jobs from any company's ATS in one API call" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wanted live, structured job listings from a handful of big companies — no LinkedIn middleman, no Indeed anti-bot wall, no headless browser. So I just asked each company's own &lt;strong&gt;applicant tracking system&lt;/strong&gt; (ATS) directly.&lt;/p&gt;

&lt;p&gt;Here's what one keyless call returned, live today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI&lt;/strong&gt; — &lt;strong&gt;755&lt;/strong&gt; open roles (Ashby)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bosch&lt;/strong&gt; — &lt;strong&gt;4,773&lt;/strong&gt; (SmartRecruiters)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stripe&lt;/strong&gt; — &lt;strong&gt;535&lt;/strong&gt; (Greenhouse)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Palantir&lt;/strong&gt; — &lt;strong&gt;287&lt;/strong&gt; (Lever)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Airbnb&lt;/strong&gt; — &lt;strong&gt;196&lt;/strong&gt; (Greenhouse)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spotify&lt;/strong&gt; — &lt;strong&gt;108&lt;/strong&gt; (Lever)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No sign-up. No API key. No token. No proxy. Every number above came from a plain &lt;code&gt;curl&lt;/code&gt; against the company's public board API — the same JSON their own careers page renders from.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the ATS, not LinkedIn or Indeed
&lt;/h2&gt;

&lt;p&gt;LinkedIn and Indeed scrapers fight aggressive anti-bot systems. They break, they rate-limit, they silently return half the results, and you spend more time babysitting proxies than using the data.&lt;/p&gt;

&lt;p&gt;A company's ATS has no reason to fight you: it's the endpoint its &lt;strong&gt;own&lt;/strong&gt; careers page calls. It's the source of truth, it's fast, and for the big four ATS platforms below it's a clean public JSON API. You just have to know the shape of the call.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four calls
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Greenhouse
&lt;/h3&gt;

&lt;p&gt;The board token is the slug in &lt;code&gt;boards.greenhouse.io/&amp;lt;token&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://boards-api.greenhouse.io/v1/boards/stripe/jobs?content=true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns every posting with title, location, department and (with &lt;code&gt;content=true&lt;/code&gt;) the full HTML description. Stripe returned &lt;strong&gt;535&lt;/strong&gt; live roles; Airbnb, &lt;strong&gt;196&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lever
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.lever.co/v0/postings/palantir?mode=json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A flat JSON array — Palantir returned &lt;strong&gt;287&lt;/strong&gt; postings, each with categories, workplace type and apply URL. Spotify: &lt;strong&gt;108&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ashby
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.ashbyhq.com/posting-api/job-board/openai?includeCompensation=true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenAI's entire board — &lt;strong&gt;755&lt;/strong&gt; roles — comes back in one response, compensation bands included where published.&lt;/p&gt;

&lt;h3&gt;
  
  
  SmartRecruiters
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.smartrecruiters.com/v1/companies/BoschGroup/postings?limit=100"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paginated with &lt;code&gt;limit&lt;/code&gt;/&lt;code&gt;offset&lt;/code&gt;. Bosch (&lt;code&gt;BoschGroup&lt;/code&gt;) exposes &lt;strong&gt;4,773&lt;/strong&gt; postings this way — a genuinely large, structured hiring dataset for free.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7v3bn95b6d1q9faaam1w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7v3bn95b6d1q9faaam1w.png" alt="Nine ATS platforms, one detection-plus-fetch" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  It's not just the big four
&lt;/h2&gt;

&lt;p&gt;Those are the platforms with the marquee names, but the same "your ATS is already an API" trick works on more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workday&lt;/strong&gt; — &lt;code&gt;POST&lt;/code&gt; to the &lt;code&gt;/wday/cxs/.../jobs&lt;/code&gt; CXS endpoint (pass the full board URL)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BambooHR&lt;/strong&gt; — &lt;code&gt;{company}.bamboohr.com/careers/list&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Personio&lt;/strong&gt; — &lt;code&gt;{company}.jobs.personio.com/xml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recruitee&lt;/strong&gt; — &lt;code&gt;{company}.recruitee.com/api/offers/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Breezy HR&lt;/strong&gt; — &lt;code&gt;{company}.breezy.hr/json&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's &lt;strong&gt;nine&lt;/strong&gt; ATS platforms, each with a public listing endpoint. The exact URL patterns, response fields and gotchas for all nine are in this cheatsheet:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://github.com/noble-ronin/ats-job-apis" rel="noopener noreferrer"&gt;noble-ronin/ats-job-apis&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  One honest caveat
&lt;/h2&gt;

&lt;p&gt;Companies migrate. While checking this I hit &lt;code&gt;api.lever.co/v0/postings/brex&lt;/code&gt; and got back &lt;code&gt;{"ok":false,"error":"Document not found"}&lt;/code&gt; — Brex had moved off Lever. So in practice you want to &lt;strong&gt;detect&lt;/strong&gt; which ATS a company is on before you call it, and fall through the list until one answers.&lt;/p&gt;

&lt;p&gt;That detection-plus-fetch across all nine ATS is exactly what I wrapped into an actor, if you'd rather pass a company name and get clean rows out than wire up nine endpoints yourself:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://apify.com/ponderable_hydrometer/multi-ats-jobs" rel="noopener noreferrer"&gt;Multi-ATS Job Scraper&lt;/a&gt;&lt;/strong&gt; — give it a company or a careers-board URL, it auto-detects the ATS and returns structured, real-time jobs, with a monitor mode for new postings.&lt;/p&gt;

&lt;p&gt;But you don't need it to get started. Pick a company, guess their ATS from the careers-page URL, and run the matching &lt;code&gt;curl&lt;/code&gt; above. The odds it just works are better than you'd think.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;All counts verified live on 2026-07-25 from an EU IP with no API key. Live numbers will drift as companies open and close roles.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>webscraping</category>
      <category>jobs</category>
      <category>data</category>
    </item>
    <item>
      <title>FDA Recalls Have a Free JSON API — Every Drug, Device and Food Recall Without Scraping</title>
      <dc:creator>Noble Ronin</dc:creator>
      <pubDate>Fri, 24 Jul 2026 20:10:06 +0000</pubDate>
      <link>https://dev.to/ronin13/fda-recalls-have-a-free-json-api-every-drug-device-and-food-recall-without-scraping-4mn9</link>
      <guid>https://dev.to/ronin13/fda-recalls-have-a-free-json-api-every-drug-device-and-food-recall-without-scraping-4mn9</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fldk1gu2n6xox4hya06db.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fldk1gu2n6xox4hya06db.png" alt="FDA Recalls Have a Free JSON API" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you need FDA recall data — which drugs, devices and foods got pulled, why, by whom, and how serious it was — you do &lt;strong&gt;not&lt;/strong&gt; need to scrape fda.gov, and you do &lt;strong&gt;not&lt;/strong&gt; need a paid API. The FDA runs &lt;strong&gt;openFDA&lt;/strong&gt;, a free, &lt;strong&gt;keyless&lt;/strong&gt; JSON API over its own enforcement, adverse-event and labeling databases.&lt;/p&gt;

&lt;p&gt;No sign-up. No API key. No token. There's a higher rate limit if you register a free key, but every endpoint below works with nothing at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  The base
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.fda.gov
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recalls live under the &lt;strong&gt;enforcement&lt;/strong&gt; endpoints, one per product area:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.fda.gov/drug/enforcement.json?limit=1"&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://api.fda.gov/device/enforcement.json?limit=1"&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://api.fda.gov/food/enforcement.json?limit=1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each response has a &lt;code&gt;meta&lt;/code&gt; block (with &lt;code&gt;results.total&lt;/code&gt;) and a &lt;code&gt;results&lt;/code&gt; array. A single drug-recall record carries &lt;code&gt;recalling_firm&lt;/code&gt;, &lt;code&gt;product_description&lt;/code&gt;, &lt;code&gt;reason_for_recall&lt;/code&gt;, &lt;code&gt;classification&lt;/code&gt; (Class I / II / III — I is the most serious), &lt;code&gt;status&lt;/code&gt; (Ongoing / Completed / Terminated), &lt;code&gt;recall_initiation_date&lt;/code&gt;, &lt;code&gt;distribution_pattern&lt;/code&gt;, &lt;code&gt;code_info&lt;/code&gt;, plus an &lt;code&gt;openfda&lt;/code&gt; block that links the product back to NDC codes and brand/generic names.&lt;/p&gt;

&lt;h2&gt;
  
  
  Search with the &lt;code&gt;search&lt;/code&gt; parameter
&lt;/h2&gt;

&lt;p&gt;openFDA uses a simple &lt;code&gt;field:value&lt;/code&gt; query syntax. Quote multi-word values and URL-encode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# All Class I (most serious) drug recalls&lt;/span&gt;
curl &lt;span class="s1"&gt;'https://api.fda.gov/drug/enforcement.json?search=classification:"Class+I"&amp;amp;limit=5'&lt;/span&gt;

&lt;span class="c"&gt;# Recalls that are still Ongoing&lt;/span&gt;
curl &lt;span class="s1"&gt;'https://api.fda.gov/drug/enforcement.json?search=status:"Ongoing"'&lt;/span&gt;

&lt;span class="c"&gt;# Ranges and booleans work too — food recalls initiated in 2026&lt;/span&gt;
curl &lt;span class="s1"&gt;'https://api.fda.gov/food/enforcement.json?search=recall_initiation_date:[20260101+TO+20261231]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the time of writing there are &lt;strong&gt;1,733&lt;/strong&gt; Class I drug recalls on record and &lt;strong&gt;2,580&lt;/strong&gt; with an &lt;code&gt;Ongoing&lt;/code&gt; status — all as structured JSON, no scraping.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyd4etcydsp00xg2wtp5t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyd4etcydsp00xg2wtp5t.png" alt="Every drug, device and food recall as JSON" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Count instead of list
&lt;/h2&gt;

&lt;p&gt;Add &lt;code&gt;count=&amp;lt;field&amp;gt;.exact&lt;/code&gt; and openFDA returns an aggregation instead of raw rows — great for dashboards:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.fda.gov/drug/enforcement.json?count=classification.exact"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Right now that returns Class II = &lt;strong&gt;14,381&lt;/strong&gt;, Class I = &lt;strong&gt;1,733&lt;/strong&gt;, Class III = &lt;strong&gt;1,701&lt;/strong&gt;. One call, the whole distribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Page through everything
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.fda.gov/device/enforcement.json?limit=100&amp;amp;skip=200"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;limit&lt;/code&gt; (max 1000) and &lt;code&gt;skip&lt;/code&gt; page the results. The device enforcement set alone is &lt;strong&gt;39,539&lt;/strong&gt; records; food is &lt;strong&gt;29,238&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond recalls
&lt;/h2&gt;

&lt;p&gt;Same base, same keyless deal, for two more datasets people usually ask about in the same breath:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Adverse event reports (FAERS)&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://api.fda.gov/drug/event.json?limit=1"&lt;/span&gt;

&lt;span class="c"&gt;# Structured drug product labeling&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://api.fda.gov/drug/label.json?limit=1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The only two rules
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Be reasonable with volume — anonymous calls are rate-limited (a registered free key just raises the ceiling).&lt;/li&gt;
&lt;li&gt;Page with &lt;code&gt;limit&lt;/code&gt; + &lt;code&gt;skip&lt;/code&gt;, and remember openFDA data is a &lt;strong&gt;snapshot&lt;/strong&gt; the FDA refreshes periodically, not a live wire.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's the whole thing.&lt;/p&gt;




&lt;p&gt;If you'd rather skip the paging, the &lt;code&gt;search&lt;/code&gt; encoding and the field-mapping, the &lt;a href="https://apify.com/ponderable_hydrometer/fda-recalls-scraper" rel="noopener noreferrer"&gt;FDA Recalls Scraper&lt;/a&gt; on Apify wraps exactly these endpoints — drug/device/food, class and status filters in, structured rows out.&lt;/p&gt;

&lt;p&gt;📌 Full endpoint cheatsheet (copy-paste reference): &lt;strong&gt;&lt;a href="https://github.com/noble-ronin/fda-recalls-api" rel="noopener noreferrer"&gt;github.com/noble-ronin/fda-recalls-api&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>healthcare</category>
      <category>webscraping</category>
      <category>data</category>
    </item>
    <item>
      <title>EU Public Tenders Have a Free JSON API — Every Notice, Buyer and Deadline Without Scraping</title>
      <dc:creator>Noble Ronin</dc:creator>
      <pubDate>Mon, 20 Jul 2026 15:24:18 +0000</pubDate>
      <link>https://dev.to/ronin13/eu-public-tenders-have-a-free-json-api-every-notice-buyer-and-deadline-without-scraping-1c50</link>
      <guid>https://dev.to/ronin13/eu-public-tenders-have-a-free-json-api-every-notice-buyer-and-deadline-without-scraping-1c50</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzh32ujqc2geo0ah57k1o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzh32ujqc2geo0ah57k1o.png" alt="EU Public Tenders Have a Free JSON API" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you need EU public procurement data — who's buying what, from which government body, for how much, closing when — you do &lt;strong&gt;not&lt;/strong&gt; need a scraper, and you do &lt;strong&gt;not&lt;/strong&gt; need to pay one of the half-dozen "TED scraper" tools on the market. The EU's own &lt;strong&gt;TED&lt;/strong&gt; (Tenders Electronic Daily) journal exposes all of it as clean JSON through an official, keyless &lt;strong&gt;v3 search API&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No sign-up. No API key. No token. Just a POST request.&lt;/p&gt;

&lt;h2&gt;
  
  
  The endpoint
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST https://api.ted.europa.eu/v3/notices/search
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Anonymous access — search and retrieval require no authentication at all (only &lt;em&gt;submitting&lt;/em&gt; notices does).&lt;/p&gt;

&lt;h2&gt;
  
  
  Pull the newest notices
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s1"&gt;'https://api.ted.europa.eu/v3/notices/search'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "query": "FT~\"cloud computing\" SORT BY publication-date DESC",
    "fields": ["publication-number", "notice-title", "buyer-name", "buyer-country", "deadline"],
    "limit": 10,
    "scope": "ACTIVE",
    "paginationMode": "ITERATION"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;query&lt;/code&gt; uses TED's expert-search syntax: &lt;code&gt;FT~"..."&lt;/code&gt; for full-text, field filters like &lt;code&gt;buyer-country=DEU&lt;/code&gt; or &lt;code&gt;PD&amp;gt;=20260101&lt;/code&gt; (publication date), combined with &lt;code&gt;AND&lt;/code&gt;/&lt;code&gt;OR&lt;/code&gt;, and &lt;code&gt;SORT BY publication-date DESC&lt;/code&gt; to get live opportunities instead of the 2016 backlog. &lt;code&gt;fields&lt;/code&gt; is an explicit allowlist — ask for exactly the eForms fields you want back (&lt;code&gt;notice-title&lt;/code&gt; is always included even if you forget it).&lt;/p&gt;

&lt;h2&gt;
  
  
  What comes back
&lt;/h2&gt;

&lt;p&gt;Each notice in the &lt;code&gt;notices&lt;/code&gt; array is keyed by the same eForms field names you requested — &lt;code&gt;notice-title&lt;/code&gt;, &lt;code&gt;buyer-name&lt;/code&gt;, &lt;code&gt;classification-cpv&lt;/code&gt; (procurement category codes), &lt;code&gt;total-value&lt;/code&gt; / &lt;code&gt;total-value-cur&lt;/code&gt;, &lt;code&gt;deadline&lt;/code&gt;, &lt;code&gt;links&lt;/code&gt;. Multilingual fields like the title arrive as an object keyed by language (&lt;code&gt;{"eng": [...], "fra": [...]}&lt;/code&gt;) rather than a plain string — grab &lt;code&gt;eng&lt;/code&gt; when present, fall back to whatever language is there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filter by country, value, category
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# German buyers, AI-related, published this year&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s1"&gt;'https://api.ted.europa.eu/v3/notices/search'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"query": "FT~\"artificial intelligence\" AND buyer-country=DEU AND PD&amp;gt;=20260101 SORT BY publication-date DESC", "fields": ["publication-number","notice-title","buyer-name","total-value","deadline"], "limit": 50, "scope": "ACTIVE"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F71ssy1oprwumyq08y3lj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F71ssy1oprwumyq08y3lj.png" alt="Every EU tender notice as structured JSON" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Page through results
&lt;/h2&gt;

&lt;p&gt;Set &lt;code&gt;paginationMode: "ITERATION"&lt;/code&gt; and bump &lt;code&gt;page&lt;/code&gt; (or follow the pagination token TED returns) while &lt;code&gt;limit&lt;/code&gt; stays at or under 100 per call. &lt;code&gt;scope: "ACTIVE"&lt;/code&gt; returns currently-open notices; use &lt;code&gt;"ALL"&lt;/code&gt; to search the full historical archive (480,000+ notices back to the mid-2010s).&lt;/p&gt;

&lt;h2&gt;
  
  
  The one gotcha
&lt;/h2&gt;

&lt;p&gt;Field names are the &lt;em&gt;eForms&lt;/em&gt; names (&lt;code&gt;notice-title&lt;/code&gt;, &lt;code&gt;classification-cpv&lt;/code&gt;, &lt;code&gt;buyer-country&lt;/code&gt;) — not the old two-letter TED codes from the legacy API. If you copy a query from a pre-2023 blog post, expect it to 404 or return nothing; the schema changed with the eForms rollout.&lt;/p&gt;

&lt;p&gt;That's the whole thing: one POST endpoint, an expert-search query string, and a field allowlist — no key, no proxy, no anti-bot to fight.&lt;/p&gt;




&lt;p&gt;If you'd rather skip the pagination and the multilingual-field unwrapping, the &lt;a href="https://apify.com/ponderable_hydrometer/ted-tenders-scraper" rel="noopener noreferrer"&gt;EU Tenders Scraper&lt;/a&gt; on Apify wraps exactly this endpoint — keyword or expert query in, flat rows out (buyer, country, CPV, value, deadline, direct link).&lt;/p&gt;

&lt;p&gt;📌 Full field reference + copy-paste query cheatsheet: &lt;strong&gt;&lt;a href="https://github.com/noble-ronin/ted-tenders-api" rel="noopener noreferrer"&gt;github.com/noble-ronin/ted-tenders-api&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>government</category>
      <category>webscraping</category>
      <category>data</category>
    </item>
    <item>
      <title>US Regulations Have a Free JSON API — Every Rule, Notice and Executive Order Without Scraping</title>
      <dc:creator>Noble Ronin</dc:creator>
      <pubDate>Thu, 16 Jul 2026 11:47:52 +0000</pubDate>
      <link>https://dev.to/ronin13/us-regulations-have-a-free-json-api-every-rule-notice-and-executive-order-without-scraping-4o34</link>
      <guid>https://dev.to/ronin13/us-regulations-have-a-free-json-api-every-rule-notice-and-executive-order-without-scraping-4o34</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fts2ioy9enmvoxrwywr95.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fts2ioy9enmvoxrwywr95.png" alt="US Regulations Have a Free JSON API"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you need US federal regulations as data — final rules, proposed rules, public notices, executive orders — you do &lt;strong&gt;not&lt;/strong&gt; need to scrape, and you do &lt;strong&gt;not&lt;/strong&gt; need a paid API. The &lt;strong&gt;Federal Register&lt;/strong&gt; (the daily journal of the US government) publishes &lt;em&gt;everything&lt;/em&gt; as clean JSON through a free, keyless API.&lt;/p&gt;

&lt;p&gt;No sign-up. No API key. No token. The only limit is a polite rate cap.&lt;/p&gt;

&lt;h2&gt;
  
  
  The base
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.federalregister.gov/api/v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pull the latest documents
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://www.federalregister.gov/api/v1/documents.json?per_page=5&amp;amp;order=newest"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get back &lt;code&gt;count&lt;/code&gt;, &lt;code&gt;total_pages&lt;/code&gt;, and a &lt;code&gt;results&lt;/code&gt; array. Each result includes &lt;code&gt;document_number&lt;/code&gt;, &lt;code&gt;type&lt;/code&gt; (Rule / Proposed Rule / Notice / Presidential Document), &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;abstract&lt;/code&gt;, &lt;code&gt;publication_date&lt;/code&gt;, agencies, and direct &lt;code&gt;html_url&lt;/code&gt; and &lt;code&gt;pdf_url&lt;/code&gt; links to the official text.&lt;/p&gt;

&lt;h2&gt;
  
  
  Search by term, agency, date or type
&lt;/h2&gt;

&lt;p&gt;The API takes &lt;code&gt;conditions[...]&lt;/code&gt; filters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Everything mentioning "artificial intelligence"&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://www.federalregister.gov/api/v1/documents.json?conditions%5Bterm%5D=artificial+intelligence"&lt;/span&gt;

&lt;span class="c"&gt;# Final rules from the EPA, published this year&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://www.federalregister.gov/api/v1/documents.json?conditions%5Btype%5D%5B%5D=RULE&amp;amp;conditions%5Bagencies%5D%5B%5D=environmental-protection-agency&amp;amp;conditions%5Bpublication_date%5D%5Bgte%5D=2026-01-01"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the time of writing, the plain &lt;code&gt;artificial intelligence&lt;/code&gt; term search returns &lt;strong&gt;1,504&lt;/strong&gt; documents — all as structured JSON.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbe0djht29bxsuybgxzeh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbe0djht29bxsuybgxzeh.png" alt="Every rule, notice and executive order as JSON"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Fetch one document in full
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://www.federalregister.gov/api/v1/documents/2026-14454.json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That returns the full record for a single document number, including the abstract, the list of affected CFR parts, docket IDs, and links to the raw text (&lt;code&gt;body_html_url&lt;/code&gt;, &lt;code&gt;full_text_xml_url&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  List every agency
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://www.federalregister.gov/api/v1/agencies.json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;472 agencies, each with its slug (use it in the &lt;code&gt;conditions[agencies][]&lt;/code&gt; filter above).&lt;/p&gt;

&lt;h2&gt;
  
  
  The only two rules
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Be reasonable with request volume — it's a public-good API, not a firehose to hammer.&lt;/li&gt;
&lt;li&gt;Page with &lt;code&gt;per_page&lt;/code&gt; (max 1000) and &lt;code&gt;page&lt;/code&gt;, or use &lt;code&gt;order=newest&lt;/code&gt; for a rolling feed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's the whole thing. For consolidated &lt;strong&gt;regulations already in force&lt;/strong&gt; (as opposed to the daily journal of changes), pair this with the sibling &lt;strong&gt;eCFR&lt;/strong&gt; API — same idea, also keyless.&lt;/p&gt;




&lt;p&gt;If you'd rather skip the paging, the field-mapping and the retry logic, the &lt;a href="https://apify.com/ponderable_hydrometer/federal-register-scraper" rel="noopener noreferrer"&gt;Federal Register Scraper&lt;/a&gt; on Apify wraps exactly these endpoints — term/agency/type/date filters in, structured rows out.&lt;/p&gt;

&lt;p&gt;📌 Full endpoint cheatsheet (copy-paste reference): &lt;strong&gt;&lt;a href="https://github.com/noble-ronin/federal-register-api" rel="noopener noreferrer"&gt;github.com/noble-ronin/federal-register-api&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>government</category>
      <category>webscraping</category>
      <category>data</category>
    </item>
    <item>
      <title>SEC Filings Have a Free JSON API — Pull Any Company's 10-Ks, 8-Ks and Insider Trades Without a Key</title>
      <dc:creator>Noble Ronin</dc:creator>
      <pubDate>Thu, 16 Jul 2026 10:36:30 +0000</pubDate>
      <link>https://dev.to/ronin13/sec-filings-have-a-free-json-api-pull-any-companys-10-ks-8-ks-and-insider-trades-without-a-key-23b1</link>
      <guid>https://dev.to/ronin13/sec-filings-have-a-free-json-api-pull-any-companys-10-ks-8-ks-and-insider-trades-without-a-key-23b1</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc0t3h2tk5fww74q8thkv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc0t3h2tk5fww74q8thkv.png" alt="SEC Filings Have a Free JSON API" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everyone assumes financial data means a paid API — Bloomberg, a scraper you have to&lt;br&gt;
babysit, or some $200/month "filings API" wrapper. For raw SEC filings, none of that&lt;br&gt;
is necessary. The SEC runs its own free, public JSON API, and it's been stable and&lt;br&gt;
keyless for years.&lt;/p&gt;
&lt;h2&gt;
  
  
  The three endpoints that cover almost everything
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Ticker → CIK lookup
&lt;/h3&gt;

&lt;p&gt;SEC filings are indexed by CIK (Central Index Key), not ticker. One file maps every&lt;br&gt;
public company:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"User-Agent: Your Name your@email.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://www.sec.gov/files/company_tickers.json | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; 200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns a JSON object keyed by row number, each with &lt;code&gt;cik_str&lt;/code&gt;, &lt;code&gt;ticker&lt;/code&gt;, &lt;code&gt;title&lt;/code&gt;.&lt;br&gt;
Apple is CIK &lt;code&gt;320193&lt;/code&gt; — zero-pad it to 10 digits for the endpoints below.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. A company's full filing history
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"User-Agent: Your Name your@email.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://data.sec.gov/submissions/CIK0000320193.json | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; 400
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That single call returns the company's name, SIC industry code, exchange/ticker, and&lt;br&gt;
a &lt;code&gt;filings.recent&lt;/code&gt; array with every filing — form type (&lt;code&gt;10-K&lt;/code&gt;, &lt;code&gt;10-Q&lt;/code&gt;, &lt;code&gt;8-K&lt;/code&gt;, &lt;code&gt;4&lt;/code&gt;&lt;br&gt;
for insider trades, &lt;code&gt;13F-HR&lt;/code&gt; for institutional holdings, &lt;code&gt;DEF 14A&lt;/code&gt;, &lt;code&gt;S-1&lt;/code&gt;, …),&lt;br&gt;
&lt;code&gt;filingDate&lt;/code&gt;, &lt;code&gt;reportDate&lt;/code&gt;, and &lt;code&gt;accessionNumber&lt;/code&gt; (which you turn into a direct&lt;br&gt;
document URL). No pagination dance for recent history — at least a year, or the&lt;br&gt;
1,000 most recent filings, in one response.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Full-text search across every filing, ever
&lt;/h3&gt;

&lt;p&gt;Want every 8-K that mentions a specific phrase, across every company? That's a&lt;br&gt;
separate index:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"User-Agent: Your Name your@email.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://efts.sec.gov/LATEST/search-index?q=%22material+weakness%22&amp;amp;forms=10-K&amp;amp;startdt=2026-01-01&amp;amp;enddt=2026-06-30"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Results come back Elasticsearch-style under &lt;code&gt;hits.hits&lt;/code&gt;, each with a display name,&lt;br&gt;
CIK, form type, filing date, and accession number — everything you need to build the&lt;br&gt;
document URL without a second request.&lt;/p&gt;

&lt;h2&gt;
  
  
  The only two rules
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Send a real &lt;code&gt;User-Agent&lt;/code&gt;.&lt;/strong&gt; Not a browser string — an actual identifier: your
name and an email address. This is the SEC's entire "access control" — no key, no
OAuth, no sign-up form. Skip it and you'll get blocked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stay under 10 requests/second.&lt;/strong&gt; That's the documented fair-access ceiling
across &lt;code&gt;data.sec.gov&lt;/code&gt; and &lt;code&gt;efts.sec.gov&lt;/code&gt; combined. Fine for almost any real
workload; just don't fire filings in a tight loop with zero delay.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's the whole barrier to entry. No key rotation, no free-tier quota that resets&lt;br&gt;
monthly, no CAPTCHA wall — because there isn't a wall.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this gets tedious at scale
&lt;/h2&gt;

&lt;p&gt;The endpoints above are clean, but real usage runs into the boring parts fast: CIK&lt;br&gt;
padding, mapping every form-type filter you actually want (&lt;code&gt;10-K&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; &lt;code&gt;10-K/A&lt;/code&gt;,&lt;br&gt;
say), pagination past the first page of full-text search results, retry/backoff to&lt;br&gt;
respect the rate limit, and turning accession numbers into working document links.&lt;br&gt;
None of that is hard — it's just the kind of glue code you don't want to write twice.&lt;/p&gt;

&lt;p&gt;That's basically what &lt;a href="https://apify.com/ponderable_hydrometer/sec-edgar-scraper" rel="noopener noreferrer"&gt;SEC EDGAR Filings Scraper &amp;amp; Full-Text&lt;br&gt;
Search&lt;/a&gt; wraps: same free&lt;br&gt;
official API underneath, but you pass tickers or CIKs plus optional form filters and&lt;br&gt;
a date range, and get back one flat row per filing — company, CIK, form, dates,&lt;br&gt;
accession number, and a direct filing URL, ready to drop into a spreadsheet or a&lt;br&gt;
pipeline. Same data as the curl calls above, just without the glue code.&lt;/p&gt;

&lt;p&gt;Want the endpoints without the narrative? Full reference table + curl examples +&lt;br&gt;
gotchas: &lt;a href="https://github.com/noble-ronin/sec-edgar-api" rel="noopener noreferrer"&gt;SEC EDGAR JSON API — a&lt;br&gt;
cheatsheet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you liked this one, I also wrote up &lt;a href="https://dev.to/ronin13/skip-linkedinindeed-most-companies-job-boards-have-a-public-json-api-48b"&gt;how job boards expose a public JSON API&lt;br&gt;
underneath the "no API" LinkedIn/Indeed&lt;br&gt;
experience&lt;/a&gt; — same pattern, different domain: the data's public, you just have to know where to look.&lt;/p&gt;

</description>
      <category>api</category>
      <category>finance</category>
      <category>webscraping</category>
      <category>data</category>
    </item>
    <item>
      <title>Skip LinkedIn/Indeed: most companies' job boards have a public JSON API</title>
      <dc:creator>Noble Ronin</dc:creator>
      <pubDate>Mon, 13 Jul 2026 15:33:36 +0000</pubDate>
      <link>https://dev.to/ronin13/skip-linkedinindeed-most-companies-job-boards-have-a-public-json-api-48b</link>
      <guid>https://dev.to/ronin13/skip-linkedinindeed-most-companies-job-boards-have-a-public-json-api-48b</guid>
      <description>&lt;p&gt;If you've ever tried to pull job listings by scraping LinkedIn or Indeed, you know the pain: anti-bot systems, CAPTCHAs, rotating proxies, and scripts that silently break every few weeks.&lt;/p&gt;

&lt;p&gt;Here's the thing — you usually don't need any of that.&lt;/p&gt;

&lt;p&gt;Companies don't post jobs on LinkedIn first. They post them in their &lt;strong&gt;ATS&lt;/strong&gt; (Applicant Tracking System) — Greenhouse, Lever, Ashby, Workday, etc. — and most ATS platforms expose the company's board as a &lt;strong&gt;public JSON endpoint&lt;/strong&gt;. No key, no login, no browser. It's the company's own source of truth, so it's cleaner and fresher than any aggregator.&lt;/p&gt;

&lt;h2&gt;
  
  
  The endpoints
&lt;/h2&gt;

&lt;p&gt;A few that work with a plain GET (&lt;code&gt;{company}&lt;/code&gt; = the company's slug):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Greenhouse&lt;/strong&gt; — &lt;code&gt;https://boards-api.greenhouse.io/v1/boards/{company}/jobs?content=true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lever&lt;/strong&gt; — &lt;code&gt;https://api.lever.co/v0/postings/{company}?mode=json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recruitee&lt;/strong&gt; — &lt;code&gt;https://{company}.recruitee.com/api/offers/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Breezy HR&lt;/strong&gt; — &lt;code&gt;https://{company}.breezy.hr/json&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SmartRecruiters, Ashby, BambooHR and Personio have their own equivalents. Workday is the one annoying exception — it's a POST and needs the full board URL (tenant + datacenter + site), so you can't guess it from a bare company name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: pulling Stripe's open roles (Python)
&lt;/h2&gt;

&lt;p&gt;Stripe uses Greenhouse:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stripe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://boards-api.greenhouse.io/v1/boards/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/jobs?content=true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;—&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No Selenium, no proxy, no CAPTCHA solver. Runs in ~200ms and won't break next Tuesday because Cloudflare changed something.&lt;/p&gt;

&lt;h2&gt;
  
  
  Auto-detecting the ATS
&lt;/h2&gt;

&lt;p&gt;If you don't know which ATS a company uses, just try them in order and take the first one that returns jobs. A bare &lt;code&gt;404&lt;/code&gt; means "not this ATS, try the next." Greenhouse → Lever → Ashby → SmartRecruiters → Recruitee → Breezy covers a huge chunk of tech companies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotchas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rate limits&lt;/strong&gt; are lenient but real — be polite, set a &lt;code&gt;User-Agent&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Descriptions&lt;/strong&gt;: Greenhouse/Lever include full HTML descriptions in the list; Breezy's list endpoint doesn't (you'd fetch each posting for that).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workday&lt;/strong&gt;: POST-only, needs the full board URL — worth special-casing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  If you don't want to build/maintain 9 of these
&lt;/h2&gt;

&lt;p&gt;I got tired of keeping a fetcher per ATS in sync, so I bundled 9 of them (Greenhouse, Lever, Ashby, SmartRecruiters, Workday, BambooHR, Personio, Recruitee, Breezy) into one thing that auto-detects the ATS from a bare company name or board URL and returns normalized jobs: &lt;strong&gt;&lt;a href="https://apify.com/ponderable_hydrometer/multi-ats-jobs" rel="noopener noreferrer"&gt;https://apify.com/ponderable_hydrometer/multi-ats-jobs&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But honestly, the endpoints above are the real value — build your own if you'd rather.&lt;/p&gt;

&lt;p&gt;Which ATS should I add next? Considering Workable, Teamtailor and JazzHR.&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>python</category>
      <category>api</category>
      <category>jobs</category>
    </item>
  </channel>
</rss>
