Phase 2 of WIA-ACS defines comprehensive RESTful and gRPC APIs for programmatic access to all access control functions. These APIs enable automation, third-party integrations, mobile applications, and custom workflows while maintaining security, consistency, and ease of use. This chapter details the API design principles, authentication mechanisms, endpoint specifications, and SDKs.
WIA-ACS APIs follow modern best practices and industry standards:
URL-based versioning (recommended):
https://api.example.com/v1/users
https://api.example.com/v2/users
Header-based versioning (alternative):
GET /users HTTP/1.1
Accept: application/vnd.wia-acs.v1+json
Version lifecycle:
v1.0 → v1.1 (backward compatible)
v1.x → v2.0 (breaking changes, deprecated v1 for 12 months)
Standard error response format:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"code": "INVALID_CREDENTIAL_FORMAT",
"message": "Credential format is invalid",
"details": "Field 'expires_at' must be after 'issued_at'",
"field": "expires_at",
"request_id": "req-20251226-143217-xyz",
"documentation_url": "https://docs.wia-acs.org/errors/INVALID_CREDENTIAL_FORMAT"
}
}
HTTP Status Codes:
200 OK - Successful GET request
201 Created - Successful POST creating resource
204 No Content - Successful DELETE
400 Bad Request - Invalid input
401 Unauthorized - Missing or invalid authentication
403 Forbidden - Authenticated but not authorized
404 Not Found - Resource doesn't exist
409 Conflict - Resource already exists or version conflict
429 Too Many Requests - Rate limit exceeded
500 Internal Server Error - Server-side failure
The Authentication API verifies user identity and issues access tokens:
Request:
POST /v1/authenticate HTTP/1.1
Content-Type: application/json
{
"credential_id": "cred-20251226-xyz789",
"factors": [
{
"type": "pin",
"value": "1234"
}
],
"device_info": {
"device_id": "reader-main-lobby-001",
"ip_address": "192.168.1.45",
"user_agent": "WIA-ACS-Reader/1.0"
}
}
Response (200 OK):
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "rt_abc123xyz789",
"user": {
"user_id": "usr-20251226-abc123",
"name": "John Doe",
"email": "john.doe@example.com",
"roles": ["role-employee", "role-building-access"]
},
"session_id": "sess-20251226-143217-abc",
"mfa_required": false
}
Response (401 Unauthorized - MFA Required):
{
"error": {
"code": "MFA_REQUIRED",
"message": "Multi-factor authentication required",
"mfa_token": "mfa_tmp_token_xyz",
"available_methods": ["totp", "sms", "biometric"],
"expires_in": 300
}
}
Request:
POST /v1/authenticate/mfa HTTP/1.1
Content-Type: application/json
{
"mfa_token": "mfa_tmp_token_xyz",
"method": "totp",
"code": "123456"
}
Response (200 OK):
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"user": { /* user object */ }
}
The Authorization API evaluates access requests against policies:
Request:
POST /v1/authorize HTTP/1.1
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
{
"user_id": "usr-20251226-abc123",
"resource": {
"type": "door",
"id": "door-server-room-a",
"attributes": {
"location": "headquarters",
"security_zone": "high"
}
},
"action": "entry",
"context": {
"timestamp": "2025-12-26T14:32:17Z",
"ip_address": "192.168.1.45",
"mfa_verified": true,
"mfa_verified_at": "2025-12-26T14:30:00Z"
}
}
Response (200 OK - Access Granted):
{
"decision": "permit",
"reason": "User has required role and meets all conditions",
"matched_policies": [
"policy-it-server-room-access"
],
"valid_until": "2025-12-26T22:00:00Z",
"conditions": {
"badge_out_required": true,
"max_duration_minutes": 120
},
"audit_id": "audit-20251226-143217-xyz"
}
Response (200 OK - Access Denied):
{
"decision": "deny",
"reason": "Access outside allowed time window",
"matched_policies": ["policy-default-deny"],
"requirements": {
"time": {
"required": "Monday-Friday 06:00-22:00",
"current": "2025-12-26T23:30:00Z (Thursday 23:30)"
}
},
"audit_id": "audit-20251226-233017-abc"
}
| Endpoint | Method | Description |
|---|---|---|
| /v1/users | GET | List users (paginated, filterable) |
| /v1/users | POST | Create new user |
| /v1/users/{id} | GET | Get user details |
| /v1/users/{id} | PATCH | Update user (partial update) |
| /v1/users/{id} | DELETE | Delete/deactivate user |
| /v1/users/{id}/roles | GET | Get user's roles |
| /v1/users/{id}/roles | POST | Assign role to user |
| /v1/users/{id}/credentials | GET | List user's credentials |
Request:
GET /v1/users?status=active&department=Engineering&page=1&per_page=20&sort=name
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Response (200 OK):
{
"users": [
{
"user_id": "usr-001",
"status": "active",
"identity": {
"given_name": "John",
"family_name": "Doe",
"email": "john.doe@example.com"
},
"employment": {
"department": "Engineering",
"title": "Senior Software Engineer"
},
"roles": ["role-employee", "role-engineering"]
},
/* ... more users ... */
],
"pagination": {
"current_page": 1,
"per_page": 20,
"total_pages": 5,
"total_items": 97,
"has_next": true,
"has_previous": false
},
"links": {
"self": "/v1/users?page=1&per_page=20",
"next": "/v1/users?page=2&per_page=20",
"first": "/v1/users?page=1&per_page=20",
"last": "/v1/users?page=5&per_page=20"
}
}
Request:
POST /v1/credentials HTTP/1.1
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
{
"user_id": "usr-20251226-abc123",
"credential_type": "smart_card",
"issued_at": "2025-12-26T10:00:00Z",
"expires_at": "2026-12-26T10:00:00Z",
"encoding": {
"format": "piv",
"facility_code": 123,
"card_number": 45678
},
"access_profiles": ["profile-building-entry", "profile-office-floor-5"],
"factors": [
{
"factor_type": "something_you_have",
"method": "smart_card",
"strength": "high"
},
{
"factor_type": "something_you_know",
"method": "pin",
"strength": "medium",
"pin": "1234"
}
]
}
Response (201 Created):
{
"credential_id": "cred-20251226-xyz789",
"user_id": "usr-20251226-abc123",
"credential_type": "smart_card",
"status": "active",
"issued_at": "2025-12-26T10:00:00Z",
"expires_at": "2026-12-26T10:00:00Z",
"encoding": {
"format": "piv",
"facility_code": 123,
"card_number": 45678,
"chip_uid": "04:3F:2A:B5:C8:19:80"
},
"qr_code": "data:image/png;base64,iVBORw0KGgoAAAANS...",
"provisioning_url": "https://acs.example.com/provision/cred-20251226-xyz789"
}
Request:
DELETE /v1/credentials/cred-20251226-xyz789?reason=lost_stolen
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Response (204 No Content):
{
"revoked_at": "2025-12-26T14:35:00Z",
"revocation_reason": "lost_stolen",
"revoked_by": "usr-admin-001",
"replacement_credential": null
}
Request:
GET /v1/audit/events?start_date=2025-12-26T00:00:00Z&end_date=2025-12-26T23:59:59Z
&event_type=access_denied&user_id=usr-20251226-abc123
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Response (200 OK):
{
"events": [
{
"event_id": "evt-20251226-143217-abc123",
"event_type": "access_denied",
"timestamp": "2025-12-26T14:32:17.234Z",
"actor": {
"user_id": "usr-20251226-abc123",
"user_name": "John Doe"
},
"target": {
"resource_type": "door",
"resource_id": "door-server-room-a"
},
"result": "denied",
"reason": "Insufficient clearance level"
}
],
"pagination": { /* pagination info */ }
}
WIA-ACS supports webhooks for real-time event notifications:
Request (Create Webhook):
POST /v1/webhooks HTTP/1.1
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
{
"url": "https://example.com/wia-acs-webhook",
"events": ["access_granted", "access_denied", "credential_revoked"],
"secret": "whsec_xyz123abc789",
"active": true,
"filters": {
"resource_type": "door",
"location": "headquarters"
}
}
Webhook Delivery (POST to subscribed URL):
POST /wia-acs-webhook HTTP/1.1
Content-Type: application/json
X-WIA-ACS-Event: access_granted
X-WIA-ACS-Signature: sha256=abc123...
X-WIA-ACS-Delivery: delivery-20251226-143217-xyz
{
"webhook_id": "webhook-001",
"event": {
"event_id": "evt-20251226-143217-abc123",
"event_type": "access_granted",
"timestamp": "2025-12-26T14:32:17.234Z",
/* full event object */
}
}
| Tier | Rate Limit | Burst | Use Case |
|---|---|---|---|
| Basic | 1,000 req/hour | 20 req/min | Small deployments |
| Standard | 10,000 req/hour | 100 req/min | Medium enterprises |
| Premium | 100,000 req/hour | 500 req/min | Large enterprises |
| Enterprise | Custom | Custom | Global deployments |
Rate Limit Headers:
HTTP/1.1 200 OK
X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 9847
X-RateLimit-Reset: 1735225200
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1735225200
Retry-After: 3600
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "API rate limit exceeded",
"retry_after": 3600
}
}
WIA-ACS provides official SDKs in multiple languages:
import { WiaAcsClient } from '@wia/acs-sdk';
const client = new WiaAcsClient({
apiUrl: 'https://api.example.com',
apiKey: 'your-api-key'
});
// Authenticate user
const authResult = await client.authenticate({
credentialId: 'cred-xyz789',
factors: [
{ type: 'pin', value: '1234' }
]
});
// Check authorization
const authzResult = await client.authorize({
userId: authResult.user.user_id,
resource: { type: 'door', id: 'door-main-lobby' },
action: 'entry'
});
if (authzResult.decision === 'permit') {
console.log('Access granted!');
}
from wia_acs import WiaAcsClient
client = WiaAcsClient(
api_url="https://api.example.com",
api_key="your-api-key"
)
# Create user
user = client.users.create({
"identity": {
"given_name": "Jane",
"family_name": "Smith",
"email": "jane.smith@example.com"
},
"roles": ["role-employee"]
})
# Issue credential
credential = client.credentials.create({
"user_id": user.user_id,
"credential_type": "smart_card",
"expires_at": "2026-12-26T10:00:00Z"
})
print(f"Created credential: {credential.credential_id}")
For high-performance scenarios, WIA-ACS provides gRPC APIs alongside REST:
// Protocol Buffer Definition
service AuthenticationService {
rpc Authenticate(AuthenticateRequest) returns (AuthenticateResponse);
rpc AuthenticateMFA(MFARequest) returns (AuthenticateResponse);
rpc RefreshToken(RefreshTokenRequest) returns (AuthenticateResponse);
}
message AuthenticateRequest {
string credential_id = 1;
repeated AuthFactor factors = 2;
DeviceInfo device_info = 3;
}
message AuthenticateResponse {
string access_token = 1;
string token_type = 2;
int32 expires_in = 3;
User user = 4;
bool mfa_required = 5;
}
Benefits of gRPC:
• 5-10x faster than REST for high-frequency operations
• Binary protocol reduces bandwidth
• Built-in streaming for real-time events
• Strong typing with Protocol Buffers
• Automatic client generation in 10+ languages
This chapter covered Phase 2 of WIA-ACS: comprehensive API interfaces. We explored RESTful API design, authentication and authorization endpoints, user and credential management, audit APIs, webhooks for real-time events, rate limiting, and SDK libraries. These APIs enable automation, integration, and custom application development while maintaining security and consistency.
With APIs defined, Chapter 6 examines Phase 3: secure communication protocols. We'll explore TLS 1.3 for transport security, OAuth 2.0 and OpenID Connect for authentication, SAML for enterprise SSO, and certificate management best practices.