API Integration Guide
This guide is for developers who want to verify their users’ credentials programmatically — for example, checking that a job applicant holds a work certificate, or that a customer has passed identity verification — by integrating the Socious Verify API into their own application.
If you are looking for the non-technical product guide, start with Welcome to Socious Verify.
Base URLs
| Environment | URL |
|---|---|
| API | https://api.shinid.com |
| Dashboard (hosted pages) | https://app.shinid.com |
Authentication
- Sign in to the dashboard and open Integrations.
- Click Add, name your integration, and copy the Secret Key.
- Send the Secret Key in the
apikeyheader on API requests:
curl https://api.shinid.com/verifications/VERIFICATION_ID/individuals/CUSTOMER_ID \
-H "apikey: YOUR_SECRET_KEY"
The Secret Key identifies your organization and must only be used server-side — never expose it in browser or mobile code. The end-user-facing endpoints in the flows below (connect, verify) don’t require it.
Core Concepts
- Schema — defines the shape of a credential (its attributes and their types). Browse available schemas in the dashboard under Schemas.
- Verification — a reusable proof request you define once: which schema to ask for, plus optional conditions on attribute values. Created in the dashboard under Verifications.
- Verification individual — one verification request sent to one person. Each individual is tied to your
customer_id(any stable identifier from your system, e.g. your internal user ID) and moves through a status lifecycle until it is verified or fails.
Option A — Hosted Verification Page (recommended)
The fastest integration: send your user to a Socious-hosted page and check the result from your backend. No frontend work needed.
1. Create a verification in the dashboard and copy its ID.
2. Redirect your user to the hosted page, passing your own user identifier as customer:
https://app.shinid.com/connect/redirect/VERIFICATION_ID?customer=CUSTOMER_ID
The page shows a QR code / connection link. The user scans it with their Socious Wallet, approves the connection, and shares the requested credential.
3. Check the result from your backend using your Secret Key:
curl https://api.shinid.com/verifications/VERIFICATION_ID/individuals/CUSTOMER_ID \
-H "apikey: YOUR_SECRET_KEY"
{
"id": "9a1f0e9c-...",
"verification_id": "339ac66a-...",
"status": "VERIFIED",
"body": { "...": "credential data shared by the user" },
"validation_error": null,
"verified_at": "2026-08-05T10:21:33Z",
"created_at": "2026-08-05T10:18:02Z"
}
Treat the user as verified only when status is VERIFIED.
Option B — Direct API (custom UI)
Use this when you want the QR code / connection link inside your own interface.
1. Create a verification individual for your user:
curl -X POST https://api.shinid.com/verifications/individuals \
-H "Content-Type: application/json" \
-d '{
"verification_id": "VERIFICATION_ID",
"customer_id": "CUSTOMER_ID"
}'
Returns 201 with the individual record — keep its id (called INDIVIDUAL_ID below). Calling it again for the same customer and verification returns the same record instead of creating a duplicate.
2. Get a connection link and show it to the user:
curl https://api.shinid.com/verifications/INDIVIDUAL_ID/connect
The response includes connection_url — render it as a QR code for desktop users or open it directly on mobile, where it launches the Socious Wallet app. A connection link is reused for 2 minutes; call connect again to refresh an expired one.
3. Wait for the user. Once the wallet connects, Socious Verify automatically sends the proof request to the user’s wallet, and the user approves sharing the credential.
4. Poll for the result:
curl https://api.shinid.com/verifications/INDIVIDUAL_ID/verify
Each call returns the current individual record. Poll every few seconds until status becomes VERIFIED or FAILED:
async function waitForResult(individualId) {
while (true) {
const res = await fetch(`https://api.shinid.com/verifications/${individualId}/verify`);
const individual = await res.json();
if (individual.status === 'VERIFIED' || individual.status === 'FAILED') return individual;
await new Promise((r) => setTimeout(r, 3000));
}
}
For the final server-side check, prefer the authenticated lookup from Option A step 3 (GET /verifications/{verification_id}/individuals/{customer_id} with your apikey) so the result you act on comes from a request only your backend can make.
Status Lifecycle
| Status | Meaning |
|---|---|
CREATED | Individual created; user has not connected yet |
REQUESTED | Wallet connected; proof request sent, awaiting the user’s approval |
VERIFIED | Credential received and all conditions passed |
FAILED | Credential received but a condition failed — see validation_error |
Attribute Conditions
When creating a verification you can add conditions on schema attributes — for example graduation year BIGGER than 2020. Supported operators are EQUAL, NOT, BIGGER, and SMALLER. If the credential the user shares does not satisfy a condition, the individual ends in FAILED and validation_error explains which check failed. The shared credential data is available in body either way.
Errors
Errors return a JSON body with a single error field:
{ "error": "invalid apikey" }
| Code | Meaning |
|---|---|
400 | Malformed request or invalid ID |
401 | Missing or invalid apikey / token |
403 | Authenticated, but not allowed to access this resource |
Support
If you run into problems integrating, contact us via the contact page — include the verification ID and, if relevant, the individual ID.