Integrations

PitchPrfct

First-party SMS/CRM integration connected via API key — powers the dialer SMS tab and lands as the first entry in Project88's typed provider registry.

PitchPrfct is the first integration to land on Project88's typed provider registry — a folder-per-provider layout under src/integrations/ that drives a new Project 88 tab in the Connections settings modal, alongside the existing Integrations (Composio-managed) and Tools tabs.

The PitchPrfct entry covers all 46 endpoints across 8 resource groups through a single allowlisted path-passthrough edge function (pitchprfct-api), and it powers the dial widget's SMS tab.

Connect

  1. ⌘KSettings → Connections → Project 88 tab.
  2. Click Connect on the PitchPrfct card. The generic ApiKeyConnectModal opens — it matches the project's condensed ConfirmDialog styling and runs a per-provider validate() hook before persisting.
  3. Paste your PitchPrfct API key and submit. The key transits the pitchprfct-api edge function exactly once (with a validateKey envelope) to confirm it's live, then lands in Supabase Vault via the discriminator-shaped insert_integration_api_key RPC. The key never reaches the browser again after connect.

You'll see PitchPrfct in the Project 88 tab with a "Connected" status.

Where the credential lives

StoredNotes
Supabase Vault, via insert_integration_api_key (migration 126)Payload is the self-describing discriminator { type: 'api_key', key, provider } — distinct from the OAuth-shaped payload used by Gmail / Outlook / Google Calendar
RPC permissions (migration 127)REVOKE EXECUTE FROM anon; GRANT EXECUTE TO authenticated. Clears Supabase advisor lint 0028
Edge function in-memory cacheMap<userId, key> with a 5-min TTL, scoped per warm instance

The proxy never echoes the key back to the browser, and only allowlisted PitchPrfct paths can be reached through it.

Edge function: allowlisted path-passthrough

supabase/functions/pitchprfct-api is a single proxy with verify_jwt: true. One regex covers all 46 endpoints across the 8 resource groups, and a 26-scenario Deno suite asserts the allowlist plus a leak canary (the key must never appear in the response body or in proxied error envelopes).

The browser-side typed client (src/integrations/pitchprfct/client.js) is a hand-rolled JSDoc-typed JS wrapper (no TS in this codebase) with a generic pollJob() helper for the bulk endpoints.

Drift guard

A nightly contract test under .github/workflows/contract-tests.yml runs three live checks against PitchPrfct using the PITCHPRFCT_TEST_API_KEY GitHub secret. If PitchPrfct ships a breaking change, the workflow fails before the next user opens the dial widget.

Known upstream quirk

PitchPrfct's conversations.list({contactUuid}) endpoint returns HTTP 500 for valid UUIDs. The dialer SMS tab works around it by skipping the conversations endpoint and calling messages.list({contactUuid}) directly — a comment at the call site flags the workaround so it can be unwound once upstream fixes the bug.

Sending: fromNumber requirement

PitchPrfct exposes no API to enumerate sending numbers, so outbound sends read from localStorage['dial.sms.pitchprfct.fromNumber']. If the value is missing, the message bubble flips to failed with a clear configuration error rather than dropping silently. A first-party settings UI for the from-number is a follow-up.

Adding another Project 88 integration

The registry layout is intentionally copy-paste-able. To wire a new first-party provider:

  1. Duplicate src/integrations/pitchprfct/ to src/integrations/<new-provider>/.
  2. Swap the provider definition in index.js (display name, icon, validate() hook, base URL).
  3. Update the typed client wrapper and its tests.
  4. Add the new provider to src/integrations/registry.js.

The same vault path, RPC, modal, and Project 88 tab pick it up automatically.

Webhooks

Inbound PitchPrfct webhooks are deferred — v1 ships on-demand only. The dial widget polls every 5 seconds for new inbound SMS while the conversation is open (paused during an in-flight optimistic send so the poll can't clobber it); nothing pushes into Project 88 yet. A webhook lane will land when user behavior calls for it — at which point the poll drops out.

Where to next

On this page