Integrations & API

Proposal API

Create proposal drafts, update items and sponsor requirements, retrieve links, and follow acceptance and signing through REST API v2 and MCP.

Use the proposal API when another system prepares sponsorship offers for your team. For example, a lead engine can create a draft for an approved sponsor, add the placements and dates you want to offer, then let you review and share it in Sponsy.

Creating a draft does not email the sponsor, publish the offer, or book slots. You choose when to share it. Once the sponsor accepts, Sponsy follows the proposal's normal acceptance settings, including deal and slot creation.

The endpoints are part of REST API v2. V2 beta access and an API v2 bearer token are required. Creating or changing proposals requires Pro or Custom, plus the relevant token permissions. See API setup for access and token management.

A draft-first workflow

  1. Find or create the customer and contacts you want to address.
  2. Read the publications and placements to get their IDs and rate settings.
  3. Create the draft with its items, prices, dates, and sponsor requirements.
  4. Save the returned proposal ID in your system. Use that ID to read or update the same draft on later runs.
  5. Review the proposal in Sponsy, then share it with the sponsor.
  6. Read the proposal again to follow its response and signing state.

Keep sending as a deliberate step. A nightly job that prepares drafts does not need to publish them or send reminders.

Endpoints and permissions

All paths below start at https://api.getsponsy.com/v2. Send Authorization: Bearer <token> with every request. Your token needs the listed proposal permission, and its user must also have access to the workspace and publications involved.

Method and pathPurposeToken permission
GET /proposalsList proposals with filters and cursor paginationproposals.read
GET /proposals/{id}Read an offer, its items, link, and lifecycle stateproposals.read
POST /proposalsCreate a draftproposals.create
PATCH /proposals/{id}Edit an offer or archive/unarchive itproposals.update
DELETE /proposals/{id}Soft-delete a draftproposals.delete
POST /proposals/{id}/publishMake a draft available on its offer linkproposals.update
POST /proposals/{id}/remindersExplicitly email a proposal reminderproposals.update
GET /proposals/{id}/insertion-orderRetrieve a direct proposal's insertion-order PDFproposals.read
POST /proposals/{id}/groups/publisher-approvalAsk selected agency groups' publishers for approvalproposals.update
GET /proposal-groupsList incoming publisher groupsproposals.read
GET /proposal-groups/{id}Read an incoming publisher groupproposals.read
POST /proposal-groups/{id}/acceptAccept as the group's publisherproposals.update
POST /proposal-groups/{id}/rejectReject as the group's publisher, with a reasonproposals.update

The token user's effective workspace permissions also apply. Prices, unit prices, totals, and agency fees require financials.read. Financial fields are returned as null without it. Financial inputs are ignored without financials.update, preserving existing prices during non-financial edits. Insertion-order PDFs also require financials.read. Requiring a signature needs your workspace's e-signature capability.

Create a draft

Save a request such as this as proposal.json, replacing the example UUIDs with IDs from your workspace:

{
  "customerId": "11111111-1111-4111-8111-111111111111",
  "dealName": "November newsletter sponsorship",
  "extraMessage": "Two November issues for your review.",
  "assetsCollectionRequired": true,
  "requireSignature": true,
  "items": [
    {
      "publicationId": "22222222-2222-4222-8222-222222222222",
      "placementId": "33333333-3333-4333-8333-333333333333",
      "priceType": "FLAT",
      "price": 750,
      "quantity": 2,
      "proposedDates": ["2026-11-10", "2026-11-17", "2026-11-24"],
      "recommendedDates": ["2026-11-10", "2026-11-17"]
    }
  ]
}
curl https://api.getsponsy.com/v2/proposals \
  -H "Authorization: Bearer $SPONSY_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data @proposal.json

The response is the created proposal, with its id, status, url, and item IDs. Keep the item IDs when editing those items later. The offer remains a draft even though its future share URL is returned.

Item pricing supports FLAT, CPC, and CPM. Send explicit prices if your job calculates them from rate settings; check the reference for the defaults used when a price is omitted. quantity is the number of placements offered. proposedDates contains the available choices, and recommendedDates marks the choices you recommend. Date values use YYYY-MM-DD; range-based placements also support start|end entries such as 2026-11-01|2026-11-30.

You can also provide main contacts, an associated deal, expiration, payment and asset requirements, deal custom fields, collection selections, and item content or slot-detail fields. Main contacts must belong to the selected customer. Publications, placements, fields, collections, and associated deals are checked against the workspace and the proposal's ownership rules.

To link an offer item to existing items in its associated deal, use the explicit dealItemIds field. Those IDs must belong to that deal and match the item's publication and placement. Internal linkage keys in metadata are reserved; do not put deal or slot IDs into metadata to bypass these checks.

Update, read, and delete

PATCH changes only the fields you include. For example, save this as proposal-update.json to change the message and expiration without changing the items:

{
  "extraMessage": "Updated with the dates we discussed.",
  "expiresAt": "2026-11-05T17:00:00Z"
}
curl -X PATCH "https://api.getsponsy.com/v2/proposals/$PROPOSAL_ID" \
  -H "Authorization: Bearer $SPONSY_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data @proposal-update.json

