Start with metadata, then ask for text.
Attachment workflows usually need two layers. First, list the source URLs, file names, package pages, labels, and hashes tied to an opportunity. Then search or fetch extracted text when the document has been indexed.
Find SAM.gov current opportunities with extracted attachment text.
Start with the opportunity list when you need a production query that returns records with document features. Use source=sam_current and hasExtractedText=true to find records whose documents block has indexed text.
{
"data": [
{
"recordId": "00000000-0000-4000-8000-000000000001",
"threadKey": "sam:W912ABC26R0001",
"summary": {
"sourceName": "sam-contract-opportunities-current",
"title": "Enterprise IT Support Services",
"agencyName": "Defense Logistics Agency"
},
"documents": {
"hasPackagePage": true,
"hasPdf": true,
"hasExtractedText": true,
"hasTechnicalDocuments": false,
"attachmentCount": 3
}
}
],
"page": { "limit": 5, "nextCursor": null }
}When you have a recordId, scope the document calls.
Scoped document calls are better for opportunity review screens and agents. They keep the source record, package page, text, and evidence together instead of forcing a second join in your app.
# 1. Fetch document metadata for one opportunity
curl -s 'https://api.boringdataplatform.com/v1/opportunities/<recordId>/documents' \
-H 'Authorization: Bearer <YOUR_API_KEY>'
# 2. Return bounded extracted text for the largest indexed document
curl -s 'https://api.boringdataplatform.com/v1/opportunities/<recordId>/documents/text?max_chars=5000' \
-H 'Authorization: Bearer <YOUR_API_KEY>'
# 3. Search only within that opportunity's indexed document text
curl -s 'https://api.boringdataplatform.com/v1/opportunities/<recordId>/documents/search?q=delivery%20schedule&limit=5' \
-H 'Authorization: Bearer <YOUR_API_KEY>'Coverage varies by source
SAM.gov records do not all have attachments. Some attachments are links, some are PDFs, and some have no extracted text.
Private storage stays private
Public responses return document metadata, source URLs, snippets, and hashes. Internal object-storage paths are not exposed.
Search is keyword-based
Document text search matches indexed chunks when live document search is enabled. Use exact terms that should appear in the attachment text.
Fetch the documents block for a SAM.gov current opportunity.
Replace the API key and run these commands from a shell with jq installed. The first request finds a SAM.gov current opportunity with extracted text; the second fetches its document metadata.
export BDP_API_KEY='<YOUR_API_KEY>'
record_id=$(
curl -s 'https://api.boringdataplatform.com/v1/opportunities?source=sam_current&hasExtractedText=true&limit=1' \
-H "Authorization: Bearer $BDP_API_KEY" \
| jq -r '.data[0].recordId'
)
curl -s "https://api.boringdataplatform.com/v1/opportunities/${record_id}/documents" \
-H "Authorization: Bearer $BDP_API_KEY"