API reference
Member attestation
For Zev partners: attest that a signed-in member is a verified member — student, professional or builder — through Zev Access.
Member attestation lets a partner organization tell Zev who one of their members is, so every Zev product can offer that member the benefits of Zev Access. A partner attests its verified members — today student, professional and builder.
Before it works
Three conditions, all enforced on Zev’s side. Attestation is refused, with a message saying which, until every one holds:
- Your workspace is enrolled in a program. A Zev admin enables it for an approved partner. Nothing you can do in the console turns it on.
- Your app is a verified Sign-in app. The same domain and entity verification behind going live. Attestation pauses if that verification lapses, and resumes when it is restored.
- The member has connected with ZevID. They complete Sign in with ZevID and approve the consent screen. Only then can you attest them. An account that exists only in your own database cannot be attested.
Where to find the accountId
accountId is the member’s ZevID account UUID — the identifier ZevID
issued for the person, not one you invent. After a member signs in with ZevID,
it appears on their user in this API, under externalAccounts, on the entry
whose provider is zevid:
curl https://api.zevauth.net/v1/users/user_123 \
-H "Authorization: Bearer sk_live_..."
{
"id": "user_123",
"email": "member@example.com",
"externalAccounts": [
{
"provider": "zevid",
"providerAccountId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"email": "member@example.com",
"verified": true,
"revoked": false
}
]
}
Pass that providerAccountId as accountId. ZevID rejects any other format
(for example an old zid_... string) with a 400.
Test and live
Attestation is live only. It writes a real fact onto a real ZevID account that every Zev product reads, so there is no test form: a test key calling these endpoints is refused before the request leaves ZevAuth, with a message saying so. Build and rehearse the member’s sign-in in your test environment as usual; attest them only from your live app once it is verified.
Attest
/v1/partner/affiliations/attest Server-side only, with your secret key. You send who the member is; you never send which workspace they belong to. That is taken from your key.
curl -X POST https://api.zevauth.net/v1/partner/affiliations/attest \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"accountId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"memberRef": "MEMBER-2023-0451",
"attributes": { "matriculationYear": 2023, "graduationYear": 2027, "institution": "Example University" }
}'
| Field | Required | Meaning |
|---|---|---|
accountId | yes | The member’s ZevID account UUID, from their zevid entry in externalAccounts (see above). |
memberRef | no | Your own member identifier. Stored for you; never shown to products or other partners. |
type | no | Which program to attest, if your workspace holds more than one. Omit it when you have one. |
attributes | no | Program facts. Conventions are per program type, below. |
expiresAt | sometimes | ISO 8601 end date. Optional when a graduationYear or your program default supplies one; required otherwise. See End dates. |
Re-attesting the same member refreshes their attributes and expiry, and
reactivates a lapsed one. When your workspace runs a single program, its
type is inferred and you can leave type out; send it only when the
workspace holds more than one.
End dates
Every affiliation has an end date, so benefits expire on their own rather than
lingering. The date comes from the first of these that applies: the expiresAt
you send, a graduationYear in attributes (for students), or your program’s
default. If none of them does, the attest is refused with a 400 — send an
expiresAt.
Your program also has a maximum membership length, agreed with Zev and
measured from the member’s first attestation (for example four years). Send
shorter end dates freely; a date beyond the maximum is refused with a 400 that
names the member’s last allowed date. Re-attesting does not extend it, even
after a revoke and a re-attest.
Attribute conventions
| Type | Attributes |
|---|---|
student | matriculationYear, graduationYear, institution |
professional | Whatever your agreement defines. |
builder | tier (member or lead), chapter, role |
Revoke
/v1/partner/affiliations/revoke The member left, was removed, or their membership lapsed. Revoking is allowed even while a program is suspended, because reducing access is never blocked.
curl -X POST https://api.zevauth.net/v1/partner/affiliations/revoke \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "accountId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d" }'
As with attest, add type only if your workspace holds more than one program.
Reporting
/v1/partner/affiliations/report Totals for your program, computed by ZevID. Server-side only, with your secret key; the workspace is taken from the key, so you only ever see your own numbers.
curl https://api.zevauth.net/v1/partner/affiliations/report \
-H "Authorization: Bearer sk_live_..."
{
"attested": 1240,
"active": 1097,
"claimedAtLeastOne": 823,
"claimsByOffer": [
{ "offerKey": "spotify", "title": "Spotify Premium", "claims": 611 }
],
"activeOverTime": [
{ "month": "2026-08", "active": 1042 },
{ "month": "2026-09", "active": 1097 }
]
}
Add ?type=<program> to narrow to one program when your workspace holds more
than one; omit it when you have a single program.
What attestation is not
An affiliation is a fact Zev stores about a person, read by Zev products. It is not a role, an organization, or user metadata in your own ZevAuth project, and it does not appear in your users’ tokens. If you need your own authorization data, use organizations or publicMetadata; those are yours. Attestation is for the Zev-wide member benefits your partnership is about.
Offers, packs and the claiming of them all live in ZevID and on the member’s ZevID account — ZevAuth does not model them. See Zev Access.
The member sees their affiliations on their ZevID account and can remove any of them; benefits expire on their own at the attested expiry.
Updated at, Wednesday, October 21, 2026