Skip to main content
A connection lives from the moment a user authorizes an account until it’s deleted. In between, BundleUp keeps its access token usable so your requests just work. A connection starts Active. Each request checks the access token. If it’s about to expire, BundleUp refreshes it before forwarding the request. If it’s only due for an early refresh, BundleUp refreshes it in the background. A failed refresh doesn’t disable the connection; the next request tries again. The connection ends when it’s deleted.

Creation

A connection is created when:
  • a user completes the authorization flow, or
  • you import existing tokens with POST /v1/connections (useful when migrating from your own OAuth implementation).
Either way, you receive a connection.created webhook.

Token refresh

Access tokens expire. Some last an hour, some a few minutes, some never. BundleUp keeps them fresh on demand, at the moment a request needs them: If several requests for the same connection need a refresh at the same moment, only one refresh call is made to the provider and all requests use its result. This matters for providers that rotate refresh tokens: two simultaneous refreshes would otherwise invalidate each other. Each successful refresh sends a connection.refreshed webhook. You can also refresh a connection by hand from the dashboard (Connections → Refresh connection token), for example after fixing an integration’s credentials.
Because refresh happens on demand, a connection that isn’t used for a long time isn’t refreshed in the meantime. That’s fine for most providers: the refresh token is still valid when the next request arrives. A few providers expire unused refresh tokens after a period of inactivity, in which case the user needs to reconnect.

When a refresh fails

A refresh can fail because the user revoked access at the provider, the provider expired the refresh token, the integration’s client secret changed, or the provider was briefly unavailable.
  • If the token had already expired, the request that triggered the refresh fails and nothing is sent to the provider. On the Proxy and MCP, you get 400 connection_refresh_failed when the connection has no refresh token, or a 5xx error when the provider rejects the refresh.
  • If the refresh was a background one, the current token is still valid, so your request goes through. The failure is silent.
In both cases the connection stays as it is. BundleUp doesn’t limit refresh attempts and doesn’t disable connections automatically. The next request that needs a fresh token tries again. Temporary provider problems fix themselves. If refreshes keep failing, the cause is permanent (usually the user revoked access) and the fix is to ask the user to reconnect:
  1. Watch for repeated connection_refresh_failed errors, or 401/403 responses from the provider, on the same connection.
  2. Show the user a “Reconnect” prompt that runs the authorization flow again.
  3. Store the new connection ID and delete the old connection.

Updates

The only field you can change on a connection is its external ID, from the dashboard or with PATCH /v1/connections/{id}. Changing it sends connection.updated. To change a connection’s scopes, the user has to go through the authorization flow again, which creates a new connection.

Deletion

Delete a connection when the user disconnects the integration in your product, or when you replace it with a new one:
BundleUp asks the provider to revoke the token where the provider supports revocation, then deletes the stored credentials. You receive connection.deleted. Any later request with that connection ID fails with connection_invalid. Deleting an integration deletes all of its connections.

When users revoke access at the provider

If a user removes your app from their account in the provider’s settings, BundleUp isn’t told. The connection still exists, but the provider rejects its token, usually with 401. The next refresh also fails. Handle it like any permanent refresh failure: prompt the user to reconnect, then delete the old connection.