Home/Knowledge Base/Security & Compliance/API Security — Secure Integration and API Access
Back to Security & Compliance

API Security — Secure Integration and API Access

8 min readadvancedLast updated: January 2, 2026

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.

ScopeGrants Access To
asset:createCreate assets via integration API
asset:updateUpdate assets (reserved — endpoint not yet released)
asset:locationUpdate asset geographic position
assignment:updateAssign assets to users or locations
maintenance:createCreate maintenance records
iot:signal:ingestIngest 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 tenantId from the API key record only — never from the request body
  • Scoping all database queries with tenantId in the WHERE clause
  • Returning 404 NOT_FOUND rather than 403 FORBIDDEN when 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:

  1. Create a new key with the same permissions
  2. Update your integration to use the new key
  3. Verify the new key is working
  4. 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