Integrations
Configure third-party integrations — RevenueCat, Superwall, APNs, FCM — with credentials validation.
Integrations live on the control-plane project_integrations table. Configuration is JSONB; the shape depends on the provider (revenuecat, superwall, apns, fcm). APNs and FCM credentials are additionally fetched from GCP Secret Manager when POST /:provider/test is called.
Source: apps/api/src/routes/admin/integrations.ts.
Endpoints
| Method | Path | Description |
|---|---|---|
| POST | /admin/projects/:projectId/integrations | Create / upsert an integration. |
| GET | /admin/projects/:projectId/integrations | List integrations (metadata only — config redacted). |
| PATCH | /admin/projects/:projectId/integrations/:provider | Partial update. |
| POST | /admin/projects/:projectId/integrations/:provider/test | Validate credentials. |
POST /admin/projects/:projectId/integrations
Upsert by (project_id, provider) — existing integration is replaced.
Request
| Field | Type | Required | Description |
|---|---|---|---|
provider | "revenuecat" | "superwall" | "apns" | "fcm" | yes | |
config | object | yes | Provider-specific config (e.g. webhook_secret, team_id, key_id, service_account_json). |
Response 201
webhook_url is only included for providers that expose an inbound webhook (revenuecat, superwall).
Try it:
/admin/projects/%7B%7BprojectId%7D%7D/integrationscurl -X POST 'https://api.amba.dev/admin/projects/%7B%7BprojectId%7D%7D/integrations'Curl:
GET /admin/projects/:projectId/integrations
Returns integration metadata (no config — credentials stay server-side).
Response 200
Try it:
/admin/projects/%7B%7BprojectId%7D%7D/integrationscurl -X GET 'https://api.amba.dev/admin/projects/%7B%7BprojectId%7D%7D/integrations'Curl:
PATCH /admin/projects/:projectId/integrations/:provider
Allowed fields: config, is_active.
Errors
404 NOT_FOUND.
Try it:
/admin/projects/%7B%7BprojectId%7D%7D/integrations/%7B%7Bprovider%7D%7Dcurl -X PATCH 'https://api.amba.dev/admin/projects/%7B%7BprojectId%7D%7D/integrations/%7B%7Bprovider%7D%7D'Curl:
POST /admin/projects/:projectId/integrations/:provider/test
Validate credentials against the provider. All four providers now make a real outbound call — there is no stub path.
apns/fcm— loads credentials (Secret Manager + DB), then calls the provider with a deliberately-invalid token. A 4xx "bad token" response proves the creds are valid; a 401/403 indicates bad creds. Response shape comes fromPushSendResult(valid,errorCode,errorMessage).revenuecat— performs an authenticatedGET https://api.revenuecat.com/v1/subscribers/<probe>against the secret REST key stored inconfig.secret_api_key(falls back toconfig.api_keyfor older integrations).superwall— performs an authenticatedGET https://api.superwall.com/v1/events?limit=1againstconfig.api_key.
For RevenueCat / Superwall, the response status is classified into one of three buckets:
classification | Meaning | Trigger |
|---|---|---|
ok | Credentials accepted. | HTTP 200 or 404 from the provider. |
creds_invalid | Credentials rejected, or the configured key is blank. | HTTP 401 / 403, or a missing/empty key. |
provider_unreachable | Couldn't get a definitive answer. | Network error, DNS failure, 10s timeout, 5xx, or any other unexpected status. |
The outbound call is wrapped in a 10-second AbortSignal.timeout so admin requests never wedge on a slow provider. Each test run is logged at info level with provider, projectId, classification, and (when available) providerStatus.
Response 200 — push providers
Response 200 — revenuecat / superwall
Errors
400 UNSUPPORTED_PROVIDER— provider is outside the schema-allowed set.404 NOT_FOUND— integration not configured or inactive.502 CREDENTIAL_LOAD_FAILED— Secret Manager or credential parsing failed (push providers only).error.detailsincludesproviderandreason.500 TEST_FAILED.
Try it:
/admin/projects/%7B%7BprojectId%7D%7D/integrations/%7B%7Bprovider%7D%7D/testcurl -X POST 'https://api.amba.dev/admin/projects/%7B%7BprojectId%7D%7D/integrations/%7B%7Bprovider%7D%7D/test'Curl: