Developer Reference
Archipartnersdesign API
Read CRM, pipeline, projects, invoices, tasks, and marketing data from the Archipartnersdesign platform — and push leads or subscribers in from external sources. Auth uses long-lived API keys generated by the tenant owner.
Base URL: https://app.archipartnersdesign.com/api/v1
API keys
1. Authentication
Every request must include an Authorization header carrying a long-lived API key:
Authorization: Bearer apd_X9cR4mP1tHvnLWKf3JaEyDqUbN8wC0Z2
Keys are minted from the owner-only settings page: /app/settings/api-keys. The plaintext key is shown ONCE on creation — store it in a secrets manager (1Password, AWS Secrets Manager, etc.) immediately. Subsequent listings only show the prefix (e.g. apd_X9cR…).
Each key is scoped to a single tenant and to a list of explicit scope strings. A key with no scopes has NO API access — owners who need broad access pick all scopes when generating.
Available scopes
read:crmwrite:crmread:pipelinewrite:pipelineread:projectsread:invoicesread:taskswrite:tasksread:timeread:permitsread:subscriberswrite:subscribers
Revoke a key at any time from the same settings page — revocation is immediate (no token-lifetime delay).
REST
2. Endpoint reference
Every endpoint below accepts either a JWT (existing user session) or an API key with the listed scope. JWT users are gated by their tenant role; API-key callers are gated by scope.
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /crm/organizations | read:crm | List organizations. |
| GET | /crm/organizations/:id | read:crm | Get one organization by id. |
| GET | /crm/contacts | read:crm | List contacts. |
| GET | /crm/contacts/:id | read:crm | Get one contact by id. |
| GET | /crm/leads | read:crm | List leads. |
| GET | /crm/leads/:id | read:crm | Get one lead by id. |
| POST | /crm/leads | write:crm | Create a lead. |
| GET | /pipeline/opportunities | read:pipeline | List deals (opportunities). |
| GET | /pipeline/opportunities/:id | read:pipeline | Get one deal by id. |
| POST | /pipeline/opportunities | write:pipeline | Create a deal. |
| GET | /projects | read:projects | List projects. |
| GET | /projects/:id | read:projects | Get one project by id. |
| GET | /invoicing/invoices | read:invoices | List invoices. |
| GET | /invoicing/invoices/:id | read:invoices | Get one invoice by id. |
| GET | /tasks | read:tasks | List tasks. |
| POST | /tasks | write:tasks | Create a task. |
| GET | /time-entries | read:time | List time entries. |
| GET | /permits | read:permits | List permits. |
| GET | /permits/:id | read:permits | Get one permit by id. |
| GET | /marketing/subscribers | read:subscribers | List marketing subscribers. |
| POST | /marketing/subscribers | write:subscribers | Add a marketing subscriber. |
Sample request — list leads
curl https://app.archipartnersdesign.com/api/v1/crm/leads \ -H "Authorization: Bearer apd_X9cR4mP1tHvnLWKf3JaEyDqUbN8wC0Z2"
Sample response
{
"data": [
{
"id": "ck5a2b3c4d5e6f7g8h9i0j",
"title": "Restaurant remodel — 2,400 sqft",
"status": "new",
"source": "website",
"estimatedValue": 18000,
"estimatedSqFt": 2400,
"projectType": "commercial",
"createdAt": "2026-05-05T14:00:00.000Z",
"contact": { "id": "...", "fullName": "Jane Doe", "email": "jane@example.com" },
"organization": null,
"assignedTo": null
}
],
"total": 1,
"page": 1,
"limit": 25,
"totalPages": 1
}Sample request — create a lead
curl -X POST https://app.archipartnersdesign.com/api/v1/crm/leads \
-H "Authorization: Bearer apd_X9cR4mP1tHvnLWKf3JaEyDqUbN8wC0Z2" \
-H "Content-Type: application/json" \
-d '{
"title": "External form: Jane Doe",
"email": "jane@example.com",
"phone": "+15205551234",
"source": "website",
"estimatedValue": 18000
}'Outbound
3. Webhooks
The platform fires HTTPS webhooks on 8 business events. Subscribe at /app/settings/webhooks — owner picks the events, gets a signing secret, paste both into your endpoint.
Event types
| Event | When it fires |
|---|---|
invoice_sent | After an invoice flips from draft to sent. |
invoice_paid | After an invoice is fully paid (status flips to paid). |
payment_received | After a payment is recorded against an invoice. |
lead_created | After a new lead is persisted (CRM, intake bot, Zapier). |
lead_scored | After the AI lead-score worker writes back a tier + score. |
opportunity_won | When a deal is moved into a closed-won stage. |
project_completed | When a project advances to its final delivered stage. |
permit_approved | When a permit transitions to approved. |
Sample payload
POST https://your-endpoint.example.com/webhook
Content-Type: application/json
X-APD-Event: lead_created
X-APD-Signature: sha256=4e2b1d…
X-APD-Timestamp: 1746460800
X-APD-Webhook-Id: ck5a2b3c4d5e6f7g8h9i0j
{
"event": "lead_created",
"tenantId": "ck_tenant_123",
"data": {
"leadId": "ck5a2b3c…",
"title": "Restaurant remodel — 2,400 sqft",
"status": "new",
"source": "website",
"estimatedValue": 18000,
"createdAt": "2026-05-05T14:00:00.000Z"
}
}Verify the signature
Compute HMAC-SHA256 over <timestamp>.<raw body> using your signing secret and compare against the value in the X-APD-Signature header. Reject if mismatched or if the timestamp is more than 5 minutes old (replay protection).
// Node.js
import crypto from 'crypto';
function verifyWebhook(req, signingSecret) {
const sig = req.headers['x-apd-signature'] || '';
const ts = req.headers['x-apd-timestamp'] || '';
const rawBody = req.rawBody; // string or Buffer
// 1. Replay protection — within 5 minutes
const skewSec = Math.abs(Date.now() / 1000 - Number(ts));
if (skewSec > 300) throw new Error('stale webhook');
// 2. Recompute HMAC
const payload = ts + '.' + rawBody;
const expected =
'sha256=' +
crypto.createHmac('sha256', signingSecret).update(payload).digest('hex');
// 3. Constant-time compare
const a = Buffer.from(sig);
const b = Buffer.from(expected);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
throw new Error('bad signature');
}
}Failed deliveries are retried with exponential backoff (1m, 5m, 15m, 1h, 6h, 24h). After 10 consecutive failures the webhook is auto-deactivated and the owner gets an in-app notification — re-enable from the settings page once the endpoint is fixed.
Integration
4. Zapier connector
The platform exposes a small Zapier-friendly surface under /zapier/*. Use it to wire APD into Zapier Zaps:
- Trigger: New Lead — Zapier polls
/zapier/triggers/lead-createdevery few minutes and starts your Zap for each new lead. - Action: Create Lead — Zapier
POSTs to/zapier/actions/create-leadfrom a flat input (Typeform, Wix form, Webflow, …). - Action: Add Subscriber — same idea but routes a newsletter signup into the marketing list.
Building a Zap
- Generate an API key at
/app/settings/api-keyswith the scopes you need (typicallyread:crm+write:crm+write:subscribers). - In Zapier, install the Archipartnersdesign app. Paste the key in the auth step. Zapier hits
/zapier/auth/testand shows your tenant name on success. - Add a trigger or action. Map the input fields and turn the Zap on.
Manifest
Static manifest describing every trigger / action / sample payload: GET /api/v1/zapier/manifest.json. Public, no auth.
Quotas
5. Rate limits
Default limit: 100 requests per minute per tenant across all API key callers combined. Hitting the limit returns 429 Too Many Requests with a Retry-After header in seconds.
For higher volumes (bulk import, large reporting workloads), request a quota increase from your account owner.