Skip to content

feat: add GSA eBuy requests, attachment URLs and access check - #9

Open
makegov-mark[bot] wants to merge 2 commits into
mainfrom
feat/ebuy
Open

makegov-mark[bot] wants to merge 2 commits into
mainfrom
feat/ebuy

Conversation

@makegov-mark

@makegov-mark makegov-mark Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

What

Adds support for the GSA eBuy endpoints introduced in Tango API 5.1.0.

Method Endpoint
ListEbuyRequests / IterateEbuyRequests GET /api/ebuy/requests/
GetEbuyRequest GET /api/ebuy/requests/{rfq_id}/
GetEbuyAttachmentURL GET /api/ebuy/requests/{rfq_id}/attachments/{doc_seq_num}/download/
GetEbuyAccess (typed *EbuyAccess) GET /api/ebuy/access/
  • ListEbuyRequestsOptions names every filter the endpoint accepts: Search, RfqID, ReferenceNumber, RequestType, Status, Sin, Schedule, BuyerAgency, Agency, ContractNumber, IssueDate[After/Before], CloseDate[After/Before], Ordering.
  • ShapeEbuyRequestsMinimal mirrors the API's default list shape.
  • GetEbuyAttachmentURL does not follow the API's redirect. It returns the short-lived presigned URL from the Location header, so callers decide when (and with which client) to download. A link entry (is_link: true) returns *EbuyLinkAttachmentError, which carries the link in URL and unwraps to *ValidationError; a document not yet captured returns *NotFoundError.
  • Redirect handling is per request: requestSpec gains a noRedirect flag that uses a shallow copy of the configured *http.Client with CheckRedirect set, so the shared client and every other call are unchanged.

Behavior worth knowing

  • Requests are scoped to the caller's own linked GSA schedule contracts and require the Pro tier or above. With no linked contract the list is empty rather than an error; GetEbuyAccess tells the two apart.
  • A request outside scope returns *NotFoundError, the same as an unknown id.
  • status is frozen at the last-seen state; read last_seen for staleness. contract_number is a filter only and never returned.

These are documented on the options struct, the methods, docs/API_REFERENCE.md, and the CHANGELOG.

Testing

  • ebuy_test.go: filter mapping for every option, nil options, iterator paging, detail shaping and 404, the attachment redirect (asserts exactly one request and that the redirect target is never fetched), the shared client still following redirects for other calls, the link-entry 400, uncaptured 404, 3xx without Location, unexpected 2xx, argument validation, and all three access-response shapes.
  • tests/integration/ebuy_test.go: a live GetEbuyAccess smoke test (works for any key; no eBuy grant needed).
  • go test -race ./... green on Go 1.23; golangci-lint v1.64.8 (the version CI resolves) clean.

Attachment text (Tango API 5.9.1)

  • attachments(extracted_text) returns the text extracted from an attachment's document.
  • This SDK returns untyped records and passes the shape through unchanged, so the change is documentation plus one pass-through test.
  • It is returned only when named: the default shape and attachments(*) leave it out, and no preset includes it.
  • The key is absent rather than null for an attachment with no text (a link, an empty scan, or a document not yet extracted).
  • Checks after this commit: gofmt, go vet and go test -race ./... pass. golangci-lint was not run locally.

🤖 Generated with Claude Code

vdavez and others added 2 commits September 28, 2026 14:26
Adds ListEbuyRequests, IterateEbuyRequests, GetEbuyRequest, GetEbuyAttachmentURL and GetEbuyAccess for the eBuy endpoints introduced in Tango API 5.1.0.
ListEbuyRequestsOptions names every filter the endpoint accepts, and ShapeEbuyRequestsMinimal mirrors the API's default list shape.
GetEbuyAttachmentURL stops at the API's redirect and returns the presigned URL from the Location header; a link entry returns EbuyLinkAttachmentError carrying the link.
The no-redirect behavior is per request, so the client's shared http.Client is untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`attachments(extracted_text)` on an eBuy request returns the text extracted from an attachment's document.
The SDK returns untyped records and passes the shape through unchanged, so this is documentation plus a pass-through test.
The leaf is returned only when named: the default shape and `attachments(*)` leave it out, and no preset includes it.
The key is absent rather than null for an attachment with no text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vdavez
vdavez marked this pull request as ready for review October 10, 2026 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant