Procurement API v6 is the backend service for vendor, contract, invoice, renewal, and dashboard workflows. This service is used by the procurement platform-ui sub-app, interal to Topcoder staff.
All business routes are served under /v6/procurement and require bearer auth.
GET /v6/procurement/healthchecks service and database readiness./v6/procurement/api-docsexposes Swagger documentation.
GET /v6/procurement/dashboardreturns vendor count, active contract count, pending/overdue invoice counts and totals, expiring contract preview rows, and active renewal count.
GET /v6/procurement/vendorslists vendors.GET /v6/procurement/vendors/:idreturns one vendor.POST /v6/procurement/vendorscreates a vendor.PUT /v6/procurement/vendors/:idreplaces a vendor.DELETE /v6/procurement/vendors/:idhard-deletes a vendor.
GET /v6/procurement/contractslists contracts with vendor summaries and derived lifecycle.GET /v6/procurement/contracts/expiring?days=30lists active contracts whose end date falls inside the expiry window.GET /v6/procurement/contracts/:idreturns one contract.POST /v6/procurement/contractscreates a contract.PUT /v6/procurement/contracts/:idreplaces a contract.DELETE /v6/procurement/contracts/:idhard-deletes a contract.
GET /v6/procurement/invoiceslists invoices with vendor, optional contract, and derived payment-state summaries.GET /v6/procurement/invoices?state=pendingfilters by derived invoice state.GET /v6/procurement/invoices/overduelists overdue invoices.GET /v6/procurement/invoices/:idreturns one invoice.POST /v6/procurement/invoicescreates an invoice.PUT /v6/procurement/invoices/:idreplaces an invoice.DELETE /v6/procurement/invoices/:idhard-deletes an invoice.
GET /v6/procurement/renewalslists renewals with contract and vendor context.GET /v6/procurement/renewals/stagesreturns workflow stage metadata.GET /v6/procurement/renewals/:idreturns one renewal.POST /v6/procurement/renewalscreates a renewal atquotationand stampsquotationAt.PUT /v6/procurement/renewals/:idreplaces editable renewal fields without changing workflow stage.- Create and replace normalize
newStartDateandnewEndDateto the submitted business dates at midnight UTC. PATCH /v6/procurement/renewals/:id/stagemoves one workflow stage forward or backward.po_releaseis terminal and finalizes contract dates plus optional value in one transaction, applying the normalized renewal dates to the contract.DELETE /v6/procurement/renewals/:idhard-deletes a renewal.
The API does not persist alert-only states:
- Contract
lifecycleis derived from storedContract.statusandendDate. - Invoice
paymentStateis derived from storedInvoice.status,dueDate, andpaidDate. - Active renewals are renewals whose
stageis notpo_release.
Money fields are serialized as numbers in read models and dashboard totals.
Health remains unguarded. Every business controller uses
ProcurementAccessGuard and exact scope metadata on each handler.
| Caller type | Required access | Notes |
|---|---|---|
| Human | procurement-user or procurement-admin role |
Role claims may be supplied through role or roles. |
| Machine read | procurement:read scope |
Write scope is not treated as implicit read access. |
| Machine write | procurement:write scope |
Required for create, replace, delete, and renewal stage movement. |
| Missing route scope metadata | Denied for machine callers | Business handlers must declare explicit scopes. |
Authentication is delegated to the shared bearer-token middleware. Local login and local user-management endpoints are intentionally absent from this service.
Required:
DATABASE_URL- PostgreSQL connection string used by Prisma.AUTH_SECRET- JWT secret used bytc-core-library-js.VALID_ISSUERS- JSON array or comma-separated issuer list accepted by the auth middleware.
Optional:
PORT- HTTP port, default3000.
Node.js 26.12.1 and pnpm 11.15.1 are the supported local toolchain. Run
nvm use, install dependencies with pnpm install, generate Prisma with
pnpm prisma generate, and start the service with pnpm start:dev.
The production image uses Alpine 3.24's patched Node.js 26.12.1 package and runs
as the unprivileged app user (UID 10001). Build-only package managers and
development dependencies are excluded from the final image.
This branch uses tc-core-library-js 4.0.0-rc.1. Use its named
createJwtVerifier / createJwtAuthenticator, createM2MClient, and
createBusApiClient exports for shared authentication and bus API publishing.
Service-specific roles, scopes, sessions and ownership checks remain in this service.
The former bus wrapper dependency and local JWT cryptography must not be reintroduced.
RSA verification requires an exact configured issuer and audience (JWT_AUDIENCE
for client tokens, AUTH0_AUDIENCE for machine/API tokens, or this service's explicit
issuer-policy settings). HMAC secrets must be at least 32 bytes; no default secret
is supplied. Expiry is enforced. Machine identity comes from the shared verifier,
not the presence of scopes. Supply real development credentials through the service's
existing environment configuration before deployment.
Bus publishers use createBusApiClient(config).postEvent(event) with the existing
event envelope and optional key. Configure BUSAPI_URL for v6 and the existing
OAuth credentials/token provider. The client uses bounded HTTPS requests and does
not retry POSTs automatically. Application retry/outbox behavior remains local.
See the core migration guide for the API mapping, compatibility requirements, and rollout scope.
Container stages that install Node through APK constrain nodejs-current to the
major version in NODE_VERSION, rather than an exact Alpine package revision.
Alpine replaces older patch packages in its repositories; the compatible pin
allows current security patches while a build-time check rejects a different
Node major. The runtime keeps Alpine's dynamically linked Node and system
libraries. Existing non-root users and application entrypoints are preserved.
Build stages using a versioned official Node image retain their configured
version, and pnpm build arguments are explicitly declared in the consuming stage.
The frozen pnpm graph pins the shared Topcoder library to an immutable revision
and applies patched runtime and tooling dependencies. Older tooling uses a
tested minimatch adapter. Run pnpm audit and pnpm test:dependency-compat
alongside the existing lint, build and test checks when changing dependencies.
Container bases are pinned by digest, and Alpine packages receive security
updates during image builds.