Skip to content

Managing Integrations

Overview

An integration is a configured connection between your tenant and an external provider. You supply credentials once, choose which capabilities to enable, and the platform handles verification, encryption, and routing from that point forward. Each provider can have at most one integration per tenant - if you need to swap credentials, update the existing record rather than creating a new one.

Provider credentials are encrypted at rest and never returned in plaintext through the API. Sensitive fields such as secret keys and auth tokens are always masked in responses, so you can safely log or display integration details without exposing credentials. Non-sensitive fields such as publishable keys and sender phone numbers remain visible to help you identify which account is configured.

Integration Lifecycle

StatusDescriptionHow to Transition
pending_verifyCredential check queued but not yet completeAutomatic - transitions after async verification
activeVerified, healthy, and eligible for routingAutomatic after successful verification; or POST /{id}/activate
inactiveManually disabled, excluded from routingPOST /{id}/disable; reverse with POST /{id}/activate
errorVerification failed or a runtime error was recordedUpdate credentials via PATCH /{id} to re-trigger verification

Routing and Status

Routing rules only select integrations in active status. An integration in pending_verify, inactive, or error will not receive operations even if a routing rule references it.

API Endpoints

List Available Providers

Returns all providers registered in the platform, including their supported capabilities, the credential fields required to configure them, and whether your tenant has already configured each one.

Endpoint: GET /api/v1/integrations/providers

Authentication: Required (Bearer token)

Response (200 OK):

json
{
  "success": true,
  "message": "Providers retrieved successfully",
  "data": [
    {
      "name": "stripe",
      "display_name": "Stripe",
      "category": "payment",
      "capabilities": ["initiate_payment", "process_refund", "verify_payment"],
      "credential_schema": {
        "publishable_key": { "type": "string", "sensitive": false, "required": true },
        "secret_key": { "type": "string", "sensitive": true, "required": true },
        "webhook_secret": { "type": "string", "sensitive": true, "required": false }
      },
      "is_configured": false
    },
    {
      "name": "twilio",
      "display_name": "Twilio",
      "category": "communication",
      "capabilities": ["send_sms", "send_whatsapp"],
      "credential_schema": {
        "account_sid": { "type": "string", "sensitive": false, "required": true },
        "auth_token": { "type": "string", "sensitive": true, "required": true },
        "from_number": { "type": "string", "sensitive": false, "required": true }
      },
      "is_configured": true
    }
  ],
  "meta": {}
}

Use credential_schema to build your configuration form. Fields marked sensitive: true are encrypted on the server and masked in subsequent API responses.


List Integrations

Returns all integrations configured for your tenant. Supports filtering and pagination.

Endpoint: GET /api/v1/integrations

Authentication: Required (Bearer token)

Query Parameters:

  • status (string) - Filter by status: pending_verify, active, inactive, error
  • category (string) - Filter by category: payment, communication
  • per_page (integer) - Results per page (default: 25, max: 100)
  • page (integer) - Page number

Example Request:

bash
GET /api/v1/integrations?status=active&category=payment&per_page=15

Response (200 OK):

