Manage the lifecycle of API tokens used to authenticate with the Salami Gateway API. Create tokens with specific scopes, monitor usage, set expiration dates, and revoke compromised tokens.
Salami uses Laravel Sanctum for API token authentication. Tokens are personal access tokens tied to a user account and can be scoped to specific API modules.
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/account/tokens |
Create a new API token |
GET |
/api/account/tokens |
List all tokens |
POST |
/api/account/tokens/test |
Test token validity |
DELETE |
/api/account/tokens/{id} |
Revoke a token |
Token management endpoints require authentication via an existing valid token or session authentication.
Generate a new API token with specified abilities (scopes).
Endpoint: POST /api/account/tokens
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Descriptive token name |
abilities |
array | Yes | Array of scope strings |
expires_at |
string | No | Expiration date (YYYY-MM-DD), null for no expiration |
Request:
curl -X POST \
https://yourtenant.salami.dgl.co.ke/api/account/tokens \
-H 'Authorization: Bearer EXISTING_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Production Server",
"abilities": ["payments:read", "payments:write", "sms:write"],
"expires_at": "2026-12-31"
}'
Response:
{
"success": true,
"data": {
"token_id": 15,
"name": "Production Server",
"plain_text_token": "3|laravel_sanctum_abc123def456ghi789jkl012mno345pqr678stu901vwx",
"abilities": ["payments:read", "payments:write", "sms:write"],
"expires_at": "2026-12-31T23:59:59Z",
"created_at": "2026-03-29T18:00:00Z"
},
"message": "Token created successfully. Copy the token now - it will not be shown again."
}
Critical: The
plain_text_tokenis returned only once at creation time. Store it securely. If lost, revoke the token and create a new one.
{
"name": "Admin Full Access",
"abilities": ["*"]
}
{
"name": "Reporting Dashboard",
"abilities": ["payments:read", "sms:read", "etims:read", "kra:apps", "kra:checkers"]
}
{
"name": "KRA Integration Server",
"abilities": [
"kra:apps", "kra:checkers", "kra:payments",
"kra:compliance", "kra:registration", "kra:returns"
]
}
Retrieve all tokens for the authenticated user.
Endpoint: GET /api/account/tokens
Request:
curl -X GET \
https://yourtenant.salami.dgl.co.ke/api/account/tokens \
-H 'Authorization: Bearer YOUR_API_TOKEN'
Response:
{
"success": true,
"data": [
{
"id": 15,
"name": "Production Server",
"abilities": ["payments:read", "payments:write", "sms:write"],
"last_used_at": "2026-03-29T17:45:00Z",
"usage_count": 1247,
"expires_at": "2026-12-31T23:59:59Z",
"revoked_at": null,
"status": "active",
"created_at": "2026-03-29T18:00:00Z"
},
{
"id": 12,
"name": "Mobile App",
"abilities": ["payments:read", "sms:read"],
"last_used_at": "2026-03-28T09:30:00Z",
"usage_count": 456,
"expires_at": null,
"revoked_at": null,
"status": "active",
"created_at": "2026-03-15T10:00:00Z"
},
{
"id": 8,
"name": "Old Dev Token",
"abilities": ["*"],
"last_used_at": "2026-02-15T12:00:00Z",
"usage_count": 89,
"expires_at": "2026-03-01T00:00:00Z",
"revoked_at": null,
"status": "expired",
"created_at": "2026-01-01T10:00:00Z"
}
]
}
| Status | Description |
|---|---|
active |
Token is valid and can be used |
expired |
Token has passed its expiration date |
revoked |
Token has been manually revoked |
| Field | Type | Description |
|---|---|---|
id |
integer | Token ID |
name |
string | Descriptive name |
abilities |
array | Granted scopes |
last_used_at |
string/null | Last API request timestamp |
usage_count |
integer | Total number of API requests made |
expires_at |
string/null | Expiration timestamp (null = no expiry) |
revoked_at |
string/null | Revocation timestamp (null = not revoked) |
status |
string | active, expired, or revoked |
created_at |
string | Creation timestamp |
Note: The actual token value is never returned in list responses for security.
Verify that a token is valid and check its abilities.
Endpoint: POST /api/account/tokens/test
Request:
curl -X POST \
https://yourtenant.salami.dgl.co.ke/api/account/tokens/test \
-H 'Authorization: Bearer TOKEN_TO_TEST' \
-H 'Accept: application/json'
Valid Token Response:
{
"success": true,
"data": {
"valid": true,
"token_id": 15,
"name": "Production Server",
"user": "admin@company.co.ke",
"abilities": ["payments:read", "payments:write", "sms:write"],
"expires_at": "2026-12-31T23:59:59Z",
"usage_count": 1248,
"last_used_at": "2026-03-29T18:05:00Z"
},
"message": "Token is valid"
}
Invalid/Expired Token Response:
{
"success": false,
"message": "Unauthenticated.",
"error": "unauthenticated"
}
Permanently invalidate a token. Revoked tokens cannot be restored.
Endpoint: DELETE /api/account/tokens/{id}
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer | Yes | Token ID to revoke |
Request:
curl -X DELETE \
https://yourtenant.salami.dgl.co.ke/api/account/tokens/15 \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-H 'Accept: application/json'
Response:
{
"success": true,
"data": {
"token_id": 15,
"name": "Production Server",
"revoked_at": "2026-03-29T18:10:00Z"
},
"message": "Token revoked successfully"
}
Warning: Revocation is immediate and permanent. Any application using this token will immediately lose access.
See Account Scopes for the complete scopes reference.
Summary:
| Scope | Module | Description |
|---|---|---|
* |
All | Full access to all endpoints |
payments:read |
Payments | View transactions, balances |
payments:write |
Payments | Create transactions, send money |
payments:callback |
Payments | Handle provider callbacks |
sms:read |
SMS | View messages, inbox/outbox |
sms:write |
SMS | Send SMS messages |
sms:sync |
SMS | Sync from mobile apps |
sms:receive |
SMS | Receive incoming messages |
etims:read |
eTIMS | View sales, purchases, items |
etims:write |
eTIMS | Submit sales, manage items |
etims:callback |
eTIMS | Handle KRA callbacks |
kra:apps |
KRA | Manage KRA app configurations |
kra:checkers |
KRA | PIN validation, lookups |
kra:payments |
KRA | PRN generation |
kra:compliance |
KRA | TCC applications |
kra:registration |
KRA | PIN registration |
kra:returns |
KRA | Tax return filing |
A token with ["*"] abilities bypasses all scope checks and has access to every endpoint.
Scopes are enforced by the CheckTokenScopes middleware. When a request arrives:
* is present, access is granted403 response is returnedCreated (plain text shown once)
|
v
Active (in use, usage_count incrementing)
|
+---> Expired (past expires_at date)
|
+---> Revoked (manually invalidated)
| Practice | Recommendation |
|---|---|
| Token naming | Use descriptive names: "Production POS", "Staging Mobile App" |
| Expiration | Set 90-day expiration for production tokens |
| Scope assignment | Follow principle of least privilege |
| Rotation | Create a new token before revoking the old one |
| Monitoring | Review usage_count and last_used_at regularly |
| Incident response | Revoke immediately if a token is compromised |
| Storage | Use environment variables, never hardcode tokens |
| Code | Description |
|---|---|
200 |
Success |
201 |
Token created successfully |
401 |
Not authenticated |
403 |
Insufficient permissions |
404 |
Token not found |
422 |
Validation error (missing name or abilities) |
Back to: Getting Started | Account Scopes