Implementation Guide
Credential Lifecycle Flows
This section describes how each lifecycle operation should behave from an integration-implementation perspective.
Lifecycle Summary
Operation | Trigger in Sine | Endpoint | Runtime expectation |
|---|---|---|---|
Verify | Integration setup and verification actions | POST /verify | Fast validation of auth and connectivity |
Provision | Visitor check-in (or configured pre-check-in flow) | POST /provision | Synchronous and blocking |
Activate | Post-check-in activation stage | POST /activate | Asynchronous and non-blocking |
Deprovision | Check-out, expiry, or callback | POST /deprovision | Asynchronous and non-blocking |
Provisioning
Provision is the critical gating call in the ACI lifecycle. If Provision fails, Sine cannot complete normal credential issuance for that visit.
Security principle: Credentials must be provisioned inactive
Credentials provisioned to your ACS must not grant access until explicitly activated. This enforces a critical security boundary:
- A visitor checks in and is assigned a credential.
- Sine performs approval checks: notifying and waiting for confirmation from the visitor's host (the employee or staff member they are booked to meet), applying any site security validations, and running background checks if configured.
- Only after Sine confirms approval does it call Activate.
- Activate is the authoritative gate for when physical access is actually granted.
If your ACS cannot represent inactive/disabled credentials, your integration must track activation state separately and reject reader/turnstile requests until Activate has been called. Do not allow access based on provisioned state alone.
Trigger and intent
- Called when Sine needs to create or attach a credential for a specific visit.
- Must return correlation identifiers used by later Activate and Deprovision calls.
Integration responsibilities
- Validate authentication and request payload.
- Create or attach the ACS holder/credential record.
- Return PROVISIONED and the required data object.
- Persist enough internal mapping to support idempotent retries.
Implementation notes
- Treat badgeNumber/barcode as possibly pre-existing values.
- For physical and deactivate-only capable integrations, handle reuse safely (match-existing, upsert, or explicit conflict response).
- For digital credentials, generate non-guessable credential values.
Minimum successful response shape
{
"code": "PROVISIONED",
"data": {
"barcode": "<credential-value>",
"accessControlVisitId": "<acs-holder-id>",
"accessControlLocationId": "<optional-acs-location-id>"
}
}Provision flow checkpoints
- Authenticate request and validate required fields.
- Resolve access groups and card/credential handling mode.
- Create or link ACS holder and credential.
- Return ACS correlation IDs and credential identifier.
- Log with visit and correlation IDs (without leaking secrets).
Activation
Activation enables access for an already-provisioned credential.
Why Activation exists: The approval gate
Provisioning creates a credential, but Activation is where Sine grants permission to use it. This two-step design allows Sine to:
- Notify the visitor's host (the employee they are booked to meet) and wait for their approval if required.
- Apply any site security policies or screening checks.
- Cancel the access grant if approval is not given - in this case, no Activate call is made.
- Enforce a clear audit trail of who approved access, and when.
Your endpoint must respect this: a provisioned but non-activated credential should not grant physical access regardless of whether it exists in the ACS. Activation is the commitment to access.
Trigger and intent
- Called after Provision when Sine transitions the visit into an active state.
- Uses previously issued identifiers (accessControlVisitId, badgeNumber/barcode, and optional location/credential metadata).
Integration responsibilities
- Resolve the target holder/credential in ACS using supplied identifiers.
- Enable access rights for the visit window and configured access groups.
- Return ACTIVATED for successful or idempotently-already-active outcomes.
Operational behaviour
- Activation is asynchronous from Sine's lifecycle perspective.
- Failures are operationally significant, but do not retroactively block a completed check-in.
- Your endpoint should remain idempotent for duplicate activation calls.
Activation flow checkpoints
- Validate identity and correlation fields.
- Resolve holder/credential relation in ACS.
- Apply activation (or no-op if already active).
- Return success and structured logs.
Deprovisioning
Deprovision removes or disables access at the end of the visit lifecycle.
Trigger and intent
- Called on check-out, expiry, or callback-driven checkout.
- Can be invoked in standard mode or deactivate-only mode.
Modes
Mode | Request signal | Expected behaviour |
|---|---|---|
Standard | deactivateOnly absent or false | Apply normal revoke/deprovision behaviour |
Deactivate-only | deactivateOnly=true | Disable access while preserving reusable/audit records |
Integration responsibilities
- Handle both modes independent of credential type.
- Treat repeated deprovision calls as idempotent.
- If records are already inactive/removed, return success rather than hard failure where safe.
Deprovision flow checkpoints
- Validate auth and correlation identifiers.
- Determine mode from query flag (deactivateOnly).
- Execute revoke/deactivate logic in ACS.
- Return DEPROVISIONED and emit traceable logs.
Error and Retry Behaviour
Implementations should separate permanent request errors from transient operational failures so Sine can react correctly.
Recommended status mapping
Scenario | HTTP status | Response guidance |
|---|---|---|
Invalid payload or field constraints | 400 | Return validation details in message |
Missing or invalid API key | 401 | Return auth failure message |
Auth valid but operation not permitted | 403 | Return permission/context error |
Identifier conflict or duplicate that cannot be resolved | 409 (or 400 if no conflict status support) | Explain conflict and expected remediation |
Downstream ACS unavailable/timeout | 500 / 502 / 503 / 504 | Return transient failure message |
Retry design guidance
- Provision: treat as blocking and fail-fast on non-recoverable errors.
- Activate/Deprovision: design for retries and duplicate delivery.
- Use idempotent handlers so repeated requests do not create duplicate holders, duplicate cards, or inconsistent access state.
- Reuse stable keys (visitId, accessControlVisitId, badgeNumber) to deduplicate safely.
Idempotency rules of thumb
- "Already exists" during Provision should be handled deterministically, not as an unclassified 500.
- "Already active" during Activate should return success-equivalent behaviour.
- "Already deprovisioned/deactivated" during Deprovision should return success-equivalent behaviour.
- Never rely on a single delivery attempt for Activate/Deprovision.
Structured error response
Use this shape for non-success responses:
{
"code": "REQUEST_FAILED_ERROR",
"message": "Human-readable failure description"
}Keep messages actionable for operators - include what failed, where it failed, and whether a retry is likely to succeed.
Endpoint Implementation Reference
This section describes the full request and response contract for each endpoint your integration must expose. All lifecycle endpoints use POST unless otherwise stated.
Common Request Headers
All lifecycle requests from Sine include:
Header | Value |
|---|---|
Authorization | Your configured API key |
Content-Type | application/json |
Validate the Authorization header on every request. Return 401 if the key is missing or does not match.
Overview of Required Endpoints
Endpoint | Method | Required | Purpose |
|---|---|---|---|
/verify | POST | Yes | Validate API key and connectivity during setup |
/provision | POST | Yes | Create or attach a credential for a visit |
/activate | POST | Yes | Enable access for a provisioned credential |
/deprovision | POST | Yes | Revoke or deactivate access at end of visit |
/access-groups | GET | Optional | Return available access groups for Sine configuration UI |
The paths shown above are illustrative. Your integration can use any URL paths - the actual endpoints are registered in your integration configuration. See Section 6 for setup details.
Endpoint Specifications
Verify
Purpose: Confirms that Sine can reach your endpoint and that the API key is valid. Called during integration setup and when administrators test connectivity.
Request body:
{
"externalId": "your-site-reference"
}Field | Type | Required | Description |
|---|---|---|---|
externalId | string | No | A site-specific reference string configured in Sine. Present only if configured. |
Success response (200 OK):
{
"code": "SUCCESS"
}Notes:
- Keep this endpoint lightweight - it is used as a connectivity check during setup.
- No ACS operations are expected. Validate the API key and return success.
Provision
Purpose: Creates or attaches a credential in your ACS for a specific visit. The credential must be created in an inactive or disabled state - access is not enabled until Activate is called.
Request body:
{
"visitId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"siteId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"externalId": "your-site-reference",
"credentialType": "digital",
"validFrom": "2026-05-25T09:00:00.000Z",
"validTo": "2026-05-25T17:00:00.000Z",
"visitor": {
"firstName": "Jane",
"lastName": "Smith",
"email": "[email protected]",
"mobile": "+61400000000",
"photoURL": "https://signed-url.example.com/photo.jpg"
},
"visitorType": {
"id": "vt-001",
"name": "Contractor"
},
"company": {
"id": "co-001",
"name": "ACME Corp"
},
"host": {
"id": "h-001",
"firstName": "Alex",
"lastName": "Johnson",
"email": "[email protected]"
},
"accessGroups": [
"782b7f6e-ef97-4242-9c58-81cc0e3af04d"
],
"checkoutUrl": "https://app.sine.co/callbacks/checkout/{jwt}?teamId=xyz"
}Request field reference:
Field | Type | Required | Description |
|---|---|---|---|
visitId | UUID v4 | Yes | Unique Sine identifier for this visit. Use as your primary idempotency key. |
siteId | UUID v4 | Yes | Sine identifier for the site/location. |
externalId | string | No | Integration-specific reference string configured in Sine. Max 256 characters. |
credentialType | string | No | digital, physical, or virtual. See Credential Types |
validFrom | string | Yes | ISO 8601 UTC. Start of the credential validity window. |
validTo | string | Yes | ISO 8601 UTC. End of the credential validity window. |
visitor | object | Yes | Visitor details. |
visitor.firstName | string | Yes | Visitor's first name. |
visitor.lastName | string | Yes | Visitor's last name. |
visitor.email | string | No | Visitor's email address. |
visitor.mobile | string | No | Visitor's phone number in E.164 format (e.g. +61400000000). |
visitor.photoURL | string | No | Signed, time-limited URL to the visitor's photo. Do not persist beyond operational need. |
visitorType | object | No | Visitor classification. Includes id and name. |
company | object | No | Visitor's company. Includes id and name. |
host | object | No | The employee the visitor is meeting. Includes id, firstName, lastName, email, mobile, hostGroup, hostGroupName. |
accessGroups | array of strings | No | ACS access group IDs to apply to this credential. See Access Groups . |
checkoutUrl | string | No | Callback URL your ACS should call when the visitor badges out at an exit reader. Includes an authentication token. See Check-Out Flow - ACS Initiated. |
badgeNumber | string | No | Pre-assigned card number. Present for physical credential flows. See Check-In Flow - Physical Card Credential . |
zoneId | string | No | Legacy field. Zone identifier when zone feature is enabled. |
zoneDetails | object | No | Legacy field. Zone id, name, and externalId when zone feature is enabled. |
Success response (201 Created):
{
"code": "PROVISIONED",
"data": {
"barcode": "2345v34sdv",
"accessControlVisitId": "1234",
"accessControlLocationId": "6789"
}
}Response field reference:
Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes | Must be PROVISIONED. |
data.barcode | string | Yes | The credential value (QR code data or card number). For digital credentials, must be unpredictable - see notes below. |
data.accessControlVisitId | string | Yes | Your ACS-side identifier for this visit/holder. Sine stores this and returns it in all subsequent Activate and Deprovision calls. |
data.accessControlLocationId | string | No | Optional ACS location partition key. Stored and echoed back by Sine in later calls. |
data.destinationName | string | No | Display label for the pass (e.g. floor or room name). Used on badge printing or QR display. |
data.destinationId | string | No | Identifier for the destination. |
Notes:
- Provision is synchronous and blocking. Sine waits for the response before displaying or printing the credential. Slow or failed responses will delay or block check-in.
- The barcode returned here becomes the badgeNumber Sine sends in all subsequent Activate and Deprovision calls.
- For digital credentials, barcode must be non-sequential and non-guessable. Do not use card numbers, sequential integers, or visitor IDs.
- For physical credentials, Sine sends the pre-assigned card number as badgeNumber in the request. Echo it back as barcode in the response.
- photoURL values are signed and ephemeral. Do not store them beyond the current request context.
Activate
Purpose: Enables access for a previously provisioned credential. Called after Sine has completed its approval checks for the visit.
Request body:
{
"visitId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"siteId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"externalId": "your-site-reference",
"credentialType": "digital",
"validFrom": "2026-05-25T09:00:00.000Z",
"validTo": "2026-05-25T17:00:00.000Z",
"accessControlVisitId": "1234",
"accessControlLocationId": "6789",
"badgeNumber": "2345v34sdv",
"accessGroups": [
"782b7f6e-ef97-4242-9c58-81cc0e3af04d"
]
}Request field reference:
Field | Type | Required | Description |
|---|---|---|---|
visitId | UUID v4 | Yes | Visit identifier from Provision. |
siteId | UUID v4 | Yes | Sine site identifier. |
externalId | string | No | Integration reference string. Same value as Provision. |
credentialType | string | No | Credential type. Same value as Provision. |
accessControlVisitId | string | Yes | The ACS identifier you returned in the Provision response. |
accessControlLocationId | string | No | The ACS location identifier you returned in the Provision response, if applicable. |
badgeNumber | string | Yes | The credential value (barcode) returned in the Provision response. |
accessGroups | array of strings | No | Access group IDs to apply. May differ from Provision if updated by an administrator. |
Success response (200 OK):
{
"code": "ACTIVATED"
}Notes:
- Activate is asynchronous from Sine's perspective. Sine does not hold the check-in flow open waiting for the outcome.
- Your endpoint must be idempotent. If the credential is already active, return ACTIVATED rather than an error.
- Use accessControlVisitId and/or badgeNumber to resolve the target credential. Do not rely solely on visitId.
Deprovision
Purpose: Revokes or disables a credential at the end of the visit lifecycle. Standard behaviour removes the credential entirely. Deactivate-only mode preserves the record.
Request body:
{
"visitId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"siteId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"externalId": "your-site-reference",
"credentialType": "digital",
"validFrom": "2026-05-25T09:00:00.000Z",
"validTo": "2026-05-25T17:00:00.000Z",
"accessControlVisitId": "1234",
"accessControlLocationId": "6789",
"badgeNumber": "2345v34sdv",
"accessGroups": [
"782b7f6e-ef97-4242-9c58-81cc0e3af04d"
]
}The request body fields are identical to Activate. The deactivate-only mode is signalled via a query parameter:
POST /deprovision?deactivateOnly=trueParameter | Type | Location | Description |
|---|---|---|---|
deactivateOnly | boolean | Query string | When true, disable access without destructive deletion. Absent or false means full deprovision. |
Request field reference:
Field | Type | Required | Description |
|---|---|---|---|
visitId | UUID v4 | Yes | Visit identifier from Provision. |
siteId | UUID v4 | Yes | Sine site identifier. |
externalId | string | No | Integration reference string. |
credentialType | string | No | Credential type. |
accessControlVisitId | string | Yes | The ACS identifier from the Provision response. |
accessControlLocationId | string | No | The ACS location identifier from the Provision response, if applicable. |
badgeNumber | string | Yes | The credential value from the Provision response. |
accessGroups | array of strings | No | Access group IDs associated with this visit. |
Success response (200 OK):
{
"code": "DEPROVISIONED"
}Notes:
- Deprovision is asynchronous from Sine's perspective. Sine marks the visitor as checked out regardless of the outcome.
- Your endpoint must be idempotent. If the credential is already revoked or does not exist, return DEPROVISIONED rather than an error.
- When deactivateOnly=true, preserve the cardholder and credential record in the ACS. See Physical Card Inventory and Asset Management for context.
Access Groups Endpoint
The Access Groups endpoint is optional. When configured, it allows Sine administrators to browse and assign access groups from your ACS directly within Sine's integration settings.
Method: GET
Example request:
GET https://your-endpoint.example.com/access-groups?externalId=xyzQuery parameters:
Parameter | Type | Description |
|---|---|---|
externalId | string | Integration reference string. Present if configured. |
nameIncludes | string | Case-insensitive substring filter on group name. Optional. |
id | string (repeatable) | Fetch by exact group ID. Multiple id params may be sent. id and nameIncludes are never sent together. |
after | string | Pagination cursor from a previous nextLink response. |
Success response (200 OK):
{
"results": [
{ "name": "Level 1", "id": "782b7f6e-ef97-4242-9c58-81cc0e3af04d" },
{ "name": "Level 2", "id": "5bdd1fa4-8ad7-4fdf-8893-30bd65c28bcf" }
],
"nextLink": "https://your-endpoint.example.com/access-groups?externalId=xyz&after=5bdd1fa4-8ad7-4fdf-8893-30bd65c28bcf"
}Response field reference:
Field | Type | Required | Description |
|---|---|---|---|
results | array | Yes | List of access groups. Each entry must include id and name. |
results[].id | string | Yes | Opaque ACS identifier for the group. This is the value sent in accessGroups on lifecycle requests. |
results[].name | string | Yes | Human-readable group name shown in the Sine interface. |
nextLink | string | No | Full URL for the next page of results. Omit when there are no further pages. |
Notes:
- nextLink must be a directly callable URL - Sine follows it as-is.
- If your ACS does not support filtering, return all groups regardless of query parameters.
- You may set Cache-Control: max-age=<seconds> on the response. Sine will honour client-side caching for the specified duration. Cache is invalidated on API key change, external ID change, or Verify/Provision errors.
Versioning and Compatibility
The ACI integration contract follows an additive compatibility model:
- Sine may add new optional fields to request bodies in future updates. Your integration must ignore unknown fields gracefully.
- Sine will not remove or rename existing required fields without a versioned deprecation path.
- Your response payloads should include at minimum the documented required fields. Sine ignores any additional fields you include.
Practical guidance:
- Use permissive JSON parsing - ignore unknown keys rather than hard-failing.
- Do not reject requests that contain new or unexpected fields.
- Validate that all required response fields are present before returning a success code from your own handlers.