Delegated access to Zev products
Revocation
Every way a connection ends, how your app notices, and how to disconnect a user from your side.
The user is always in control of a connection. It can end, or narrow, in four ways:
| Who | What happens |
|---|---|
| The user | Disconnects your app in their ZevID account under Apps and websites, or removes one target. Removing the last target disconnects. |
| You | Call the revoke endpoint below, for example when the user clicks Disconnect inside your app. |
| The product | Removes a target when the user loses their role on it, or the target is deleted. It can also suspend your app on that product. |
| ZevID | Suspends one connection, your app on one product, or your app on every product. |
A revoke takes effect immediately. A suspension blocks refresh and new authorizations until it is lifted.
Revoke a connection
/v1/partner/delegated/revoke Server side only, with your secret key (sk_live_…, or sk_test_… for a test connection). Send the grant_id from the
token response.
curl https://api.zevauth.net/v1/partner/delegated/revoke \
-H "Authorization: Bearer sk_live_..." \
-H "content-type: application/json" \
-d '{ "grant_id": "6d1d2c3b-4a5f-4e6d-8c7b-9a0b1c2d3e4f", "reason": "user disconnected in app" }'
reason is optional, up to 200 characters, and for your own records.
{
"grant_id": "6d1d2c3b-4a5f-4e6d-8c7b-9a0b1c2d3e4f",
"status": "revoked",
"gv": 7,
"revoked_at": "2026-10-20T09:12:44.000Z"
}
It is idempotent: revoking an already revoked connection succeeds again.
A grant_id that is not one of your connections returns
404 grant_not_found. The user does not get an email when you revoke.
How you notice
| Signal | Means |
|---|---|
delegated_access.connection.revoked webhook | The connection is gone. by says who. |
delegated_access.connection.updated with targets_removed or suspended | It narrowed, or is paused for now. |
400 invalid_grant on refresh | The connection is revoked or suspended, or the refresh token is no longer valid. |
401 from the product’s API | The access token is no longer accepted. |
Access tokens already issued last at most 10 minutes, and products check every call against the current state of the connection, so a revoke is honoured within seconds.
What to do
- Delete the stored refresh token for that connection. It will never work again.
- Mark the connection disconnected in your app.
- Show the user a Reconnect button that starts the
flow again. For a removed target, a
prompt=configurelink lets them pick targets again.
Updated at, Wednesday, October 21, 2026