<?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: Jure Vito Srovin</title>
    <description>The latest articles on DEV Community by Jure Vito Srovin (@jurevito).</description>
    <link>https://dev.to/jurevito</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%2F4205200%2Fb68ecbb8-6eda-47fa-aec5-308e3662d620.png</url>
      <title>DEV Community: Jure Vito Srovin</title>
      <link>https://dev.to/jurevito</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jurevito"/>
    <language>en</language>
    <item>
      <title>TED API v3 guide: search, API key and bulk download</title>
      <dc:creator>Jure Vito Srovin</dc:creator>
      <pubDate>Sat, 24 Oct 2026 18:30:06 +0000</pubDate>
      <link>https://dev.to/jurevito/ted-api-v3-guide-search-api-key-and-bulk-download-5403</link>
      <guid>https://dev.to/jurevito/ted-api-v3-guide-search-api-key-and-bulk-download-5403</guid>
      <description>&lt;h2&gt;
  
  
  What is the TED API v3?
&lt;/h2&gt;

&lt;p&gt;TED (Tenders Electronic Daily) is the EU's official journal for public procurement, where every &lt;a href="https://tenderapi.eu/en/tools/thresholds/" rel="noopener noreferrer"&gt;above-threshold&lt;/a&gt; tender notice from all 27 member states is published. Below-threshold tenders live on national portals, covered in &lt;a href="https://tenderapi.eu/en/blog/how-to-find-eu-tenders/" rel="noopener noreferrer"&gt;how to find EU tenders&lt;/a&gt;. The current TED API is version 3, and its Search API exposes those notices as JSON through a single endpoint:&lt;br&gt;
&lt;/p&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;You can call it without any authentication, so it is open to every reuser. The complete request and response reference lives in the &lt;a href="https://api.ted.europa.eu/swagger" rel="noopener noreferrer"&gt;Swagger documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Download the OpenAPI specification
&lt;/h2&gt;

&lt;p&gt;The Swagger page is generated from an OpenAPI 3.1 file you can download directly and feed into a client generator or Postman:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;https://api.ted.europa.eu/api-v3.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It covers every v3 endpoint, including search, notice submission, validation and rendering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do you need an API key?
&lt;/h2&gt;

&lt;p&gt;Not to search. The Search API is fully public. A key is only needed for the other endpoints, such as submitting, validating or rendering your own notices. If you do want one, it takes three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Visit the &lt;a href="https://developer.ted.europa.eu/home" rel="noopener noreferrer"&gt;TED Developer Portal&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Log in with your EU Login credentials.&lt;/li&gt;
&lt;li&gt;Generate your key under &lt;strong&gt;Manage API Keys&lt;/strong&gt;, and copy it right away because it can't be shown again.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Search tenders with Python
&lt;/h2&gt;

