Supyagent
Connected Accounts

Troubleshooting

Error reference and debugging guide for the Connected Accounts API — authentication, rate limiting, OAuth flows, integrations, and common issues.

Troubleshooting

This page covers every error you might encounter when using the Connected Accounts API, organized by category. Each error includes the HTTP status code, response format, common causes, and how to fix it.

Authentication Errors

401 — Invalid or Missing API Key

{
  "ok": false,
  "error": "Invalid or missing API key"
}

Causes:

  • Missing Authorization header
  • Malformed header (must be Bearer sk_live_...)
  • API key was deleted or regenerated in the dashboard
  • Using a key from a different environment

Fix: Verify the header format is exactly Authorization: Bearer sk_live_your_key_here. If the key was regenerated, update your application with the new key.


403 — Partner Required

{
  "ok": false,
  "error": "Partner profile required",
  "error_code": "PARTNER_REQUIRED"
}

Causes:

  • The API key belongs to an account that hasn't registered as a partner
  • Partner profile was deactivated

Fix: Register as a partner at supyagent.com/settings/partner. See the Quickstart.


403 — Partner Suspended

{
  "ok": false,
  "error": "Partner profile is suspended"
}

Causes:

  • Partner profile was suspended due to policy violation or billing issue

Fix: Contact support to resolve the suspension.


401 — Payment Past Due

{
  "ok": false,
  "error": "Payment past due. Please update your payment method."
}

Causes:

  • Stripe payment failed and subscription status is past_due
  • Applies to all tiers — all API requests are blocked until resolved

Fix: Update your payment method in the dashboard at Settings > Billing. API access resumes immediately after successful payment.


Rate Limiting

429 — Rate Limit Exceeded

{
  "ok": false,
  "error": "Rate limit exceeded"
}

The response includes these headers:

HeaderExampleDescription
X-RateLimit-Minute-Limit30Per-minute limit for your tier
X-RateLimit-Minute-Remaining0Requests remaining in the current minute
Retry-After45Seconds to wait before retrying

Per-minute limits by tier:

TierRequests/Minute
Free30
Pro300
Enterprise1,000

Fix: Wait for the Retry-After duration, then retry. Implement exponential backoff in your client. If you consistently hit limits, upgrade your tier.


429 — Monthly Quota Exceeded (Free Tier)

{
  "ok": false,
  "error": "Free tier limit of 1000 API calls reached. Upgrade to Pro for more."
}

The response includes:

HeaderExampleDescription
X-RateLimit-Limit1000Monthly quota
X-RateLimit-Remaining0Remaining calls this month

Causes:

  • Free tier has a hard cap of 1,000 API calls per month
  • No overage is allowed on the free tier

Fix: Upgrade to Pro at Settings > Billing. Pro tier allows 100,000 calls/month with overage billing at $0.50/1,000 calls.


OAuth Flow Errors

These errors appear as query parameters on your redirect_url after an OAuth flow fails.

access_denied

https://yourapp.com/callback?error=access_denied

Cause: The user clicked "Deny" or "Cancel" on the OAuth consent screen.

Fix: Show the user a friendly message explaining why the permission is needed. Offer to retry the connection.


session_expired

https://yourapp.com/callback?error=session_expired

Cause: The connect session exceeded its 30-minute time limit. The user took too long to complete authorization.

Fix: Create a new connect session and redirect the user again. Sessions expire 30 minutes after creation.


session_already_used

https://yourapp.com/callback?error=session_already_used

Cause: The connect session was already completed (the authorization code was already exchanged). This can happen if the user refreshes the callback page or navigates back.

Fix: Check the session status — the integration may already be active. If not, create a new connect session.


no_code

https://yourapp.com/callback?error=no_code

Cause: The OAuth provider redirected back without an authorization code. This is unusual and typically indicates a provider-side issue.

Fix: Retry the connection. If it persists, check the provider's status page.


token_exchange_failed

https://yourapp.com/callback?error=token_exchange_failed

Cause: Supyagent received the authorization code but failed to exchange it for tokens. This can happen if:

  • The OAuth app credentials are misconfigured
  • The provider's token endpoint is down
  • The PKCE code verifier doesn't match

Fix: Retry the connection. If it persists, verify your OAuth app is correctly configured with the provider.


Integration Errors

Account Not Found

{
  "ok": false,
  "error": "Connected account \"invalid-id\" not found"
}

Causes:

  • The X-Account-Id value doesn't match any external_id under your partner profile
  • Typo in the external_id
  • The account was deleted

Fix: Verify the external_id matches exactly. Use List Accounts to see all accounts.


Integration Not Found

{
  "ok": false,
  "error": "No active google integration for this account",
  "error_code": "INTEGRATION_NOT_FOUND"
}

Causes:

  • The account doesn't have the requested provider connected
  • The integration was disconnected
  • The integration status is expired or revoked

Fix: Check the account's integrations, then initiate a new connect session if needed.


Token Error

{
  "ok": false,
  "error": "Failed to refresh access token",
  "error_code": "INTEGRATION_TOKEN_ERROR"
}

Causes:

  • The refresh token is invalid (user revoked access from the provider's settings)
  • The provider's token endpoint returned an error
  • The OAuth app's credentials changed

Fix: The user needs to re-authorize. Create a new connect session for the provider. The old integration will be replaced.


Duplicate External ID

{
  "ok": false,
  "error": "Account with external_id \"user-123\" already exists",
  "error_code": "DUPLICATE_EXTERNAL_ID"
}

Cause: You tried to create an account with an external_id that already exists under your partner profile.

Fix: Use the existing account, or choose a different external_id. Use Get Account to find the existing account.


Debugging Workflow

Step 1: Verify Authentication

# Test your API key
curl -s https://app.supyagent.com/api/v1/accounts?limit=1 \
  -H "Authorization: Bearer sk_live_your_key_here" | jq .ok

Expected: true. If false, check your API key.

Step 2: Verify the Connected Account

# List accounts to find the external_id
curl -s https://app.supyagent.com/api/v1/accounts \
  -H "Authorization: Bearer sk_live_your_key_here" | jq '.data.accounts[] | {external_id, id}'

Step 3: Verify the Integration

# Check integration status for a specific account
curl -s https://app.supyagent.com/api/v1/accounts/ACCOUNT_UUID/integrations \
  -H "Authorization: Bearer sk_live_your_key_here" | jq '.data.integrations[] | {provider, status}'

Look for "status": "active". If the status is expired or revoked, the user needs to re-authorize.

Step 4: Test the Provider Call

# Make a simple read-only call
curl -v https://app.supyagent.com/api/v1/google/gmail/messages \
  -H "Authorization: Bearer sk_live_your_key_here" \
  -H "X-Account-Id: user-123"

The -v flag shows response headers including rate limit info.

Step 5: Check Rate Limits

Look at the response headers:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Minute-Limit: 30
X-RateLimit-Minute-Remaining: 28

If X-RateLimit-Remaining is 0, you've hit your monthly quota. If X-RateLimit-Minute-Remaining is 0, wait for the minute window to reset.


Common Mistakes

MistakeFix
Using the Supyagent UUID as X-Account-IdUse the external_id you set when creating the account
Passing account_id as a query parameterUse the X-Account-Id header instead
Not checking integration status before callingCheck that the integration is active first
Creating duplicate accounts instead of reusingHandle the 409 response and reuse the existing account
Caching OAuth tokens client-sideAlways go through the Supyagent API — it handles token lifecycle