Verification API
How verification works
Section titled “How verification works”When you submit a credential for verification, BaseID performs a multi-step cryptographic validation:
Credential string │ ├─ 1. Format detection (JWT-VC or SD-JWT based on ~ separator) │ ├─ 2. Decode JWT header → extract issuer DID (iss) and key ID (kid) │ ├─ 3. Resolve issuer DID → fetch DID Document with public keys │ ├─ 4. Find verification method → match kid to a public key in the document │ ├─ 5. Verify signature → cryptographic check using the issuer's public key │ ├─ 6. Check expiration → reject if exp claim is in the past │ └─ 7. Return result → issuer, subject, format, validityWhat verification proves
Section titled “What verification proves”| Check | What it confirms |
|---|---|
| Signature valid | The credential was signed by the private key matching the issuer’s DID |
| Issuer resolved | The issuer DID exists and has a valid DID Document |
| Not expired | The credential’s exp claim (if present) is in the future |
| Not tampered | Any modification to the credential invalidates the signature |
What verification does NOT check
Section titled “What verification does NOT check”- Revocation status — use the revoke endpoint to manage revocation
- Trust in the issuer — verification confirms the signature is valid, not that you should trust the issuer. Use the Trust API for reputation
- Claim accuracy — verification proves the issuer signed the claims, not that the claims are true
Verify a credential
Section titled “Verify a credential”POST /v1/verifyAuthorization: Bearer <token>Permission required: credentials:verify
Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
credential | string | Yes | Raw credential string (JWT compact or SD-JWT compact serialization) |
Format auto-detection
Section titled “Format auto-detection”The API automatically detects the format:
| Pattern | Detected format | How it’s verified |
|---|---|---|
Three .-separated parts, no ~ | jwt_vc_json (JWT-VC) | Full JWT verified |
Contains ~ separators | vc+sd-jwt (SD-JWT VC) | JWT part before first ~ is verified |
You do not need to specify the format — submit any credential string and the API handles it.
Example — verify a JWT-VC
Section titled “Example — verify a JWT-VC”curl -X POST https://api.baseid.cloud/v1/verify \ -H "Authorization: Bearer bsk_live_..." \ -H "Content-Type: application/json" \ -d '{ "credential": "eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6..." }'Example — verify an SD-JWT VC
Section titled “Example — verify an SD-JWT VC”curl -X POST https://api.baseid.cloud/v1/verify \ -H "Authorization: Bearer bsk_live_..." \ -H "Content-Type: application/json" \ -d '{ "credential": "eyJhbGciOiJFZERTQSJ9.eyJpc3Mi...~eyJfc2QiOi...~" }'Response — valid credential
Section titled “Response — valid credential”{ "valid": true, "format": "jwt_vc_json", "issuer": "did:key:z6MkIssuer...", "subject": "did:key:z6MkHolder...", "error": null}Response — invalid credential
Section titled “Response — invalid credential”{ "valid": false, "format": "jwt_vc_json", "issuer": null, "subject": null, "error": "JWT-VC verification failed: signature mismatch"}Response fields
Section titled “Response fields”| Field | Type | Description |
|---|---|---|
valid | boolean | true if signature is valid and credential is not expired |
format | string | Detected format: jwt_vc_json or vc+sd-jwt |
issuer | string or null | Issuer DID (extracted from iss claim). Null if verification failed before extraction. |
subject | string or null | Subject DID (from credentialSubject.id). Null for bearer credentials or on failure. |
error | string or null | Human-readable error message. Null on success. |
Common verification errors
Section titled “Common verification errors”| Error | Cause | Fix |
|---|---|---|
signature mismatch | Credential was tampered with, or signed by a different key than the DID claims | Re-issue the credential with the correct key |
missing iss claim in JWT | The JWT doesn’t contain an iss field | Ensure the credential was issued by BaseID or a compliant issuer |
failed to resolve DID | The issuer’s DID could not be resolved | Check that the issuer DID is valid and the method is supported (did:key) |
no verification method with JWK | The DID Document doesn’t contain a usable public key | The DID may be malformed or use an unsupported key type |
expired credential | The exp claim is in the past | Issue a new credential with a later expiration |
Verification in SDKs
Section titled “Verification in SDKs”TypeScript
Section titled “TypeScript”const result = await client.verify.credential(jwtString);if (result.valid) { console.log(`Issued by: ${result.issuer}`);} else { console.error(`Invalid: ${result.error}`);}Python
Section titled “Python”result = client.verify.credential(jwt_string)if result["valid"]: print(f"Issued by: {result['issuer']}")else: print(f"Invalid: {result['error']}")result, err := client.Verify.Credential(jwtString)if result.Valid { fmt.Println("Issued by:", result.Issuer)} else { fmt.Println("Invalid:", result.Error)}Supported DID methods for verification
Section titled “Supported DID methods for verification”| Method | Example | Resolution |
|---|---|---|
did:key | did:key:z6Mk... | Public key encoded in the DID itself — no network request |
Additional methods (did:web, did:peer, did:webvh) are available in
the core library and will be added to the Cloud API in a future release.
Usage metering
Section titled “Usage metering”Each verification call is counted toward your monthly API usage. Check current usage via the Usage API.
See also
Section titled “See also”- Credential Formats concept — format architecture and trade-offs
- DIDs concept — DID resolution used during verification
- Credentials API — issue credentials to verify
- Security Model — trust and verification architecture