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:crm
  • write:crm
  • read:pipeline
  • write:pipeline
  • read:projects
  • read:invoices
  • read:tasks
  • write:tasks
  • read:time
  • read:permits
  • read:subscribers
  • write: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.

MethodPathScopeDescription
GET/crm/organizationsread:crmList organizations.
GET/crm/organizations/:idread:crmGet one organization by id.
GET/crm/contactsread:crmList contacts.
GET/crm/contacts/:idread:crmGet one contact by id.
GET/crm/leadsread:crmList leads.
GET/crm/leads/:idread:crmGet one lead by id.
POST/crm/leadswrite:crmCreate a lead.
GET/pipeline/opportunitiesread:pipelineList deals (opportunities).
GET/pipeline/opportunities/:idread:pipelineGet one deal by id.
POST/pipeline/opportunitieswrite:pipelineCreate a deal.
GET/projectsread:projectsList projects.
GET/projects/:idread:projectsGet one project by id.
GET/invoicing/invoicesread:invoicesList invoices.
GET/invoicing/invoices/:idread:invoicesGet one invoice by id.
GET/tasksread:tasksList tasks.
POST/taskswrite:tasksCreate a task.
GET/time-entriesread:timeList time entries.
GET/permitsread:permitsList permits.
GET/permits/:idread:permitsGet one permit by id.
GET/marketing/subscribersread:subscribersList marketing subscribers.
POST/marketing/subscriberswrite:subscribersAdd 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

EventWhen it fires
invoice_sentAfter an invoice flips from draft to sent.
invoice_paidAfter an invoice is fully paid (status flips to paid).
payment_receivedAfter a payment is recorded against an invoice.
lead_createdAfter a new lead is persisted (CRM, intake bot, Zapier).
lead_scoredAfter the AI lead-score worker writes back a tier + score.
opportunity_wonWhen a deal is moved into a closed-won stage.
project_completedWhen a project advances to its final delivered stage.
permit_approvedWhen 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-created every few minutes and starts your Zap for each new lead.
  • Action: Create Lead — Zapier POSTs to /zapier/actions/create-lead from a flat input (Typeform, Wix form, Webflow, …).
  • Action: Add Subscriber — same idea but routes a newsletter signup into the marketing list.

Building a Zap

  1. Generate an API key at /app/settings/api-keys with the scopes you need (typically read:crm + write:crm + write:subscribers).
  2. In Zapier, install the Archipartnersdesign app. Paste the key in the auth step. Zapier hits /zapier/auth/test and shows your tenant name on success.
  3. 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.

Questions? Email your account owner. Documentation last updated: Wave 17 (Public API surface).
Archipartnersdesign API | Archipartnersdesign