&lt;p&gt;Every request carries three things: a &lt;code&gt;query&lt;/code&gt;, the &lt;code&gt;fields&lt;/code&gt; you want back, and a &lt;code&gt;limit&lt;/code&gt;. The &lt;code&gt;query&lt;/code&gt; itself uses TED's expert search syntax, written as &lt;code&gt;field operator value&lt;/code&gt; and combined with &lt;code&gt;AND&lt;/code&gt;, &lt;code&gt;OR&lt;/code&gt;, and &lt;code&gt;NOT&lt;/code&gt;. These are the fields you will reach for most often:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;classification-cpv&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;classification-cpv=38000000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CPV code (sector)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;buyer-country&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;buyer-country=DEU&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Buyer country, ISO 3-letter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;publication-date&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;publication-date&amp;gt;=20260420&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Published on or after a date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;estimated-value-proc&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;estimated-value-proc&amp;gt;=50000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Estimated value of the procurement&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Rather than memorize the syntax, build your query visually in the &lt;a href="https://ted.europa.eu/en/expert-search" rel="noopener noreferrer"&gt;TED expert search&lt;/a&gt; and copy the resulting query string into your code. If you are unsure which CPV code fits your sector, look it up with the &lt;a href="https://tenderapi.eu/en/tools/cpv/" rel="noopener noreferrer"&gt;CPV tool&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The example below finds laboratory-equipment tenders (CPV &lt;code&gt;38000000&lt;/code&gt;) published since the start of the year, with an estimated value between 50,000 and 500,000 EUR, from buyers in Germany. Because a single page holds at most 250 notices, it pages through results with iteration mode, pulling five pages of 100 for up to 500 notices in one run:&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.ted.europa.eu/v3/notices/search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; AND &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;classification-cpv=38000000&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;# Lab equipment
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;buyer-country=DEU&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;               &lt;span class="c1"&gt;# Germany
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;publication-date&amp;gt;=20260101&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;estimated-value-proc&amp;gt;=50000&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;estimated-value-proc&amp;lt;=500000&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&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;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fields&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&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;publication-number&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;notice-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;classification-cpv&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;estimated-value-proc&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;estimated-value-cur-proc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&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;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;scope&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;ACTIVE&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;paginationMode&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;ITERATION&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;notices&lt;/span&gt; &lt;span class="o"&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;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&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="c1"&gt;# Fetch five pages.
&lt;/span&gt;    &lt;span class="n"&gt;data&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;post&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="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&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="n"&gt;notices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;notices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="c1"&gt;# Use iteration token to paginate results efficiently.
&lt;/span&gt;    &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;iterationNextToken&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;notices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;iterationNextToken&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;

    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;notice&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;notices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;publication-number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;notice-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;eng&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;cpv&lt;/span&gt; &lt;span class="o"&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="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;notice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;classification-cpv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notice&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;estimated-value-proc&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;n/a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;currency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notice&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;estimated-value-cur-proc&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="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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cpv&lt;/span&gt;&lt;span class="si"&gt;}&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;A couple of response details are worth knowing. &lt;code&gt;notice-title&lt;/code&gt; is keyed by language code, so &lt;code&gt;notice-title["eng"]&lt;/code&gt; returns the English title, while &lt;code&gt;classification-cpv&lt;/code&gt; arrives as a list of codes. In iteration mode every page hands you an &lt;code&gt;iterationNextToken&lt;/code&gt; that you pass back on the next request, and the loop stops as soon as a page comes back smaller than your limit. From here you can swap &lt;code&gt;DEU&lt;/code&gt; for any country code, or &lt;code&gt;38000000&lt;/code&gt; for the sector you bid on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filter by CPV code and keywords
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;IN (...)&lt;/code&gt; to match several CPV codes at once. Newer topics such as blockchain, AI or cybersecurity have no CPV code of their own, so buyers file them under broad IT codes like &lt;code&gt;72000000&lt;/code&gt; (IT services) or &lt;code&gt;48000000&lt;/code&gt; (software packages). Combine those with a full-text search on &lt;code&gt;FT&lt;/code&gt; to narrow them down:&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="n"&gt;query&lt;/span&gt; &lt;span class="o"&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;FT~(blockchain) &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AND classification-cpv IN (72000000 48000000) &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AND publication-date&amp;gt;=20260101&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;Not sure which code fits your sector? Search all 9,000+ codes with the &lt;a href="https://tenderapi.eu/en/tools/cpv/" rel="noopener noreferrer"&gt;CPV tool&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bulk download historical notices
&lt;/h2&gt;

&lt;p&gt;For backfills, paging through the Search API is slow. TED publishes every Official Journal issue as a daily package of XML notices, available without signing in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://ted.europa.eu/packages/daily/{yyyynnnnn}
https://ted.europa.eu/packages/monthly/{yyyy-nn}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The daily pattern takes the OJ S number: the year followed by the five-digit issue number, so &lt;code&gt;202600001&lt;/code&gt; is the first issue of 2026. The monthly pattern takes the year and month, such as &lt;code&gt;2026-01&lt;/code&gt;. Both return a &lt;code&gt;.tar.gz&lt;/code&gt; archive of eForms XML, and TED's release calendar maps dates to issue numbers. Parsing eForms XML is a project of its own, because notices use nested UBL structures and many fields only exist in some notice types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits and good practice
&lt;/h2&gt;

&lt;p&gt;The Search API is generous, but a handful of limits shape how you use it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Page size.&lt;/strong&gt; A request returns at most 250 notices, so anything larger needs &lt;code&gt;paginationMode: "ITERATION"&lt;/code&gt; and the token loop shown above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query size.&lt;/strong&gt; A single query can hold up to 2,000 clauses. When you target many CPV codes, group them with &lt;code&gt;IN (...)&lt;/code&gt; rather than chaining a long list of &lt;code&gt;OR&lt;/code&gt; terms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limits.&lt;/strong&gt; Calls are throttled, so space out requests in scheduled jobs and use bulk packages for backfills.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Field shapes.&lt;/strong&gt; Many fields are multilingual or come back as lists, which is why the example reads them defensively with &lt;code&gt;.get()&lt;/code&gt; and a language key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be a good citizen.&lt;/strong&gt; Cache what you fetch and avoid pulling the same notices twice. TED refreshes throughout the day, so an hourly or daily sync is usually plenty.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the entire loop: build a query, POST it, read the JSON, and paginate. From there you can store notices in a database, push alerts to your team, or feed them straight into your own product.&lt;/p&gt;

</description>
      <category>python</category>
      <category>api</category>
      <category>opendata</category>
    </item>
  </channel>
</rss>
