Overview
This article covers how UniAsset secures integration API access — API key generation and storage, permission scopes, tenant isolation, webhook signing, and production security practices.
API Key Authentication
Key Format
UniAsset API keys follow the format:
ua_live_<64-hex-chars>
The first 12 characters after ua_live_ form an unencrypted prefix used for database lookup. The remaining 52 characters are the secret component. The full 64-character hex string is the key.
Storage
UniAsset stores only the bcrypt hash of the full key. The plaintext is never persisted. This means:
- The full key is shown once only at creation — copy it immediately
- UniAsset staff cannot retrieve your key
- If you lose the key, revoke it and generate a new one
Authentication Flow
1. Client sends: Authorization: Bearer ua_live_<key>
2. Server extracts prefix (first 12 chars)
3. Database lookup by prefix → finds API key record
4. bcrypt.compare(fullKey, storedHash) → verifies secret
5. Checks revokedAt is null
6. Resolves tenant plan → enforces plan gate
7. Checks required permission is in key.permissions
8. On success → handler executes with tenantId derived server-side
The tenantId is never accepted from the request body. It is always derived server-side from the API key record.
Permission Scopes
Each API key carries a set of permission scopes. A key can only call endpoints that match its granted permissions.
| Scope | Grants Access To |
|---|---|
asset:create | Create assets via integration API |
asset:update | Update assets (reserved — endpoint not yet released) |
asset:location | Update asset geographic position |
assignment:update | Assign assets to users or locations |
maintenance:create | Create maintenance records |
iot:signal:ingest | Ingest IoT signals (Enterprise plan required) |
Least-privilege principle: Grant only the scopes your integration actually uses. An IoT pipeline that ingests signals should receive only iot:signal:ingest — not asset:create or assignment:update.
Plan Enforcement
All integration API calls enforce plan access at runtime:
- CRUD operations (
asset:create,maintenance:create,assignment:update,asset:location) require Business plan or higher - IoT signal ingestion (
iot:signal:ingest) requires Enterprise plan
If the tenant's plan is insufficient, the API returns 403 PLAN_UPGRADE_REQUIRED or 403 ENTERPRISE_REQUIRED.
Tenant Isolation
Every API key is bound to a single tenant. There is no cross-tenant access. The server enforces this by:
- Deriving
tenantIdfrom the API key record only — never from the request body - Scoping all database queries with
tenantIdin theWHEREclause - Returning
404 NOT_FOUNDrather than403 FORBIDDENwhen a resource exists but belongs to a different tenant (prevents tenant enumeration)
Rate Limiting
Each API key has a rate limit (default: 60 requests/minute; maximum: 1,000 requests/minute). Rate limits are set at key creation.
When a rate limit is exceeded, the endpoint returns:
429 Too Many Requests
If your integration requires a higher rate limit, create a new key with a higher limit or contact support.
Audit Logging
Every integration API request — successful or failed — is recorded in IntegrationEventLog with:
- Timestamp
- Tenant ID
- API key ID and name
- Endpoint path
- HTTP status code
- Client IP address
- Sanitized request body (sensitive fields masked)
Audit logs are visible to Owner, Admin, and Manager roles at Settings → Integrations → Activity.
Webhook Security
HMAC-SHA256 Signing
UniAsset signs every outbound webhook delivery with HMAC-SHA256. The signature covers the full JSON body exactly as delivered.
Signature header: X-UniAsset-Signature: <hex-digest>
Compute the signature:
HMAC-SHA256(webhookSecret, rawBody) → hex string
Where rawBody is the exact byte-for-byte JSON string delivered in the POST body (do not parse and re-serialize — use the raw body).
Additional headers:
X-UniAsset-Event: <event-name>
X-UniAsset-Timestamp: <ISO8601>
For language-specific verification examples and replay-attack protection, see Webhook Security Verification.
Secret Storage
The webhook secret is generated server-side and shown once only at creation. Store it in your secrets manager. UniAsset stores the secret in the database — if you believe it has been exposed, delete the webhook and create a new one (a new secret will be generated).
Key Rotation
Rotate API keys regularly or immediately after suspected exposure:
- Create a new key with the same permissions
- Update your integration to use the new key
- Verify the new key is working
- Revoke the old key in Settings → Integrations → API Keys
Keys with existing audit log entries cannot be deleted (the audit trail must be preserved). Revoke instead of delete in these cases.
Key Per Integration
Create one API key per integration, not one key for all integrations. Benefits:
- Surgical revocation: Revoking a compromised key doesn't break unrelated integrations
- Audit clarity: Activity logs show which integration made each call
- Least privilege: Each key carries only the permissions that integration needs
IP Allowlisting
UniAsset records the client IP on every API call in the audit log. At this time, IP-based allowlisting is not enforced at the API layer. If your security policy requires it, implement IP filtering at your network or API gateway layer before forwarding requests to UniAsset.
Related Articles
Need Help?
If you have questions not covered in this article, our support team is here to help.
Contact Support