API Docs v 3.0
API Documentation
Simplified JSON outputs for procurement documents
Spend Network’s summary endpoint provides a simplified JSON output that provides a flatter, smaller, more consistent output. This enables lower volumes of data to travel into databases and more consistent and easier parsing of the data.
JSON Output Structure and Information Design Principles
The JSON output for the API has been meticulously structured to ensure clarity, consistency, and ease of use. The following key principles have been adopted in its design:
1. A single document structure for all records
-
Consistency: All records, whether tender notice, planning or contract awards contain the same fields and all fields deploy consistent data structures at all times. This ensures that simple validation routines can be written for each document (e.g. a checksum for the total number of fields).
-
Use: Tender documents will contain fields for awards data, which will not be populated, it is critical for developers to use
release_tagsto determine the nature of the published document before accessing the appropriate data.
2. Clear and Descriptive Naming Conventions
-
Consistency: Each key follows a consistent naming pattern that aids in easy identification and understanding. For example, all monetary values related to awards are prefixed with
award_, making it straightforward to locate and differentiate from other values liketender_. -
Descriptiveness: Keys are named descriptively to convey the precise information they hold. For instance,
buyer_address_country_nameclearly indicates it stores the country name of the buyer's address.
3. Logical Grouping of Related Information
-
Categorisation: Related data points are grouped together logically. For example, all keys related to buyer information start with
buyer_(e.g.,buyer_name,buyer_address_country_name), ensuring that similar information can be found in proximity. -
Hierarchical Structure: Our data is broadly flat, but the small amount of hierarchy helps users navigate the data efficiently, recognizing patterns and relationships between different pieces of information.
4. Effective handling of one to many relationships
-
Managing edge cases: In rare cases contract award notices are published as an extension to a tender notice, in still rarer circumstances there are more than one award published against a given tender. We handle this dynamically, collating data where appropriate (e.g in the
award_titles) and using the first award found in fields where referential integrity is essential. This is the case in fields with the_firstsuffix. -
Implications: In some cases it is possible that only the first award from a set of multiple awards is being documented. In this context developers can use our complete API to gather additional records from the original published releases where necessary.
5. Comprehensive Data Coverage
-
Detailed Information: The JSON structure includes extensive details covering various aspects such as buyer details, award values in multiple currencies, tender specifics, and more. This comprehensive coverage ensures users have all necessary data in one place.
-
Multiple Data Types: The structure accommodates various data types including strings, numbers, arrays, and booleans, to accurately represent different kinds of information.
6. Timestamp and Date Management
-
ISO 8601 Format: All date and time values are provided in ISO 8601 format (e.g.,
2021-12-17T08:27:49Z), a widely accepted standard that supports interoperability and ease of parsing across different systems. -
Clear Distinction Between Dates: Different types of dates such as
release_date,start_date, andclosing_dateare clearly differentiated, ensuring precise tracking of timelines.
7. Nullability for Optional Fields
-
Explicit Nulls: Fields that might not always have a value (e.g.,
contact_url,buyer_address_street_address) are included with a null value when applicable, maintaining a consistent structure while signalling optional data.
8. Array Utilization for Multiple Entries
-
Lists for Multiple Items: Fields that can have multiple entries, such as
supplier_names,cpv_names, andsupplier_ids, are represented as arrays. This approach ensures flexibility and scalability in handling multiple values.
9. Identification and Referencing
-
Unique Identifiers: Keys like
ocidandtender_idare used to provide unique identifiers for contracts and tenders, supporting traceability and integration with other datasets. Where we are able to we will supply identifiers for suppliers with a unique id for companies to reconcile to the source. -
References: Fields such as
references_ocidsallow for linking related documents or entities, facilitating comprehensive data analysis.
10. Currency and Value Clarity
-
Explicit Currency Indicators: Monetary values are accompanied by currency indicators (e.g.,
award_currency_first,tender_currency), ensuring that users can accurately interpret financial data. -
Multiple Currency Representations: Values are provided in different currencies (USD, GBP, EUR) to cater to a diverse range of users and use cases.
11. Status and Metadata Information
-
Status Indicators: Fields like
tag_statusanddps_predoffer status information, helping users understand the current state and categorization of the data. -
Metadata for Traceability: Metadata fields such as
date_createdanddate_updatedprovide insights into the data's lifecycle, aiding in version control and auditing.
This structured approach ensures that the JSON output is both user-friendly and comprehensive, facilitating efficient data retrieval and analysis for diverse applications.
Example document
This example document shows how our summary api data is structured and published.
{
"_index": "sn-api-ocds-gold-v3-prod",
"_id": "ocds-0c46vo-0001-12ef087c-3ad3-4d72-b2bb-e3d416081402",
"_score": 1,
"_source": {
"has_attachment":"true"
"cpv_names": [
"Education and training services",
"Personnel services except placement and supply services",
"Specialist training services",
"Vocational training services",
"Personal development training services",
"Business and management consultancy services",
"Personnel services except placement and supply services",
"Specialist training services",
"Vocational training services",
"Personal development training services",
"Business and management consultancy services",
"Education and training services"
],
"tender_url": "https://www.contractsfinder.service.gov.uk/Notice/12ef087c-3ad3-4d72-b2bb-e3d416081402",
"closing_date": null,
"awards_usd_value": 0,
"date_updated": "2024-01-18T02:40:12.144016",
"buyer_address_country_name": "United Kingdom",
"tender_eur_value": 0,
"cpv_aug_names": [
"Personnel services except placement and supply services",
"Specialist training services",
"Vocational training services",
"Personal development training services",
"Business and management consultancy services"
],
"cpv_aug_codes": [
"79630000",
"80510000",
"80530000",
"80570000",
"79410000"
],
"buyer_name": "DRIVER AND VEHICLE STANDARDS AGENCY",
"tender_id": "tender_362771/1301350",
"language": "en",
"source": "cf_notices",
"release_tags": "planning",
"cpv_codes": [
"80000000",
"79630000",
"80510000",
"80530000",
"80570000",
"79410000",
"79630000",
"80510000",
"80530000",
"80570000",
"79410000",
"80000000"
],
"contracts_eur_value": 0,
"buyer_address_street_address": "112 Upper Parliament Street",
"buyer_address_locality": "Nottingham",
"buyer_address_iso_alpha2": "GB",
"contracts_gbp_value": 0,
"contact": "epscategoryteam@dvsa.gov.uk",
"awards_gbp_value": 0,
"supplier_names": [],
"processing_status": "success",
"supplier_ids": [],
"ocid": "ocds-0c46vo-0001-12ef087c-3ad3-4d72-b2bb-e3d416081402",
"buyer_address_region": "England",
"contracts_usd_value": 0,
"start_date": null,
"dps_pred": false,
"contact_url": null,
"date_created": "2024-01-16T02:35:38.235781",
"awards_eur_value": 0,
"tender_description": """Driver & Vehicle Standards Agency""",
"award_descriptions": "",
"tender_gbp_value": 0,
"tender_usd_value": 0,
"cpv_aug_data": [
{
"cpv_aug_names": "Personnel services except placement and supply services",
"cpv_aug_codes": "79630000",
"relevance_score": 16.9238
},
{
"cpv_aug_names": "Specialist training services",
"cpv_aug_codes": "80510000",
"relevance_score": 15.2334
},
{
"cpv_aug_names": "Vocational training services",
"cpv_aug_codes": "80530000",
"relevance_score": 9.0345
},
{
"cpv_aug_names": "Personal development training services",
"cpv_aug_codes": "80570000",
"relevance_score": 8.3424
},
{
"cpv_aug_names": "Business and management consultancy services",
"cpv_aug_codes": "79410000",
"relevance_score": 7.7439
}
],
"release_date": "2024-01-15T12:32:28Z",
"references_ocids": [],
"tag_status": "open",
"tender_title": "Tailored Executive Development",
"award_titles": ""
}
}
The following shows an example of a document where lotting features have been identified and collected.
{
"ocid": "ocds-0c46vo-0001-036588-2025_036588-2025",
"start_date": "2025-09-04T00:00:00+01:00",
"date_created": "2025-07-03T01:37:44.838811",
"tender_description": "Nest is on a path to becoming one of the largest pensions schemes in the UK and our growth trajectory means that the operating model for Nest Invest will need to evolve over the next ten years.\nIn order to support the continued strategic growth and development of the investment function Nest Invest will require ongoing specialist consultancy support for the development of the organisational model and development of the investment approach",
"award_descriptions": "",
"tender_gbp_value": 10000000,
"lots": {
"lot_descriptions": [
"1: Strategic investment business, organisational strategy and governance advice with extensive proven experience of international investment best practice with large Financial Conduct Authority (FCA) regulated Occupational Pension Schemes (OPS) with assets under management of £25 billion and above",
"2: Target Operating Model design and delivery including the transition and implementation of operating models for fund administration and custody service including additional SME operational support as needed to large Financial Conduct Authority (FCA) regulated Occupational Pension Schemes (OPS) (or similar) with assets under management of £25 billion and above. 35",
"3: Specialist investment consultancy services to large Financial Conduct Authority (FCA) regulated occupational pension schemes (OPS) with assets under management of £25 billion and above"
],
"lot_classifications": [],
"lot_earliest_start_date": "2025-09-04T00:00:00+01:00",
"lot_statuses": [
"active"
],
"lot_identifiers": [],
"lot_ids": [
"1",
"2",
"3"
],
"lot_currencies": [
"GBP"
],
"lot_total_value": 10000000.0,
"lot_count": 3,
"lot_amounts": [
3500000.0,
3500000.0,
3000000.0
],
"lot_titles": [
"1: LOT 1 Strategic investment business, organisational strategy and governance advice",
"2: LOT 2 Target Operating Model design and delivery including the transition and implementation of operating models for fund administration and custody service including additional SME operational support as needed",
"3: Specialist investment consultancy services to large Financial Conduct Authority (FCA) regulated occupational pension schemes (OPS"
],
"lot_latest_end_date": "2029-09-03T23:59:59+01:00",
"lot_primary_currency": "GBP",
"lot_procurement_categories": []
},
Field list
Below we have grouped fields and listed each possible field then and provided a field type and description.
Currencies and conversion
Our currency output adheres to international currency standards by using ISO 4217 codes for currency representation. This ensures that monetary values are clearly identified and standardised across different datasets, facilitating accurate interpretation and conversion. By employing ISO currency codes such as GBP (British Pound), USD (US Dollar), and EUR (Euro), the data maintains consistency and interoperability in financial reporting and analysis.
We use https://exchangeratesapi.io/ for currency conversion, which provides several key benefits, including accurate and up-to-date exchange rates sourced from reliable financial data providers, enhancing the reliability of financial reporting, supporting a wide range of currencies, enabling comprehensive and global financial analysis. Integrating this API into our system ensures that all currency-related data is consistent, precise, and reflects the correct conversion rates at the time of publication.
|
Code |
Field type |
Description |
|---|---|---|
|
|
String |
The original currency of an award notice as published in the source data, where the currency is adequately labelled and can be determined by Spend Network. This currency may be any known currency. |
|
|
Value |
The original value of an award as published in the source data, where the value is adequately structured and can be converted to a value field by Spend Network. |
|
|
Value |
The value of |
|
|
Value |
The value of |
|
|
Value |
The value of |
|
|
String |
The original currency of a tender notice as published in the source data, where the currency is adequately labelled and can be determined by Spend Network. This currency may be any known currency. This value is only populated when the source is in OCDS format and the contract notice is appended to a tender notice in a manner compliant with the standard. |
|
|
Value |
The original value of a tender as published in the source data and where the value is adequately structured and can be converted to a value field by Spend Network. This value is only populated when the source is in OCDS format and the contract notice is appended to a tender notice in a manner compliant with the standard. |
|
|
Value |
The value of |
|
|
Value |
The value of |
|
|
Value |
The value of |
Entities and Organisations
During our input process we are cleansing fields to provide, reliable consistent values across both buyer names and addresses. In some cases we also match supplier identifiers. The cleansing of buyer names is primarily for the UK, with new links being developed all of the time across other countries. Addresses are cleansed through a proprietary address management algorithm, splitting up codes, identifying postcodes and allocating clean country names, before then deriving a country code.
|
Name |
Field type |
Description |
|---|---|---|
|
|
String |
This field contains the name of the buying entity or organisation. It identifies the buyer involved in the tender or contract, facilitating recognition and tracking of the entity. |
|
|
String |
The name of the country where the buyer's address is located. Where the source provides an identifiable country name we will amend this entry to provide a consistent reference, e.g. “UK” is converted to “United Kingdom” |
|
|
String |
The locality or city where the buyer's address is situated. Where we can we seek to extract and separate address features into the correct patterns for greater geographical analysis. |
|
|
String |
The region where the buyer's address is situated. Where we can we seek to extract and separate address features into the correct patterns for greater geographical analysis. |
|
|
String |
This field lists the names of the suppliers involved in the contract or tender, the data is provided in a list format. |
|
|
List of strings |
This field contains unique identifiers for the suppliers, such as registration or company numbers. The source indexes for each ID are added as prefixes e.g. |
|
|
String |
This field represents the street address of the buyer. Where we can we seek to extract and separate address features into the correct patterns for greater geographical analysis. |
|
|
String |
This field uses the ISO 3166-1 alpha-2 code to represent the buyer's country. It provides a standardized and internationally recognized format for country identification. |
Dates and Times
The following dates and times are used in the contract award documents.
|
Field Name |
Field type |
Description |
|---|---|---|
|
|
Date time |
The contract start date. It indicates when the contract is scheduled to commence, |
|
|
Date time |
The contract end date. It indicates when the contract is scheduled to be completed, |
|
|
Date time |
The publisher’s own record for the date that the document was published. |
|
|
Date time |
This field captures any updates to the document. It indicates the most recent modification date. |
|
|
Date time |
This field specifies the deadline for submissions on tenders. It represents the final date for submitting tenders. |
|
|
Date time |
This field indicates the date gathered by Spend Network. It marks when the data was collected and recorded. If there is no release date or start date, this date is the best substitute. |
Document identifiers
We use the following document identifiers in the output, these are identifiers for the documents, OCIDs can be used as reliable database keys and are unique. By using these identifiers, we ensure that each document can be accurately tracked, referenced, and integrated into various data systems, supporting robust data management and analysis practices.
|
Field Name |
field type |
Description |
|---|---|---|
|
|
String |
This field represents the identifier provided by the publisher. It uniquely identifies the tender within the publisher's system. |
|
|
String |
This field is Spend Network's unique identifier, compliant with the Open Contracting Data Standard. It ensures consistent and standardised identification of contracts. |
|
|
String |
This field contains additional records that have been linked to the document as potential duplicates. Developers can use this list to suppress likely duplicates or, if required, show likely duplicates. |
Status and Metadata
Status and metadata tags provides information on the origin of the data, categorization of document types, the status of contracts, and classification of contract types. Each entry ensures clarity and consistency, facilitating accurate data interpretation and analysis.
|
Field Name |
Data Type |
Description |
|---|---|---|
|
|
String |
This field contains the name of the source code used to harvest the data. It indicates the origin of the data collection process. |
|
|
String |
This field specifies the document type, which can be 'tender', 'award', or 'planning'. It categorises the type of document being referred to. (List of options from GF) |
|
|
String |
This field indicates whether a contract is "open" or "closed". It specifies the current status of the contract, e.g., whether it is finished or underway. (List of options from GF) |
|
|
Boolean |
This field denotes whether Spend Network has identified that this contract is a framework or dynamic purchasing system (DPS) contract. It helps in classifying the type of contract. |
|
|
String |
ISO 639 language classification, automatically derived from a Google large language model. |
Descriptions and Titles
The following table provides a detailed description of the narrative fields within the JSON output related to tenders and awards.
→ award titles → comes in as a list, converted to a string (never an array)
→ Only for OCDS linked titles and awards
|
Field Name |
Data Type |
Description |
|---|---|---|
|
|
String |
This field contains the title of the tender. It provides a brief and specific name for the tender, summarising its main purpose. This value is only populated when the source is in OCDS format and the contract notice is appended to a tender notice in a manner compliant with the standard. |
|
|
String |
This field combines both the tender title and description, enabling more efficient in-memory text searching. |
|
|
String |
This field provides a detailed description of the tender. It includes the published information about the tender's requirements and objectives. This value is only populated when the source is in OCDS format and the contract notice is appended to a tender notice in a manner compliant with the standard. |
|
|
String |
This field contains descriptions of the awards associated with the tender. It provides published information about the awards granted. In the event that multiple awards are added as separate releases to a single tender, the awards descriptions will be concatenated in this field |
|
|
String |
This field includes the titles of the awards. It gives a concise and specific name for each award associated with the tender. In the event that multiple awards are added as separate releases to a single tender, the awards titles will be concatenated in this field. |
Contact Information
The following table provides a detailed description of specific fields within the JSON output related to contact information. Each field is accompanied by its data type and a brief description, facilitating a better understanding of the contact details provided and aiding in efficient data interpretation and analysis.
|
Field Name |
Data Type |
Description |
|---|---|---|
|
|
String |
This field contains the email address of the contact person or entity. It provides a direct communication channel for inquiries or further information. |
|
|
String |
This field includes the URL for contact information. It offers an online link for additional contact details or communication methods. |
Classification Codes
The following table provides a detailed description of specific fields within the JSON output related to procurement classification. Each field is accompanied by its data type and a brief description, facilitating a better understanding of the procurement categories and aiding in efficient data interpretation and analysis. CPV stands for Common Procurement Vocabulary, the EU procurement classification system, while "aug" stands for augmented, indicating additional codes added by Spend Network.
|
Field Name |
Data Type |
Description |
|---|---|---|
|
|
Array |
This field contains an array of names from the Common Procurement Vocabulary (CPV) that were provided by the original publisher. |
|
|
Array |
This field includes an array of augmented CPV names added by Spend Network. It offers additional classification names that enhance the standard CPV categorisation. |
|
|
Array |
This field contains an array of augmented CPV codes added by Spend Network. It provides additional classification codes that complement the standard CPV codes. |
|
|
Array |
This field includes an array of CPV codes from the Common Procurement Vocabulary. that were provided by the original publisher. |
URLs
The following table provides a detailed description of a specific field within the JSON output related to the URL of the published tender.
|
Field Name |
Data Type |
Description |
|---|---|---|
|
|
String |
This field contains the original source URL of the published tender. It provides a direct link to the tender's publication, enabling access to the full tender details and documentation. |
Lots
The following table provides a detailed description of a specific field within the JSON output related to lots in a published document.
|
Field name |
Data Type |
Description |
|---|---|---|
|
|
Integer |
The number of lots into which the tender or award is divided. Used to identify whether the procurement is split and how many components it includes. |
|
|
Array of Strings |
A list of identifiers for each individual lot. These identifiers are typically numeric strings (e.g., "1", "2"). |
|
|
Array of Strings |
Titles of each lot. These provide a concise description of the lot’s scope or purpose. Titles may include a prefix indicating lot number. |
|
|
Array of Strings |
Descriptive narrative for each lot. These typically include eligibility criteria, scope, or technical requirements. |
|
|
Array of Numbers |
Monetary values for each lot, expressed in the primary currency. These represent the estimated or awarded value for each lot. |
|
|
Number |
The total value of all lots combined. Used for summarizing the overall contract value when split across multiple components. |
|
|
String |
The ISO 4217 currency code used for all monetary amounts within the lot object (e.g., GBP). |
|
|
Array of Strings |
List of currencies applicable to the lots. Useful in cross-border or multi-currency procurement. |
|
|
DateTime |
The earliest scheduled start date for any of the lots. |
|
|
DateTime |
The latest scheduled end date for any of the lots. |
|
|
Array of Strings |
Statuses of individual lots (e.g., "active", "cancelled"). Multiple statuses may exist across lots in the same contract. |
|
|
Array |
A placeholder for CPV or other classification codes relevant to the lots. Currently not populated. |
|
|
Array |
Reserved for categorisation of lots by procurement category (e.g., goods, services, works). Currently not populated. |
Attachments
The following table provides a detailed description of a specific field within the JSON output related to the availability of attachments for a given document.
|
Field Name |
Data Type |
Description |
|---|---|---|
|
|
Boolean |
A field that shows whether a document has attachments associated with it. |
|
|
Array |
This field contains a list of urls for attachments that have been found for the given search. Each entry has a field for |
|
|
String |
The title of an attachment gathered from a specific page. This field is only present when the user has added |
|
|
URL |
The original URL of the attachment. This field is only present when the user has added |
API requests
Accessing the Spend Network API Endpoint
To access the Spend Network API endpoint for fetching records related to tenders, follow these steps:
API Endpoint URL
The endpoint URL is: https://api-test.spendnetwork.cloud/api/v3/notices/records_openopps
Query Parameters
Here are the query parameters you can use:
|
Name |
Type |
Description |
|---|---|---|
|
|
string |
Search term to include (maxLength: 100). |
|
|
string |
Search term to exclude (maxLength: 100). |
|
|
string |
Buyer name to include (maxLength: 100). |
|
|
string |
Supplier name to include (maxLength: 100). |
|
|
string |
Country name of the buyer to include (maxLength: 100). |
|
|
array[string] |
Country codes of the buyer to include. |
|
|
string |
Open Contracting ID to include (maxLength: 100). |
|
|
array[string] |
Languages to include. |
|
|
array[string] |
Languages to exclude. |
|
|
string($date-time) |
Tender deadline greater than or equal to. |
|
|
string($date-time) |
Tender deadline less than or equal to. |
|
|
string($date-time) |
Contract start date greater than or equal to. |
|
|
string($date-time) |
Contract start date less than or equal to. |
|
|
string($date-time) |
Contract start date exactly. |
|
|
string($date-time) |
Contract end date greater than or equal to. |
|
|
string($date-time) |
Contract end date less than or equal to. |
|
|
string($date-time) |
Contract end date exactly. |
|
|
string($date-time) |
Release date greater than or equal to. |
|
|
string($date-time) |
Release date greater than. |
|
|
string($date-time) |
Release date less than or equal to. |
|
|
string($date-time) |
Release date less than. |
|
|
string |
Release tags to include - defined as an array with one or more of the tags published by publishers using OCDS (see below). |
|
|
string |
Tag status to include (maxLength: 100). |
|
|
array[string] |
CPV codes to include. |
|
|
array[string] |
Sources to include. |
|
|
boolean |
Whether the contract is a dynamic purchasing system contract. |
|
|
boolean |
Include predicted CPV values. |
|
|
boolean |
Include only compiled records. |
|
|
boolean |
Include only original records. |
|
|
string |
Date sort direction ( |
|
|
integer |
Pagination offset (min: 0, max: 9900). |
|
|
integer |
Number of records to return (min: 0, max: 100). |
|
|
boolean |
Enable prefix search. |
|
|
integer |
Minimum value (min: 0). |
|
|
integer |
Greater than value (min: 0). |
|
|
integer |
Less than or equal to value (min: 0). |
|
|
integer |
Less than value (min: 0). |
|
|
string |
Currency to query for (maxLength: 3, e.g., USD, GBP, EUR). |
|
|
boolean |
Include duplicate records. |
|
|
boolean |
Call to include original URLs and file names from attachments. |
|
|
boolean |
Show only results with attachments |
Release Tags
Release tag items can be one or more of the following and expressed in an array.
tender
award
planning
award contract
contract award
tenderUpdate
awardUpdate
tenderAmendment
planningUpdate
awardUpdate contractUpdate
contractUpdate awardUpdate
tender planning
tenderCancellation
planning tender
contractAmendment
contractTermination
planning award
planningUpdate award
award planning
award planningUpdate
Example Code
import requests
query = {
"compiled_only": False,
"original_only": False,
"date_direction": "desc",
"offset": 0,
"limit": 50,
"prefix_search": False,
"release_tags__is": "tender",
"predicted_cpv_values": False,
"dedupe__is": False,
# Add additional parameters as needed
}
def object_to_url_search_params(obj):
params = []
for key, value in obj.items():
if isinstance(value, list):
for item in value:
params.append((key, item))
else:
params.append((key, value))
return params
url_query = requests.models.PreparedRequest()
url_query.prepare_url("<https://api-test.spendnetwork.cloud/api/v3/notices/records_openopps>", object_to_url_search_params(query))
url = url_query.url
print("Generated URL Query:", url)
def fetch_summary_api_records():
try:
response = requests.get(
url,
headers={
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_ACCESS_TOKEN", # Replace with your actual access token
},
)
response.raise_for_status() # Check for HTTP errors
body = response.json()
return body
except requests.RequestException as error:
print("Fetch error:", error)
return None
# Fetch the records
records = fetch_summary_api_records()
print(records)
Authentication
To access the API users need to generate a bearer token. This is generated by making a call to the access-token endpoint /api/v2/login/access-token which uses an OAuth2 compatible login, and returns an access token for future requests. Supports both JSON and form data formats. The payload returns a token and the expiration date as follows. To refresh the token just call the access-token endpoint with your credentials.
**{
"access_token": "string",
"token_type": "string",
"expiration_date": "string"
}**
Replace "Bearer YOUR_ACCESS_TOKEN" with your actual API access token.
For detailed API documentation and additional options, visit the Spend Network API Swagger page.
Error Handling
When interacting with the API, it is important to handle potential errors gracefully. This includes checking for HTTP errors and handling exceptions appropriately.
def fetch_summary_api_records():
try:
response = requests.get(
url,
headers={
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_ACCESS_TOKEN", # Replace with your actual access token
},
)
response.raise_for_status() # Check for HTTP errors
body = response.json()
return body
except requests.RequestException as error:
print("Fetch error:", error)
return None
except requests.HTTPError as http_err:
print(f"HTTP error occurred: {http_err}")
except Exception as err:
print(f"An error occurred: {err}")
# Fetch the records
records = fetch_summary_api_records()
print(records)
Example Query Parameters
Customise the query parameters for specific use cases to retrieve the desired data.
query = {
"date_direction": "asc",
"offset": 0,
"limit": 10,
"release_tags__is": "award",
"buyer_name__is": "MINISTRY OF DEFENCE",
}
Rate Limiting
Be aware of the API's rate limits which are based on all calls to the server rather than just your individual calls. There should be no reason for users collecting daily, paginated data to hit rate limits, however, implementing retry mechanisms and exponential backoff can help manage rate limits effectively.
Pagination
To handle large datasets, use the offset and limit parameters to paginate results. Note that there is a 10,000 record limit on what can be returned from any single query.
query = {
"offset": 0,
"limit": 100 # Adjust as necessary, but must be <= 100
}
# Iterate through pages
while True:
records = fetch_summary_api_records()
if not records or len(records) < query["limit"]:
break
query["offset"] += query["limit"]
How to filter notices by CPV
This guide explains how to use:
-
cpv__is -
prefix_search
Filtering by CPV (cpv__is)
For the OpenOpps notices endpoint (GET request), you repeat the parameter:
GET /api/v3/notices/records_openopps?cpv__is=48000000&cpv__is=72000000&cpv__is=85000000
For the summary endpoints (POST request), you send a list in JSON:
{
"cpv__is": ["48000000", "72000000", "85000000"]
}
Prefix CPV matching (prefix_search)
When should you use prefix search?
Use prefix_search=true when you want to match a family of CPV codes.
Example:
-
If you send
48000000withprefix_search=true, the API treats it like “anything starting with48”. -
That means codes like
48100000,48200000, etc. can match.
How to enable it
For OpenOpps notices endpoint (GET):
GET /api/v3/notices/records_openopps?cpv__is=48000000&cpv__is=72000000&prefix_search=true
For summary endpoints (POST):
{
"cpv__is": ["48000000", "72000000"],
"prefix_search": true
}
What happens with trailing zeros
With prefix_search=true, the system removes trailing zeros to create the prefix:
-
48000000becomes prefix48 -
72000000becomes prefix72
Sample responses
Here is an example of a typical response from the API:
{
"results": [
{
"tender_id": "tender_278767/1024151",
"buyer_name": "MINISTRY OF DEFENCE",
"tender_title": "The provision of End Point Assessment for Digital Apprenticeship Standards",
"release_date": "2021-12-17T08:27:49Z",
...
}
],
"total": 1234,
"offset": 0,
"limit": 10
}
Best Practices
-
Optimize Queries: Use specific and relevant query parameters to limit the amount of data returned.
-
Caching: Implement caching strategies to reduce the number of API calls and improve performance.
-
Error Handling: Ensure robust error handling to manage API errors gracefully.
-
Rate Limits: Be mindful of API rate limits and implement retry mechanisms where necessary.
-
Pagination: Use pagination to handle large datasets efficiently.
API Limitations
-
Record Limit: There is a 10,000 record limit on what can be returned from any query. Use pagination to retrieve additional records.
-
Update Frequency: Data is updated daily, so ensure your application accounts for this update cycle.
Contact Information
For further assistance or questions about the API, please contact our support team at contact@spendnetwork.com.
Further code examples
Example Javascript code
The following JavaScript code demonstrates how to access the Spend Network API to fetch records related to tenders, awards, or planning notices. This script constructs a query based on specified parameters and sends an HTTP GET request to the API endpoint. The query includes options such as date direction, result offset, and limit, as well as filters for release tags and CPV values.
The objectToURLSearchParams function converts the query object into URL search parameters, ensuring the correct format for the API request. The fetchSummaryAPIRecords function handles the API call, including setting the appropriate headers for authentication. Upon receiving a response, it checks for errors and parses the JSON response body.
To execute the code, make sure to replace TOKEN HERE with your actual API access token. This code snippet provides a robust foundation for integrating with the Spend Network API and retrieving procurement-related data efficiently.
const query = {
compiled_only: false,
original_only: false,
date_direction: "desc",
offset: 0,
limit: 50,
prefix_search: false,
release_tags__is: "tender", //tender,award,planning
predicted_cpv_values: false,
dedupe__is: false,
};
const objectToURLSearchParams = (obj: Record<string, any>): URLSearchParams => {
const params = new URLSearchParams();
for (const key in obj) {
if (Array.isArray(obj[key])) {
obj[key].forEach((value: any) => {
params.append(key, value);
});
} else {
params.append(key, obj[key]);
}
}
return params;
};
// Generate the query string
const urlQuery = objectToURLSearchParams(query).toString();
console.log("Generated URL Query:", urlQuery);
console.log(
`https://api-test.spendnetwork.cloud/api/v3/notices/records_openopps?${urlQuery}`,
);
export const fetchSummaryAPIRecords = async () => {
try {
const response = await fetch(
`https://api-test.spendnetwork.cloud/api/v3/notices/records_openopps?${urlQuery}`,
{
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: `Bearer TOKEN HERE`, // please add your sn-api access token
},
},
);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const body = await response.json();
return body;
} catch (error) {
console.error("Fetch error:", error);
return null;
}
};
Example Python code
The following Python code demonstrates how to access the Spend Network API to fetch records related to tenders, awards, or planning notices. This script constructs a query based on specified parameters and sends an HTTP GET request to the API endpoint. The query includes options such as date direction, result offset, and limit, as well as filters for release tags and CPV values.
-
Query Parameters: The
querydictionary contains the parameters for the API request. -
object_to_url_search_params Function: This function converts the dictionary into a list of tuples suitable for URL encoding.
-
URL Generation: The
requests.models.PreparedRequestobject is used to generate the URL with query parameters. -
fetch_summary_api_records Function: This function sends an HTTP GET request to the API endpoint, including the necessary headers for authentication. It checks for errors and parses the JSON response.
Make sure to replace "Bearer TOKEN HERE" with your actual API access token.
import requests
query = {
"compiled_only": False,
"original_only": False,
"date_direction": "desc",
"offset": 0,
"limit": 50,
"prefix_search": False,
"release_tags__is": "tender", # tender, award, planning
"predicted_cpv_values": False,
"dedupe__is": False,
}
def object_to_url_search_params(obj):
params = []
for key, value in obj.items():
if isinstance(value, list):
for item in value:
params.append((key, item))
else:
params.append((key, value))
return params
# Generate the query string
url_query = requests.models.PreparedRequest()
url_query.prepare_url("https://api-test.spendnetwork.cloud/api/v3/notices/records_openopps", object_to_url_search_params(query))
url = url_query.url
print("Generated URL Query:", url)
def fetch_summary_api_records():
try:
response = requests.get(
url,
headers={
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer TOKEN HERE", # please add your sn-api access token
},
)
response.raise_for_status() # Check for HTTP errors
body = response.json()
return body
except requests.RequestException as error:
print("Fetch error:", error)
return None
# Fetch the records
records = fetch_summary_api_records()
print(records)
Document Attachments
Spend Network’s summary API now supports both sourcing and downloading attachments (e.g. PDFs, DOCs) related to individual tender or contract documents. This feature allows users to programmatically access attachments, either via the original source information or through a direct download via Spend Network’s servers.
<aside> 🕓
A note on publishing cadence and attachments. On some occasions publishers release attachments separately from the original data publication. We collect additional documents on significant updates (e.g. when a contract is converted from a tender notice to a contract award) or on a regular data refresh.
To ensure users have the most up-to-date data and files we have created additional endpoints that can be called to return either the source of each attachment or to download each attachment.
</aside>
Filtering For Attachments
Our API contains a boolean that shows when a document has attachments associated with it. Users can use the attachment__is feature in their query to return only documents with attachments, or alternatively only those without attachments.
Example Query Parameters
query = {
"attachment__is":true,
"date_direction": "asc",
"offset": 0,
"limit": 10,
"release_tags__is": "award",
"buyer_name__is": "MINISTRY OF DEFENCE",
}
Show Attachment Sources
In order to be able to provide a source URL for a given attachment we have an additional feature that can be called which adds the sourcing data to the document payload.
To retrieve document metadata (i.e. the titles and source URLs) for attachments associated with published tenders or contracts, API users can include the attachment__show parameter in your request for a specific document:
|
Parameter |
Type |
Description |
|---|---|---|
|
|
|
When set to |
Example Query Parameters
Users should use the attachment__show parameter on a document by document basis to retain response time performance. Queries for multiple files will NOT be fast enough for production environments.
{
"attachment__show": true,
"ocid__is": "ocds-0c46vo-0001-12ef087c-3ad3-4d72-b2bb-e3d416081402",
}
Example Response Snippet
...
"attachments": [
{
"title": "Entwurfsplanung Heizung KG.pdf",
"url": "<https://www.vergabe-westfalen.de/.../Entwurfsplanung+Heizung+KG.pdf>"
},
{
"title": "LV Heizflächen Altbau.d83",
"url": "<https://www.vergabe-westfalen.de/.../LV+Heizfl%C3%A4chen+Altbau.d83>"
}
]
...
Downloading Attachments via Spend Network API
To simplify access to attachment files (bypassing source website restrictions), two dedicated endpoints are provided:
1. List Available Attachment Files
This allows users to list attachment files by title and url for a specific document.
Endpoint:
POST <https://api.spendnetwork.cloud/api/v3/attachments/list>
Authentication Required: Yes (Bearer token)
|
Parameter |
Type |
Description |
|---|---|---|
|
|
|
Internal source identifier (e.g. |
|
|
|
Unique tender ID (from the summary API) |
Example
The following request allows the user to return a list of attachments associated with a specific document.
curl -X POST \\
'<https://api.spendnetwork.cloud/api/v3/attachments/list>' \\
-H 'Authorization: Bearer YOUR_TOKEN' \\
-H 'Content-Type: application/json' \\
-d '{
"source": "td_vergabe_westfalen_de",
"tender_id": "41878101"
}'
Response
We use underscores (_) in filename values instead of period characters (.) to ensure compatibility with URL paths and to avoid issues with file extension parsing or routing logic in some systems.
[
{
"title": "SubmissionForm.docx",
"filename": "submissionform_docx"
}
]
Note: This filename value is required for the download endpoint.
2. Download Specific Attachment File
Endpoint Format:
GET /api/v3/attachments/download/{source}/{tender_id}/{filename}
Note: Use the
tender_idfield not theocididentifier.
Example
curl -X GET \\
'<https://api.spendnetwork.cloud/api/v3/attachments/download/td_vergabe_westfalen_de/41878101/submissionform_docx>' \\
-H 'Accept: application/json'
Behavior:
Returns the file as a direct download. In the event that the incorrect link has been used the API will return a Attachment file not found error.
🧠How It Fits Together
-
If the
has__attachmentfeature of a document is NOT an empty array, then you will get a response from the/attachments/listend point. -
Get the
sourceandtender_idfrom the returned JSON, and check for available attachments using the/attachments/listend point. -
Use
/attachments/listto retrieve a full list of filenames for that record. -
Compile a query using the
source,tender_idandfilenamefrom memory and send a request to the/attachments/download/...end point to fetch a specific file by filename.
Best Practices
-
Use
/attachments/listto get valid filenames for a specific document before calling/attachments/download. -
Ensure that the
sourceandtender_idmatch what is returned from the summary API. -
Always authenticate using your API token on both endpoints.
-
Collect attachments on the basis of user demand, rather than in advance in aggregate.