Connections API
Manage OAuth and API key connections for integrations
Connections API
Manage OAuth connections to external services. Connections are used by workflows to authenticate with integrated providers like Stripe, Salesforce, HubSpot, and more.
List Connections
Retrieve all connections for your company.
GET /api/v1/connectionsQuery Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
provider | string | - | Filter by provider: stripe, salesforce, hubspot, etc. |
status | string | - | Filter: active, pending, error, expired, disconnected |
limit | number | 50 | Number of results (1-100) |
Response
{
"success": true,
"data": [
{
"id": "conn_550e8400-e29b-41d4-a716-446655440000",
"name": "Stripe Production",
"provider": "stripe",
"status": "active",
"externalAccountId": "acct_xxx",
"lastSyncedAt": "2024-01-15T10:30:00.000Z",
"createdAt": "2024-01-01T10:00:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
},
{
"id": "conn_660e8400-e29b-41d4-a716-446655440001",
"name": "HubSpot CRM",
"provider": "hubspot",
"status": "active",
"externalAccountId": "123456",
"lastSyncedAt": "2024-01-15T09:00:00.000Z",
"createdAt": "2024-01-05T10:00:00.000Z",
"updatedAt": "2024-01-15T09:00:00.000Z"
}
],
"meta": {
"hasMore": false
}
}Example
curl -X GET "http://localhost:3000/api/v1/connections?provider=stripe" \
-H "x-api-key: YOUR_API_KEY"const response = await fetch(
'http://localhost:3000/api/v1/connections?provider=stripe',
{
headers: { 'x-api-key': process.env.API_KEY }
}
);
const { data } = await response.json();import requests
response = requests.get(
'http://localhost:3000/api/v1/connections',
params={'provider': 'stripe'},
headers={'x-api-key': api_key}
)
data = response.json()Get Auth URL
Generate an OAuth authorization URL for a provider. This creates a pending connection and returns the URL to redirect the user to.
GET /api/v1/connections/:provider/auth-urlPath Parameters
| Parameter | Type | Description |
|---|---|---|
provider | string | Provider name: stripe, salesforce, hubspot, quickbooks, pandadoc, netsuite, slack, gmail |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
redirectUrl | string | No | URL to redirect after OAuth completion |
connectionName | string | No | Custom name for the connection |
Response
{
"success": true,
"data": {
"connectionId": "conn_550e8400-e29b-41d4-a716-446655440000",
"provider": "stripe",
"authUrl": "https://connect.stripe.com/oauth/authorize?client_id=xxx&redirect_uri=xxx&state=xxx",
"isNew": true,
"message": "Redirect user to authUrl to complete OAuth authorization"
}
}Example
curl -X GET "http://localhost:3000/api/v1/connections/stripe/auth-url?redirectUrl=https://app.example.com/settings/connections" \
-H "x-api-key: YOUR_API_KEY"Re-authorization
If a connection already exists but is in error or disconnected status, calling this endpoint will return a new auth URL for re-authorization:
{
"success": true,
"data": {
"connectionId": "conn_existing",
"provider": "stripe",
"authUrl": "https://connect.stripe.com/oauth/authorize?...",
"isNew": false,
"message": "Redirect user to authUrl to complete OAuth authorization"
}
}Error Response (Active Connection Exists)
{
"success": false,
"error": {
"code": "BAD_REQUEST",
"message": "Active connection already exists for stripe. Disconnect first to re-authorize."
}
}OAuth Callback
Handle the OAuth callback from the provider. This endpoint is called by Nango after the user completes authorization.
GET /api/v1/connections/:provider/callbackThis endpoint does not require authentication as it handles redirects from the OAuth provider.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
connectionId | string | The connection ID from the auth flow |
success | string | "true" or "false" |
error | string | Error message if authorization failed |
redirectUrl | string | URL to redirect the user to |
Successful Authorization
If redirectUrl is provided, redirects to:
https://app.example.com/settings/connections?success=true&connectionId=xxx&provider=stripeOtherwise returns:
{
"success": true,
"data": {
"connectionId": "conn_xxx",
"provider": "stripe",
"status": "active",
"message": "OAuth authorization completed successfully"
}
}Failed Authorization
If redirectUrl is provided, redirects to:
https://app.example.com/settings/connections?error=access_denied&connectionId=xxxCreate Connection
Initiate a new connection (starts OAuth flow).
POST /api/v1/connectionsRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name for the connection |
provider | string | Yes | Provider name |
metadata | object | No | Additional metadata |
Example Request
{
"name": "Production Stripe",
"provider": "stripe",
"metadata": {
"environment": "production"
}
}Response (201 Created)
{
"success": true,
"data": {
"id": "conn_550e8400-e29b-41d4-a716-446655440000",
"name": "Production Stripe",
"provider": "stripe",
"status": "pending",
"oauthUrl": "https://api.nango.dev/oauth/connect/stripe?connection_id=xxx&public_key=xxx",
"message": "Redirect user to oauthUrl to complete connection"
}
}Get Connection
Retrieve details of a specific connection.
GET /api/v1/connections/:idResponse
{
"success": true,
"data": {
"id": "conn_550e8400-e29b-41d4-a716-446655440000",
"name": "Stripe Production",
"provider": "stripe",
"status": "active",
"externalAccountId": "acct_xxx",
"lastSyncedAt": "2024-01-15T10:30:00.000Z",
"metadata": {
"environment": "production"
},
"createdAt": "2024-01-01T10:00:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
}
}Delete Connection
Revoke and delete a connection. This also removes the connection from Nango.
DELETE /api/v1/connections/:idResponse
{
"success": true,
"data": {
"deleted": true
}
}Deleting a connection will cause workflows using this connection to fail. Make sure to update or pause affected workflows first.
Refresh Connection
Manually refresh connection credentials. Useful when credentials are about to expire.
POST /api/v1/connections/:id/refreshResponse
{
"success": true,
"data": {
"id": "conn_550e8400-e29b-41d4-a716-446655440000",
"lastSyncedAt": "2024-01-15T10:35:00.000Z",
"message": "Connection refresh completed"
}
}Error Response (Refresh Failed)
If the refresh fails, the connection status is updated to error:
{
"success": false,
"error": {
"code": "INTERNAL_ERROR",
"message": "Failed to refresh credentials: Token expired"
}
}Verify Connection
Test connection health by verifying credentials with the provider.
POST /api/v1/connections/:id/verifyResponse (Healthy Connection)
{
"success": true,
"data": {
"healthy": true,
"connectionId": "conn_550e8400-e29b-41d4-a716-446655440000",
"provider": "stripe",
"status": "active",
"externalAccountId": "acct_xxx",
"error": null,
"checkedAt": "2024-01-15T10:35:00.000Z"
}
}Response (Unhealthy Connection)
{
"success": true,
"data": {
"healthy": false,
"connectionId": "conn_550e8400-e29b-41d4-a716-446655440000",
"provider": "stripe",
"status": "error",
"externalAccountId": null,
"error": "Invalid API key provided",
"checkedAt": "2024-01-15T10:35:00.000Z"
}
}Response (Not Yet Authorized)
{
"success": true,
"data": {
"healthy": false,
"connectionId": "conn_550e8400-e29b-41d4-a716-446655440000",
"provider": "stripe",
"status": "pending",
"error": "Connection not yet authorized - complete OAuth flow first",
"checkedAt": "2024-01-15T10:35:00.000Z"
}
}Connection Statuses
| Status | Description |
|---|---|
pending | OAuth flow started but not completed |
active | Connection is working properly |
error | Connection has an issue (check errorMessage) |
expired | OAuth token has expired, needs re-authorization |
disconnected | User revoked access or connection was disconnected |
Supported Providers
| Provider | OAuth | Description |
|---|---|---|
stripe | Yes | Payment processing |
salesforce | Yes | CRM |
hubspot | Yes | Marketing/CRM |
quickbooks | Yes | Accounting |
pandadoc | Yes | Document signing |
netsuite | Yes | ERP |
slack | Yes | Messaging |
gmail | Yes | Email (Google) |
OAuth Flow
The typical OAuth flow for connecting a provider:
1. Your app calls GET /api/v1/connections/:provider/auth-url
2. API returns authUrl and connectionId
3. Your app redirects user to authUrl
4. User authorizes in provider's UI
5. Provider redirects to Nango callback
6. Nango redirects to /api/v1/connections/:provider/callback
7. API updates connection status to 'active'
8. User is redirected to your redirectUrlExample Flow (JavaScript)
// Step 1: Get auth URL
const authResponse = await fetch(
`http://localhost:3000/api/v1/connections/stripe/auth-url?redirectUrl=${encodeURIComponent('https://app.example.com/settings')}`,
{ headers: { 'x-api-key': API_KEY } }
);
const { data } = await authResponse.json();
// Step 2: Redirect user to OAuth
window.location.href = data.authUrl;
// Step 3: Handle callback (on your redirect page)
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get('success') === 'true') {
const connectionId = urlParams.get('connectionId');
console.log('Connection created:', connectionId);
} else {
const error = urlParams.get('error');
console.error('OAuth failed:', error);
}Error Responses
Connection Not Found (404)
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Connection not found"
}
}Active Connection Exists (400)
{
"success": false,
"error": {
"code": "BAD_REQUEST",
"message": "Active connection already exists for stripe. Disconnect first to re-authorize."
}
}