API & MCP
Build on VETR from your own applications, or connect an AI assistant directly to your proposal workspace.
https://vetrproposal.com/api/v1Getting started
- Make sure your organization is on Professional or Enterprise — API and MCP access is checked on every request.
- Create a token at
Settings → API Tokens, choosing the abilities you need. - Send it as a bearer token on every request.
curl -s "https://vetrproposal.com/api/v1/proposals?status=draft&per_page=10" \ -H "Authorization: Bearer $VETR_TOKEN" \ -H "Accept: application/json"
Authentication
Bearer token (Laravel Sanctum). Create a token at Settings → API Tokens and send it on every request:
Authorization: Bearer YOUR_TOKEN
Token abilities
A new token is created with read selected by default. If you intend to create or change data, tick write when you create the token — a read-only token returns 403 on every write.
| read | Every GET endpoint. Selected by default when you create a token. |
| write | POST, PUT and PATCH — and the MCP tools that send data to Google Drive or GovSlack. |
| delete | DELETE endpoints. |
What every request must satisfy
- A valid bearer token that has not been revoked.
- Your user account is active.
- Your email address is verified.
- Your organization is not suspended or cancelled.
- Your organization is on the Professional or Enterprise plan — API and MCP access is checked on every request, not only when the token is created.
- For writes, your role must be able to contribute (viewers are read-only) and the token must carry the matching ability.
Rate limit
60 requests per minute, counted per user across all of that user's tokens. The same limit applies on every plan.
Token lifetime
Tokens do not expire on a timer. They are revoked when you delete them, and automatically when the organization's subscription ends.
Versioning
The version is in the path (/api/v1). Additive changes — new fields, new endpoints — ship without a version bump; anything that would break an existing client ships as /api/v2 and v1 keeps running.
Endpoints
25 endpoints. Every list endpoint is paginated and scoped to your organization.
Account
GET/api/v1/mereadThe authenticated user and the organization the token acts for.
Returns: id, name, first_name, last_name, email, organization_id, role
Proposals
GET/api/v1/proposalsreadList proposals in your organization, newest first, paginated.
Query parameters
| status | string | optional | Filter by proposal status. |
| per_page | integer | optional | Default 15, maximum 100. |
Returns: A paginated collection of proposals.
POST/api/v1/proposalswriteCreate a proposal against an existing RFP.
Body
| rfp_id | uuid | required | Must belong to your organization. |
| title | string | required | Max 255 characters. |
| status | string | optional | Cannot be a gated stage — those move through the review workflow. |
| bid_amount | number | optional | |
| executive_summary | string | optional |
Returns: The created proposal.
GET/api/v1/proposals/{proposal}readRetrieve one proposal.
Returns: A single proposal.
PUTPATCH/api/v1/proposals/{proposal}writeUpdate a proposal.
Body
| title | string | optional | |
| status | string | optional | Gated stages are rejected — use the review & submission workflow. |
| bid_amount | number | optional | |
| executive_summary | string | optional | |
| proposal_manager_id | uuid | optional | Must be a user in your organization. |
Returns: The updated proposal.
DELETE/api/v1/proposals/{proposal}deleteSoft-delete a proposal.
Returns: 204 No Content.
Tasks
GET/api/v1/tasksreadList tasks in your organization.
Query parameters
| status | string | optional | |
| assigned_to | uuid | optional | |
| priority | string | optional | |
| per_page | integer | optional | Default 15, maximum 100. |
Returns: A paginated collection of tasks.
POST/api/v1/taskswriteCreate a task, optionally attached to a proposal or RFP.
Body
| title | string | required | |
| description | string | optional | |
| type | string | optional | |
| status | string | optional | |
| priority | string | optional | |
| due_date | date | optional | |
| assigned_to | uuid | optional | Must be a user in your organization. |
| context_type | string | optional | Required together with context_id. |
| context_id | uuid | optional | Required together with context_type; must belong to your organization. |
Returns: The created task.
GET/api/v1/tasks/{task}readRetrieve one task.
Returns: A single task.
PUTPATCH/api/v1/tasks/{task}writeUpdate a task.
Body
| title | string | optional | |
| description | string | optional | |
| status | string | optional | |
| priority | string | optional | |
| due_date | date | optional | |
| assigned_to | uuid | optional |
Returns: The updated task.
DELETE/api/v1/tasks/{task}deleteDelete a task.
Returns: 204 No Content.
PUT/api/v1/tasks/{task}/statuswriteMove a task to a new status without sending the whole record.
Body
| status | string | required |
Returns: The updated task.
Partners
GET/api/v1/partnersreadList teaming partners.
Query parameters
| status | string | optional | active, inactive, prospect or archived. |
| search | string | optional | Partial match on partner name. |
| per_page | integer | optional | Default 15, maximum 100. |
Returns: A paginated collection of partners.
POST/api/v1/partnerswriteAdd a teaming partner.
Body
| name | string | required | |
| status | string | optional | active, inactive, prospect or archived. |
| business_size | string | optional | |
| primary_contact_name | string | optional | |
| primary_contact_email | optional | ||
| naics_codes | array | optional | |
| core_competencies | array | optional | |
| cage_code | string | optional | Max 10 characters. |
| sam_uei | string | optional | Max 20 characters. |
Returns: The created partner.
GET/api/v1/partners/{partner}readRetrieve one partner.
Returns: A single partner.
PUTPATCH/api/v1/partners/{partner}writeUpdate a partner.
Body
| name | string | optional | |
| status | string | optional | |
| business_size | string | optional | |
| primary_contact_name | string | optional | |
| primary_contact_email | optional | ||
| naics_codes | array | optional | |
| core_competencies | array | optional |
Returns: The updated partner.
DELETE/api/v1/partners/{partner}deleteRemove a partner.
Returns: 204 No Content.
Past performance
GET/api/v1/past-performancesreadList past-performance records.
Query parameters
| status | string | optional | |
| agency | string | optional | Partial match on agency name. |
| per_page | integer | optional | Default 15, maximum 100. |
Returns: A paginated collection of past-performance records.
POST/api/v1/past-performanceswriteRecord a past-performance contract.
Body
| contract_number | string | required | Max 50 characters. |
| contract_title | string | required | |
| agency_name | string | required | |
| contract_type | string | optional | |
| start_date | date | optional | |
| end_date | date | optional | |
| contract_value | number | optional |
Returns: The created record.
GET/api/v1/past-performances/{past_performance}readRetrieve one past-performance record.
Returns: A single record.
PUTPATCH/api/v1/past-performances/{past_performance}writeUpdate a past-performance record.
Body
| contract_title | string | optional | |
| agency_name | string | optional | |
| contract_type | string | optional | |
| start_date | date | optional | |
| end_date | date | optional | |
| contract_value | number | optional |
Returns: The updated record.
DELETE/api/v1/past-performances/{past_performance}deleteRemove a past-performance record.
Returns: 204 No Content.
Compliance
GET/api/v1/compliance-itemsreadList compliance-matrix items.
Query parameters
| proposal_id | uuid | optional | |
| status | string | optional | |
| per_page | integer | optional | Default 15, maximum 100. |
Returns: A paginated collection of compliance items.
GET/api/v1/compliance-items/{complianceItem}readRetrieve one compliance item.
Returns: A single compliance item.
PUT/api/v1/compliance-items/{complianceItem}/statuswriteMove a compliance item to a new status.
Body
| status | string | required |
Returns: The updated compliance item.
Errors
200OK- The request succeeded.
201Created- A POST created the record.
204No Content- A DELETE succeeded. There is no response body.
401Unauthenticated- No Authorization header was sent.
- The token was revoked, or the organization's subscription ended and its tokens were revoked with it.
403Forbidden- The token lacks the ability the endpoint needs — a default token is read-only.
- The organization's plan does not include API access (Professional and Enterprise only).
- The organization is suspended or cancelled.
- The email address on the account is not verified.
- The user's role is read-only and the request was a write.
404Not Found- No such record — or the record belongs to another organization. The API does not distinguish the two, deliberately.
422Unprocessable Content- Validation failed. The response body carries an `errors` object keyed by field name.
429Too Many Requests- The 60-per-minute limit was exceeded. Retry after the window resets.
MCP server
Connect an MCP-capable AI assistant straight to your VETR workspace. It can search your proposals, read compliance status, check a VETR score and find teaming partners — without you pasting anything into a chat window.
https://vetrproposal.com/mcp/vetr Authorization: Bearer YOUR_TOKEN
Transport
Streamable HTTP (JSON-RPC over POST). Point any MCP-capable client at the URL above.
Authentication
The same Sanctum tokens as the REST API. Send `Authorization: Bearer YOUR_TOKEN`; create one at /dashboard/settings/api-tokens.
Plans
Professional and Enterprise. The plan is checked on every request, not only when the token is created.
Token abilities
A default token is read-only, which covers the read tools. The two tools that send data outside VETR — Google Drive export and GovSlack notification — require a token with the `write` ability.
Data isolation
Every tool is scoped to the organization the token belongs to. There is no way to read another organization's data through MCP.
Tools
export-proposal-to-drive-toolwriteExport a proposal to the organization's connected Google Workspace (Assured Controls) Drive. Only works when an admin has enabled the integration (Enterprise plan, consent, and Assured Controls attestation); otherwise it reports the integration is unavailable and nothing leaves the platform.
get-compliance-status-toolreadGet the compliance matrix status for a proposal. Shows which requirements are met, in progress, or missing. Includes compliance score percentage.
get-proposal-detail-toolreadGet full details of a specific proposal including sections, compliance items, tasks, and past performance. Use the proposal ID from SearchProposals results.
get-vetr-score-toolreadGet the VETR (Value, Experience, Teaming, Responsiveness) score breakdown for a proposal. The VETR framework is VETR's proprietary methodology for assessing proposal win probability.
notify-gov-slack-toolwritePost a proposal status update to the organization's connected GovSlack channel. Sends only the proposal title and status — never proposal content. Only works when an admin has connected GovSlack and consented; otherwise it reports the integration is unavailable.
search-partners-toolreadSearch for teaming partners in your partner database. Filter by capabilities, certifications, or name. Shows NAICS codes, set-aside eligibility, and past performance ratings.
search-proposals-toolreadSearch and filter proposals by status, title, or agency. Returns a list of proposals with key metrics including VETR scores, submission deadlines, and win probability.
Resources
file://resources/proposal-document-resourceAn index of your proposals — id, title, status, agency and deadline. Read one in full with the get-proposal-detail tool.
Webhooks
VETR delivers HMAC-signed webhook payloads for the events your organization subscribes to, so you can react to proposal and compliance changes without polling. Configure endpoints from your organization settings; each delivery carries a signature header you should verify before trusting the body.