Omit items to keep the item list. When you include it, send the complete desired list: retain an existing item's id to edit it, omit id for a new item, and leave an item out to remove it. Sending customFieldValues replaces the proposal's publisher field-value list. Pass null only for fields the reference marks nullable; for example, expiresAt: null clears expiration.

Read the proposal with GET /proposals/{id}. Delete an unwanted draft with DELETE /proposals/{id}. To remove a sent or completed offer from the active list, PATCH {"isArchived": true} instead; PATCH {"isArchived": false} restores it. Completed proposals retain their agreement history and cannot be freely rewritten.

List and follow changes

GET /proposals returns { "data": [...], "cursor": { "beforeCursor": ..., "afterCursor": ... } }. Lists show unarchived proposals by default. Use isArchived=true for archived offers. Filters include status, customerId, associatedDealId, createdAtFrom, createdAtTo, updatedAtFrom, and updatedAtTo.

For a CRM sync, filter by updatedAtFrom and keep the proposal IDs you have already processed. Use a small overlap between polling windows to avoid missing updates at the boundary. Follow the returned afterCursor as the next request's afterCursor, with the same filters and ordering, until it is null. You can set limit, orderBy (createdAt or updatedAt), and orderDirection (ASC or DESC).

Response and signing state

Read the returned status and lifecycle timestamps rather than writing an accepted or signed state into a proposal. Viewing, acceptance, payment, and signing are separate events; a view does not mean the sponsor has agreed to the offer.

The response includes publishedAt, viewedAt, lastViewedAt, viewCount, acceptedAt, rejectedAt, ioSignedAt, and payment timestamps, alongside status and paymentStatus. createdDealId identifies the deal made by acceptance. A safe signature summary is returned when available; signature audit IP addresses and user-agent data are kept private.

Acceptance uses Sponsy's existing proposal workflow. Your integration can read the resulting deal reference and retrieve its bookings through the deal and slot APIs. It does not need to recreate them. The current acceptance flow creates a deal for accepted items; setting createDeal to false does not bypass that existing behavior.

Publish, remind, and download the agreement

POST /proposals/{id}/publish makes the offer available at its link. It does not send an email. You can still review and share the proposal from Sponsy instead. Draft creation and publication do not impersonate sponsor acceptance.

POST /proposals/{id}/reminders is an email action. Send {} for the standard reminder, or provide {"message": "A quick reminder about the November dates."}. It uses the proposal's main contacts, or the customer's primary contacts when none are selected. Do not call this endpoint automatically unless your workflow is meant to send a reminder.

GET /proposals/{id}/insertion-order returns a download URL, filename, and report ID for a direct proposal's PDF, including the signature when present. An accepted proposal's agreement remains downloadable after expiration and when archived. Archived proposals in other states are unavailable; an expired published or in-negotiation offer cannot generate an agreement. Drafts are unavailable too.

Agency proposals

Set isAgencyProposal: true when creating an agency offer. Its items are grouped by publication, with separate groups even when two publications belong to the same publisher. You can use the agency's own publications and its active managed publications, with the applicable contracted fee settings. You cannot use an unrelated workspace's publication by passing its ID.

PATCH can replace agency items and edit group messages, notes, ordering, and archive state through groups. Replacing the item list rebuilds the groups and resets their approvals. Editing only group messages, notes, ordering, or archive state keeps their existing approvals.

Ask for publisher approval with POST /proposals/{id}/groups/publisher-approval and a body such as {"groupIds": ["44444444-4444-4444-8444-444444444444"]}. The publisher can list incoming groups through /proposal-groups and accept or reject its own group. Rejection requires a reason. These publisher actions are separate from the advertiser accepting the proposal.

Agency proposals follow the app's multi-party approval flow. The app does not offer agency signatures or agency insertion-order downloads, so these are not enabled through the API either.

MCP proposal tools

Sponsy MCP exposes the same proposal workflows:

ToolsUse
find_proposals, get_proposalSearch and read offers
create_proposal, update_proposal, delete_proposalPrepare and manage drafts
publish_proposal, remind_proposalDeliberate publication and reminder actions
get_proposal_insertion_orderRetrieve the direct agreement PDF
find_proposal_groups, get_proposal_groupRead incoming publisher groups
send_proposal_groups_for_approvalRequest publishers' approval
accept_proposal_group, reject_proposal_groupRespond as a group's publisher

Tools with a request payload take those fields in body; record-specific tools take id, and list tools take filters. They use the same workspace, publication, financial, and lifecycle checks as REST. See Sponsy MCP setup to connect a client.

Working safely with drafts

Store the proposal ID against your lead or opportunity so rerunning a job updates the intended record. Before retrying a timed-out create request, check whether the proposal was created. Do not assume every failed connection means nothing was saved.

Treat a proposal link as sensitive. Share it only with the intended sponsor and teammates.

Unknown fields, malformed UUIDs, invalid dates, and invalid item references are rejected. Expect 400 for invalid input or an incompatible proposal state, 401 for missing or invalid authentication, 403 for a permission or capability restriction, and 404 when the requested resource is unavailable to your workspace. A 409 means the proposal or approval changed during the operation; read it again before deciding whether to retry. See the reference for each operation's exact response.

For the full request schemas, response fields, validation rules, and errors, use the generated REST API v2 reference.

Search Sponsy documentation

Search docs pages and in-page sections