Developer Documentation
Integrate human verification into your platform in minutes. Everything you need to prove your users are real.
Quick Start
Install the SDK for your language, initialize with your API key, and verify your first user in three lines of code.
// JavaScript SDK import { POYVerify } from '@poyverify/sdk'; const poy = new POYVerify({ apiKey: 'your-api-key' }); const result = await poy.verify(userId); if (result.isHuman) { /* trusted user */ }
# Python SDK from poyverify import POYVerify poy = POYVerify(api_key="your-api-key") result = poy.verify(user_id) if result.is_human: # trusted user
Authentication
All API requests require a valid API key sent via the Authorization header using the Bearer token scheme.
Authorization: Bearer your-api-key
You can generate API keys from the POY Dashboard. Each key is scoped to a single project and can be revoked at any time.
Base URL
https://poyverify.com/api/poyCore Endpoints
Perform a full human verification check on a user. Returns verification status, trust score, and metadata.
Request Body
{
"userId": "usr_abc123",
"checkType": "full",
"metadata": {
"ip": "203.0.113.42",
"userAgent": "Mozilla/5.0..."
}
}Response
{
"isHuman": true,
"trustScore": 94,
"poyId": "PoY #00482A1",
"verifiedAt": "2026-04-07T12:00:00Z",
"checks": {
"liveness": "pass",
"device": "pass",
"behavioral": "pass"
}
}Quick boolean humanity check. Returns a simple true/false result with minimal latency - ideal for real-time gating.
Response
{
"isHuman": true,
"poyId": "PoY #00482A1"
}Public enrollment endpoint. No authentication required. Rate limited to 10 requests per minute per IP. Used for onboarding new users directly from your front end.
Request Body
{
"email": "user@example.com",
"displayName": "Jane Doe",
"platform": "your-app-name"
}Response
{
"poyId": "PoY #009F3B2",
"enrollmentUrl": "https://poyverify.com/enroll?token=enr_...",
"expiresAt": "2026-04-08T12:00:00Z"
}Public profile lookup. Returns non-sensitive verification status and badge information for a given PoY ID.
Response
{
"poyId": "PoY #00482A1",
"isVerified": true,
"badgeLevel": "verified",
"trustScore": 94,
"verifiedSince": "2026-01-15T08:00:00Z"
}Content Stamps
Stamp a piece of content as human-made. Generates a unique stamp ID and cryptographic signature tied to the creator's PoY identity.
Request Body
{
"contentHash": "sha256:a1b2c3d4...",
"contentType": "article",
"title": "My Blog Post",
"url": "https://example.com/post"
}Response
{
"stampId": "stmp_7f8a9b0c1d2e",
"signature": "ecdsa:...",
"createdBy": "PoY #00482A1",
"createdAt": "2026-04-07T12:30:00Z"
}Verify that a content stamp is authentic and was created by a verified human.
Request Body
{
"stampId": "stmp_7f8a9b0c1d2e"
}Response
{
"valid": true,
"createdBy": "PoY #00482A1",
"contentType": "article",
"stampedAt": "2026-04-07T12:30:00Z",
"isHumanCreator": true
}Trust & Authentication
Query the trust score for a user. Returns a 0-100 score based on verification history, behavioral signals, and credential strength.
Response
{
"userId": "usr_abc123",
"trustScore": 94,
"level": "high",
"factors": {
"liveness": 98,
"device": 90,
"behavioral": 92,
"credential": 95
}
}Initiate WebAuthn passkey registration for a user. Returns a challenge and credential creation options that you pass to the browser's WebAuthn API.
Request Body
{
"userId": "usr_abc123",
"displayName": "Jane Doe"
}Response
{
"challenge": "base64url-encoded-challenge",
"rp": { "name": "POY Verify", "id": "poyverify.com" },
"user": {
"id": "base64url-user-id",
"name": "Jane Doe",
"displayName": "Jane Doe"
},
"pubKeyCredParams": [
{ "type": "public-key", "alg": -7 }
],
"timeout": 60000
}Authenticate a user with a previously registered WebAuthn passkey. Returns a signed session token on success.
Request Body
{
"credentialId": "base64url-credential-id",
"authenticatorData": "base64url-auth-data",
"clientDataJSON": "base64url-client-data",
"signature": "base64url-signature"
}Response
{
"authenticated": true,
"sessionToken": "poy_sess_...",
"expiresAt": "2026-04-07T14:00:00Z",
"userId": "usr_abc123"
}Rate Limits
API rate limits are enforced per API key. Exceeding the limit returns a 429 status code with a Retry-After header.
| Plan | Requests / Minute | Requests / Day |
|---|---|---|
| Free | 60 | 1,000 |
| Pro | 300 | 50,000 |
| Enterprise | Custom | Unlimited |
/api/poy/public-enroll endpoint has a separate limit of 10 requests per minute per IP address, regardless of API key.Error Codes
All errors return a JSON body with a code and human-readable message field.
{
"error": {
"code": 401,
"message": "Invalid or missing API key."
}
}| Status | Meaning | Common Cause |
|---|---|---|
400 |
Bad Request | Missing required fields or invalid format |
401 |
Unauthorized | Missing or invalid API key |
403 |
Forbidden | API key lacks permission for this endpoint |
404 |
Not Found | User or resource does not exist |
429 |
Too Many Requests | Rate limit exceeded - check Retry-After header |
500 |
Internal Server Error | Unexpected server error - retry or contact support |
SDKs
Official SDKs handle authentication, retries, and error parsing so you can focus on your integration.
JavaScript / Node.js
Works in Node.js 18+ and modern browsers. TypeScript support included.
Python
Python 3.8+ with async/await support. Fully typed with type hints.
Need a different language? The REST API works with any HTTP client. See the Authentication section for details.
Webhooks
Receive real-time notifications when verification events occur. Configure webhook URLs in your POY Dashboard.
Event Types
user.verified
Fired when a user completes verification successfully
user.failed
Fired when a verification attempt fails
stamp.created
Fired when a new content stamp is created
trust.changed
Fired when a user's trust score changes significantly
passkey.registered
Fired when a user registers a new passkey
Webhook Payload
{
"event": "user.verified",
"timestamp": "2026-04-07T12:00:00Z",
"data": {
"userId": "usr_abc123",
"poyId": "PoY #00482A1",
"trustScore": 94
}
}Signature Verification
Every webhook request includes an X-POY-Signature header containing an HMAC-SHA256 signature of the request body. Verify this signature using your webhook secret to confirm authenticity.
const crypto = require('crypto'); function verifyWebhook(body, signature, secret) { const expected = crypto .createHmac('sha256', secret) .update(body) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expected) ); }