Build proposals in HubSpot, sync everything back automatically
Add these secrets to your Cloudflare Pages deployment
Run the following in your project directory, or set them in the Cloudflare Pages dashboard under Settings → Environment Variables:
npx wrangler secret put ANCHOR_API_KEY
npx wrangler secret put HUBSPOT_ACCESS_TOKEN
npx wrangler secret put ANCHOR_WEBHOOK_SECRET
npx wrangler secret put HUBSPOT_APP_ID
npx wrangler secret put HUBSPOT_CLIENT_SECRET
# For local dev, add to .dev.vars:
ANCHOR_API_KEY=your_anchor_api_key
HUBSPOT_ACCESS_TOKEN=your_hubspot_private_app_token
ANCHOR_WEBHOOK_SECRET=your_webhook_secret
HUBSPOT_APP_ID=your_app_id
HUBSPOT_CLIENT_SECRET=your_client_secret
Get Anchor API Key
Get HubSpot Token
crm.objects.deals.read/write, crm.objects.contacts.read/write, crm.schemas.deals.write, crm.objects.notes.writeAuto-creates 10 Anchor properties on your HubSpot Deal object
Click the button below to automatically create all required HubSpot custom properties. This only needs to be done once.
Anchor will POST events to your app in real-time
In your Anchor dashboard, go to Settings → Integrations → Webhooks and create a webhook with the following URL:
Required Events to Subscribe:
Embed the Anchor proposal builder inside HubSpot deal records
In your HubSpot developer account, create a Legacy CRM Card with the following settings:
Data Fetch URL:
https://your-app.pages.dev/crm-card
Target Record Types:
✅ Deals (send: dealname, amount, closedate)
✅ Contacts (send: email, firstname, lastname, company)
Card Properties:
- anchor_proposal_status (Status)
- anchor_proposal_url (Link)
- anchor_total_amount (Currency)
- anchor_monthly_recurring (Currency)
Primary Action:
IFRAME → https://your-app.pages.dev/card-ui?mode=create
Label: + New Anchor Proposal
Custom Action URLs:
https://your-app.pages.dev/*
KV stores proposal ↔ deal mappings for fast lookups
# Create KV namespace
npx wrangler kv:namespace create "anchor_hubspot_kv"
# Copy the output ID into wrangler.jsonc:
"kv_namespaces": [
{
"binding": "KV",
"id": "<your-kv-id>"
}
]
# Also create a preview namespace for local dev:
npx wrangler kv:namespace create "anchor_hubspot_kv" --preview
Webhook Endpoint
CRM Card Endpoint
API Endpoint
These 10 properties are created on your Deals object. Use them in workflows, reports, and dashboards.
| Property Name | Label | Type | Use Case |
|---|---|---|---|
| anchor_proposal_id | Anchor Proposal ID | string | Link deals to Anchor proposals |
| anchor_proposal_status | Anchor Proposal Status | enumeration | Workflow triggers, pipeline views |
| anchor_proposal_url | Anchor Proposal URL | string | Quick link to view proposal |
| anchor_proposal_title | Anchor Proposal Title | string | Deal card display |
| anchor_total_amount | Anchor Total Amount | number | Revenue reporting, forecasting |
| anchor_monthly_recurring | Anchor MRR | number | MRR dashboards |
| anchor_currency | Anchor Currency | string | Multi-currency reporting |
| anchor_sent_at | Anchor Proposal Sent At | datetime | Time-to-send analytics |
| anchor_signed_at | Anchor Proposal Signed At | datetime | Close date tracking |
| anchor_client_id | Anchor Client ID | string | Cross-reference with Anchor |
🔔 Notify closer when proposal is viewed
Trigger: anchor_proposal_status = "viewed"
Action: Send Slack/email notification to deal owner
🎉 Move deal to Closed Won on signature
Trigger: anchor_proposal_status = "approved"
Action: Move deal stage + trigger onboarding sequence
⏰ Follow up on sent-but-not-viewed proposals
Trigger: anchor_sent_at is known + status = "sent" + 48h delay
Action: Create task for deal owner to follow up
📊 MRR forecasting reports
Dashboard: Sum of anchor_monthly_recurring across deals by stage
Filter: status = "approved" for actual MRR
Endpoints exposed by this integration
/webhook/anchor
Receives Anchor webhook events (proposal.sent, approved, etc.) and syncs to HubSpot.
/crm-card?associatedObjectId=<dealId>
HubSpot CRM Card data endpoint. Returns proposal info for a deal's sidebar card.
/api/proposals
Create a new Anchor proposal and link it to a HubSpot deal. Body: { dealId, title, client, services, autoSend }
/api/proposals/:id
Fetch a single Anchor proposal (with KV-cached fallback).
/api/proposals/:id/send
Send a draft Anchor proposal to the client and update HubSpot.
/api/sync/:proposalId
Force-sync a proposal's current state from Anchor into HubSpot.
/api/mapping/:proposalId
Return the KV mapping record linking an Anchor proposal to a HubSpot deal.
/api/setup/properties
Bootstrap all 10 Anchor custom properties on the HubSpot Deals object.