json
{
  "success": true,
  "data": [
    {
      "id": "01hwxyz123abc456def789ghi0",
      "provider": "stripe",
      "display_name": "Stripe",
      "category": "payment",
      "status": "active",
      "enabled_capabilities": ["initiate_payment", "process_refund", "verify_payment"],
      "credentials": {
        "publishable_key": "pk_test_placeholder",
        "secret_key": null,
        "webhook_secret": null
      },
      "metadata": {},
      "verified_at": "2026-01-10T08:45:00Z",
      "created_at": "2026-01-10T08:30:00Z",
      "updated_at": "2026-01-10T08:45:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 15,
    "total": 3,
    "last_page": 1
  },
  "links": {
    "first": "/api/v1/integrations?page=1",
    "last": "/api/v1/integrations?page=1",
    "prev": null,
    "next": null
  }
}

Configure an Integration

Creates a new integration for the specified provider. Triggers async credential verification immediately - the integration will be in pending_verify status until verification completes.

Endpoint: POST /api/v1/integrations

Authentication: Required (Bearer token)

Request Body:

json
{
  "provider": "stripe",
  "credentials": {
    "publishable_key": "pk_test_placeholder",
    "secret_key": "sk_test_placeholder",
    "webhook_secret": "whsec_placeholder"
  },
  "enabled_capabilities": ["initiate_payment", "process_refund", "verify_payment"],
  "metadata": {
    "environment": "production",
    "account_label": "Primary Stripe Account"
  }
}

Required Fields:

  • provider - Provider name from GET /providers (e.g., stripe, twilio)
  • credentials - Object matching the provider's credential_schema
  • enabled_capabilities - Array of capability names to activate; must be a subset of the provider's supported capabilities

Optional Fields:

  • metadata - Arbitrary key-value object for your own reference (environment labels, account notes, etc.)

Response (201 Created):

json
{
  "success": true,
  "message": "Integration configured successfully",
  "data": {
    "id": "01hwxyz123abc456def789ghi0",
    "provider": "stripe",
    "display_name": "Stripe",
    "category": "payment",
    "status": "pending_verify",
    "enabled_capabilities": ["initiate_payment", "process_refund", "verify_payment"],
    "credentials": {
      "publishable_key": "pk_test_placeholder",
      "secret_key": null,
      "webhook_secret": null
    },
    "metadata": {
      "environment": "production",
      "account_label": "Primary Stripe Account"
    },
    "verified_at": null,
    "created_at": "2026-01-10T08:30:00Z",
    "updated_at": "2026-01-10T08:30:00Z"
  },
  "meta": {}
}

Error Response (422 Unprocessable Entity):

json
{
  "success": false,
  "message": "The given data was invalid.",
  "errors": {
    "provider": ["An integration for this provider already exists."]
  }
}

One Integration Per Provider

Only one integration per provider is allowed. If you need to change credentials, use PATCH /api/v1/integrations/{id} to update the existing record.


Get Integration Details

Returns full details for a single integration. Sensitive credential fields are always masked.

Endpoint: GET /api/v1/integrations/{id}

Authentication: Required (Bearer token)

Example Request:

bash
GET /api/v1/integrations/01hwxyz123abc456def789ghi0

Response (200 OK):

json
{
  "success": true,
  "data": {
    "id": "01hwxyz123abc456def789ghi0",
    "provider": "stripe",
    "display_name": "Stripe",
    "category": "payment",
    "status": "active",
    "enabled_capabilities": ["initiate_payment", "process_refund", "verify_payment"],
    "credentials": {
      "publishable_key": "pk_test_placeholder",
      "secret_key": null,
      "webhook_secret": null
    },
    "metadata": {
      "environment": "production",
      "account_label": "Primary Stripe Account"
    },
    "verified_at": "2026-01-10T08:45:00Z",
    "created_at": "2026-01-10T08:30:00Z",
    "updated_at": "2026-01-10T08:45:00Z"
  },
  "meta": {}
}

Update Integration

Updates the credentials, enabled capabilities, or metadata for an existing integration. If credentials are changed, the integration is reset to pending_verify and re-verified asynchronously.

Endpoint: PATCH /api/v1/integrations/{id}

Authentication: Required (Bearer token)

Request Body (partial update allowed):

json
{
  "credentials": {
    "publishable_key": "pk_test_placeholder_new",
    "secret_key": "sk_test_placeholder_new"
  },
  "enabled_capabilities": ["initiate_payment", "process_refund"],
  "metadata": {
    "environment": "production",
    "account_label": "Primary Stripe Account - rotated Jan 2026"
  }
}

Response (200 OK):

json
{
  "success": true,
  "message": "Integration updated successfully",
  "data": {
    "id": "01hwxyz123abc456def789ghi0",
    "provider": "stripe",
    "status": "pending_verify",
    "enabled_capabilities": ["initiate_payment", "process_refund"],
    "verified_at": null,
    "updated_at": "2026-02-01T09:00:00Z"
  },
  "meta": {}
}

Delete Integration

Soft-deletes an integration. Any routing rules that reference this integration will no longer select it. Deleted integrations do not appear in list responses.

Endpoint: DELETE /api/v1/integrations/{id}

Authentication: Required (Bearer token)

Response (200 OK):

json
{
  "success": true,
  "message": "Integration deleted successfully"
}

Deleting an Active Integration

Deleting an integration that is referenced by active routing rules will leave those rules without a valid target. Review and update your routing rules before deleting a provider integration.


Activate Integration

Re-enables an integration that is currently in inactive status. The integration transitions immediately to active without re-verifying credentials.

Endpoint: POST /api/v1/integrations/{id}/activate

Authentication: Required (Bearer token)

Response (200 OK):

json
{
  "success": true,
  "message": "Integration activated successfully",
  "data": {
    "id": "01hwxyz123abc456def789ghi0",
    "status": "active",
    "updated_at": "2026-02-15T10:30:00Z"
  },
  "meta": {}
}

Disable Integration

Manually disables an active integration. No new operations will be routed to it until it is re-activated. Existing in-flight delivery attempts continue to completion.

Endpoint: POST /api/v1/integrations/{id}/disable

Authentication: Required (Bearer token)

Response (200 OK):

json
{
  "success": true,
  "message": "Integration disabled successfully",
  "data": {
    "id": "01hwxyz123abc456def789ghi0",
    "status": "inactive",
    "updated_at": "2026-02-15T11:00:00Z"
  },
  "meta": {}
}

Business Scenarios

Scenario 1: Setting Up Stripe for the First Time

Context: Your tenant is onboarding and needs to accept payments through Stripe.

Workflow:

  1. List providers to confirm Stripe is available and not yet configured
  2. Create the integration with credentials from your Stripe dashboard
  3. Poll for active status before creating routing rules
  4. Create a routing rule targeting the Stripe integration

API Calls:

bash
# 1. Discover providers
GET /api/v1/integrations/providers

# 2. Configure integration
POST /api/v1/integrations
{
  "provider": "stripe",
  "credentials": {
    "publishable_key": "pk_test_placeholder",
    "secret_key": "sk_test_placeholder"
  },
  "enabled_capabilities": ["initiate_payment", "process_refund", "verify_payment"]
}

# 3. Poll for verification
GET /api/v1/integrations/01hwxyz123abc456def789ghi0

# 4. Once active, create routing rule
POST /api/v1/routing-rules
{
  "capability": "initiate_payment",
  "integration_id": "01hwxyz123abc456def789ghi0",
  "is_default": true,
  "priority": 100
}

Scenario 2: Rotating Credentials

Context: Your security team requires quarterly credential rotation for all payment integrations.

Workflow:

  1. Generate new credentials in your Stripe dashboard
  2. Update the integration - the system immediately queues re-verification
  3. Monitor status until active is confirmed
  4. Confirm routing rules are still referencing the same integration ID (they are - IDs do not change)

API Calls:

bash
# 1. Rotate credentials
PATCH /api/v1/integrations/01hwxyz123abc456def789ghi0
{
  "credentials": {
    "publishable_key": "pk_test_placeholder_new",
    "secret_key": "sk_test_placeholder_new"
  },
  "metadata": {
    "rotated_at": "2026-03-01",
    "account_label": "Stripe - rotated Q1 2026"
  }
}

# 2. Poll until active
GET /api/v1/integrations/01hwxyz123abc456def789ghi0

Scenario 3: Switching Communication Providers

Context: You want to move from Plivo to Twilio for SMS delivery.

Workflow:

  1. Configure Twilio integration
  2. Wait for Twilio to reach active status
  3. Update routing rules to point to Twilio instead of Plivo
  4. Disable the Plivo integration to prevent accidental routing

API Calls:

bash
# 1. Configure Twilio
POST /api/v1/integrations
{
  "provider": "twilio",
  "credentials": {
    "account_sid": "account_sid_placeholder",
    "auth_token": "auth_token_placeholder",
    "from_number": "+15550100000"
  },
  "enabled_capabilities": ["send_sms", "send_whatsapp"]
}

# 2. Update routing rule to Twilio (after it goes active)
PATCH /api/v1/routing-rules/01hwrule23abc456def789ghi0
{
  "integration_id": "01hwxyz456abc789def012ghi3"
}

# 3. Disable Plivo
POST /api/v1/integrations/01hwplivo23abc456def789g0/disable

Credential Security

Credentials are encrypted at rest using envelope encryption. The plaintext of any sensitive field - secret keys, auth tokens, webhook secrets - is never stored in the database and is never returned in API responses. Sensitive fields always appear as null in responses regardless of the request context.

Non-sensitive fields such as publishable keys and sender phone numbers are stored in plaintext because they are designed to be public-facing identifiers. These fields remain visible in API responses to help you confirm which account is configured without requiring access to your provider dashboard.

Credentials are never written to application logs. If a verification error occurs, the error description is stored in the integration's metadata field - not the credential values.

Never Share Full Request Bodies

When reporting issues or creating support tickets, do not include raw request bodies that contain credential values. Use the masked API response instead to show the configuration state.


Best Practices

1. Verify Status Before Routing

Always confirm an integration has reached active status before configuring routing rules or triggering operations. Routing evaluation skips non-active integrations, which can result in NoActiveProviderException errors if no other rule matches.

2. Use Metadata for Context

The metadata field is a free-form object attached to each integration. Use it to record when credentials were last rotated, which Stripe account or Twilio sub-account is in use, and what environment (staging vs. production) the credentials belong to. This context is invaluable during incident investigations.

3. Configure a Fallback on Routing Rules

When configuring routing rules, always specify a fallback_integration_id pointing to a secondary provider. If the primary integration becomes unavailable mid-operation, the fallback is used automatically without intervention. See the Routing Rules guide for configuration details.

4. Rotate Credentials Regularly

Establish a credential rotation schedule (quarterly is common) and use the PATCH endpoint to update credentials in place. Integration IDs never change during updates, so routing rules remain valid. Storing the rotation date in metadata makes compliance audits straightforward.


Troubleshooting

Verification Stuck in pending_verify

Symptom: Integration remains in pending_verify for more than a few minutes.

Possible Causes:

  • The async verification job is queued behind other work
  • The verification job encountered a transient network error and will retry

Resolution:

  1. Wait up to five minutes for the job to complete
  2. Check GET /api/v1/integrations/{id} - if status is still pending_verify, look at metadata for any error details
  3. If metadata contains an error, update the credentials to re-queue verification: PATCH /api/v1/integrations/{id}

Credentials Rejected During Verification

Symptom: Integration transitions to error status shortly after configuration.

Possible Causes:

  • Credentials were copied incorrectly (extra whitespace, truncation)
  • The wrong credential type was used (test key in production or vice versa)
  • The provider account does not have the required permissions for all enabled capabilities

Resolution:

  1. Retrieve the integration: GET /api/v1/integrations/{id} and check metadata for the error message
  2. Correct the credentials in your provider dashboard
  3. Update the integration with the corrected credentials:
bash
PATCH /api/v1/integrations/01hwxyz123abc456def789ghi0
{
  "credentials": {
    "secret_key": "sk_test_corrected_placeholder"
  }
}

Integration in Error State After Being Active

Symptom: An integration that was previously active has moved to error status.

Possible Causes:

  • The provider account was suspended or credentials were revoked externally
  • A key expired or was rotated in the provider dashboard without updating the integration
  • The provider returned an authentication failure during a live operation

Resolution:

  1. Log in to your provider dashboard and confirm the account is in good standing
  2. Generate new credentials if the existing ones were revoked
  3. Update the integration via PATCH /api/v1/integrations/{id} to re-trigger verification
  4. Review recent delivery attempts for this integration in the Delivery Tracking section for additional context

Documentation for SynthesQ CRM/ERP Platform