integrations

Connected apps, OAuth tokens, webhooks, and sync logs

Integrations

Connected apps, OAuth tokens, webhooks, and sync logs. Manages third-party connections, credential storage, outgoing webhook delivery, and data synchronization tracking.

Tables

connected_apps

ColumnTypeDescription
iduuidPrimary key, auto-generated
org_iduuidReferences organizations(id), cascade delete
nametextDisplay name of the connected app
providertextProvider identifier (slack, hubspot, stripe, etc.)
statusintegration_statusConnection health status, defaults to active
configjsonbProvider-specific configuration
connected_byuuidReferences users(id), set null on delete
connected_attimestamptzWhen the connection was established
created_attimestamptzRow creation timestamp
updated_attimestamptzAuto-updated on modification
metadatajsonbArbitrary key-value data

oauth_tokens

ColumnTypeDescription
iduuidPrimary key, auto-generated
org_iduuidReferences organizations(id), cascade delete
app_iduuidReferences connected_apps(id), cascade delete
user_iduuidReferences users(id), cascade delete
access_token_enctextEncrypted access token
refresh_token_enctextEncrypted refresh token (optional)
token_typetextToken type, defaults to bearer
scopestext[]Granted OAuth scopes
expires_attimestamptzToken expiration time
created_attimestamptzRow creation timestamp
updated_attimestamptzAuto-updated on modification
metadatajsonbArbitrary key-value data

webhooks

ColumnTypeDescription
iduuidPrimary key, auto-generated
org_iduuidReferences organizations(id), cascade delete
urltextDestination URL for webhook delivery
secrettextSigning secret for payload verification
eventstext[]Event types this webhook subscribes to
is_activebooleanWhether the webhook is enabled, defaults to true
created_byuuidReferences users(id), set null on delete
created_attimestamptzRow creation timestamp
updated_attimestamptzAuto-updated on modification
metadatajsonbArbitrary key-value data

webhook_events

ColumnTypeDescription
iduuidPrimary key, auto-generated
org_iduuidReferences organizations(id), cascade delete
webhook_iduuidReferences webhooks(id), cascade delete
event_typetextThe type of event that triggered delivery
payloadjsonbEvent payload sent to the endpoint
statuswebhook_event_statusDelivery status, defaults to pending
response_codesmallintHTTP response code from the endpoint
attemptsintegerNumber of delivery attempts, defaults to 0
last_attempt_attimestamptzTimestamp of the most recent attempt
created_attimestamptzRow creation timestamp
updated_attimestamptzAuto-updated on modification
metadatajsonbArbitrary key-value data

sync_logs

ColumnTypeDescription
iduuidPrimary key, auto-generated
org_iduuidReferences organizations(id), cascade delete
app_iduuidReferences connected_apps(id), cascade delete
directionsync_directionWhether the sync is inbound or outbound
entity_typetextType of entity being synced (contacts, deals, etc.)
entity_iduuidOptional specific entity being synced
statussync_statusCurrent sync status, defaults to pending
records_processedintegerNumber of records handled, defaults to 0
records_failedintegerNumber of records that failed, defaults to 0
started_attimestamptzWhen the sync run began
completed_attimestamptzWhen the sync run finished
errortextError details if the sync failed
created_attimestamptzRow creation timestamp
updated_attimestamptzAuto-updated on modification
metadatajsonbArbitrary key-value data

Enums

integration_status

ValueDescription
activeConnection is healthy and operational
inactiveConnection is disabled
errorConnection has a problem that needs attention

webhook_event_status

ValueDescription
pendingEvent is queued for delivery
sentEvent was delivered successfully
failedDelivery failed after all retry attempts

sync_direction

ValueDescription
inboundData flowing from the external app into the platform
outboundData flowing from the platform to the external app

sync_status

ValueDescription
pendingSync is queued but has not started
runningSync is currently executing
completedSync finished successfully
failedSync finished with an error

Row-Level Security

All five tables are scoped to the current user's organization via get_user_org_id(). Select, insert, and update are allowed for any org member. Delete requires the is_admin() check.

Dependencies

  • identity -- organizations and users tables, get_user_org_id() and is_admin() functions, set_updated_at() trigger function

Example Queries

List all active connected apps for the current org:

SELECT id, name, provider, status, connected_at
FROM connected_apps
WHERE status = 'active'
ORDER BY connected_at DESC;

Webhook delivery status summary (last 30 days):

SELECT
  w.url,
  count(we.id) AS total_events,
  count(we.id) FILTER (WHERE we.status = 'sent') AS delivered,
  count(we.id) FILTER (WHERE we.status = 'failed') AS failed,
  count(we.id) FILTER (WHERE we.status = 'pending') AS pending
FROM webhooks w
LEFT JOIN webhook_events we ON we.webhook_id = w.id
  AND we.created_at >= now() - interval '30 days'
WHERE w.is_active = true
GROUP BY w.id, w.url
ORDER BY w.url;

Sync history for a specific app:

SELECT
  sl.direction,
  sl.entity_type,
  sl.status,
  sl.records_processed,
  sl.records_failed,
  sl.started_at,
  sl.completed_at,
  sl.error
FROM sync_logs sl
WHERE sl.app_id = '<app_id>'
ORDER BY sl.started_at DESC
LIMIT 20;

Failed syncs in the last 7 days:

SELECT
  ca.name AS app_name,
  sl.direction,
  sl.entity_type,
  sl.error,
  sl.started_at
FROM sync_logs sl
JOIN connected_apps ca ON ca.id = sl.app_id
WHERE sl.status = 'failed'
  AND sl.started_at >= now() - interval '7 days'
ORDER BY sl.started_at DESC;

Active integrations with token expiration status:

SELECT
  ca.name AS app_name,
  ca.provider,
  ot.user_id,
  ot.scopes,
  ot.expires_at,
  CASE
    WHEN ot.expires_at < now() THEN 'expired'
    WHEN ot.expires_at < now() + interval '7 days' THEN 'expiring_soon'
    ELSE 'valid'
  END AS token_status
FROM connected_apps ca
JOIN oauth_tokens ot ON ot.app_id = ca.id
WHERE ca.status = 'active'
ORDER BY ot.expires_at ASC;

Failed webhook events awaiting retry:

SELECT
  w.url,
  we.event_type,
  we.attempts,
  we.response_code,
  we.last_attempt_at,
  we.payload
FROM webhook_events we
JOIN webhooks w ON w.id = we.webhook_id
WHERE we.status = 'failed'
ORDER BY we.last_attempt_at DESC;