Authentication & API Keys
How to authenticate, manage keys, handle permissions, and rotate credentials.
Authentication Method
All Enterprise API requests are authenticated via the X-API-Key header:
GET /api/enterprise/v1/talent/profiles/GPIN12345 HTTP/1.1
Host: api.genuinein.com
X-API-Key: gin_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6
Key Format
| Property | Value |
| Prefix | gin_ |
| Length | 64 characters total |
| Character set | Alphanumeric (a-z, 0-9) |
| Storage | SHA-256 hashed (raw key shown once at creation) |
| Example | gin_a1b2c3d4e5f6g7h8...z6 |
Key Lifecycle
CREATE ──→ ACTIVE ──→ ROTATE ──→ REVOKE
│ │
│ (immediate) │
└──────────────────────┘
Creating a Key
- Developer Portal → API Keys → Create New Key
- Select permissions (see below)
- Optionally set: IP allowlist, expiration date, webhook URL
- Copy the raw key immediately — cannot be retrieved again
Rotating a Key
- Create a new key with same permissions
- Update your integration to use the new key
- Revoke the old key after confirming new one works
- Old key has no grace period after revocation
Revoking a Key
- Immediate effect — all requests with this key return
401
- Active webhook deliveries for this key stop immediately
- Audit log entry created
Permission Model
Permissions are stored as JSONB on each key, scoped as resource:action:
{
"talent": {
"search": true,
"read": true,
"pool": true,
"pool_write": true,
"analytics": true,
"export": true
}
}
Available Permissions
| Permission | Grants Access To |
talent:search | POST /talent/search, POST /talent/bulk-search |
talent:read | GET /talent/profiles/* (all profile endpoints) |
talent:pool | GET /talent/pool |
talent:pool_write | POST /talent/pool/add, DELETE /talent/pool/{gpin} |
talent:analytics | GET /talent/insights |
talent:export | POST /talent/export, status, download |
Least Privilege Recommendations
| Use Case | Recommended Permissions |
| ATS integration (search + view) | talent:search, talent:read |
| Dashboard (analytics only) | talent:pool, talent:analytics |
| Full integration | All talent:* |
| Read-only monitoring | talent:read, talent:pool |
Security Best Practices
| Practice | Why |
| Never commit keys to source control | Keys are permanent credentials |
| Use environment variables | GENUINEIN_API_KEY env var |
| Rotate keys every 90 days | Limit exposure window |
| Separate keys per environment | dev/staging/production isolation |
| Set IP allowlist in production | Prevent key theft abuse |
| Monitor usage in Developer Portal | Detect anomalous patterns |
| Revoke immediately if compromised | No grace period needed |
Request & Response Headers
Request Headers
| Header | Required | Description |
X-API-Key | Yes | Your API key |
Content-Type | Yes (POST/PUT) | application/json |
X-Idempotency-Key | Recommended (POST) | Prevent duplicate operations |
X-Sandbox | Optional | true for sandbox mode |
Response Headers
| Header | Description |
X-Request-Id | Unique request ID for support |
X-RateLimit-Limit | Requests allowed per minute |
X-RateLimit-Remaining | Remaining in current window |
X-RateLimit-Reset | Unix timestamp of window reset |
Authentication Error Responses
{
"success": false,
"data": null,
"error": {
"code": "AUTH_REQUIRED",
"message": "API key is required. Provide it via X-API-Key header.",
"status_code": 401
},
"meta": { "request_id": "abc123def456" }
}
| Status | Code | Meaning |
| 401 | AUTH_REQUIRED | No key provided |
| 401 | AUTH_EXPIRED | Key expired or revoked |
| 403 | FORBIDDEN | Key lacks required permission |
| 403 | IP_BLOCKED | Request from non-allowed IP |