@lstrihic/codekey
v2.0.1
Published
TypeScript client for code-key.com API
Maintainers
Readme
@lstrihic/codekey
TypeScript client for the code-key.com door access control API.
Installation
npm install @lstrihic/codekeyRequirements
- Node.js 18+
- TypeScript 5+ (for TypeScript projects)
Quick Start
import { CodeKeyClient } from '@lstrihic/codekey'
const client = new CodeKeyClient(
process.env.CODEKEY_USERNAME!,
process.env.CODEKEY_PASSWORD!
)
// List all users
const users = await client.listUsersParsed('account-id')
console.log(users)
// Get single user
const user = await client.getUser('account-id', 'user-id')
// Add new guest
await client.addOrUpdateUser({
id: 'account-id',
userStatus: '0',
userType: '1',
name: 'Guest Name',
device: '15666322',
dateStart: '24.10.2025',
timeStart: '05:50',
dateEnd: '26.10.2025',
timeEnd: '20:30',
code: '123456',
note: '',
mailTrigger: 'false',
otp: 'false',
openAPILink: 'uuid',
importID: '0',
})AI Agent Usage Guide
This package only manages normal time-bound CodeKey users. Do not use, add, or recreate private/permanent user functionality.
Hard Rules
- Never call private/permanent endpoints:
get_private_users,add_private_job, ordel_job. - Never add public methods named
listPrivateUsers,listPrivateUsersParsed,addPermanentUser, ordeletePermanentUser. - Never hardcode real credentials, session cookies, account IDs, or access codes in application source. Read credentials from environment variables.
- Never log passwords,
PHPSESSIDvalues, or full raw API responses from authenticated requests. - Use
deleteUser()only for users returned bylistUsersParsed()/get_jobs.
Environment Variables
Required variables:
CODEKEY_USERNAMECODEKEY_PASSWORDCODEKEY_ACCOUNT_ID
const client = new CodeKeyClient(
process.env.CODEKEY_USERNAME!,
process.env.CODEKEY_PASSWORD!
)
const accountId = process.env.CODEKEY_ACCOUNT_ID!Safe Normal User Create Flow
Use this flow when an AI agent needs to create a user:
- Get existing normal users with
listUsersParsed(accountId). - Pick a
devicefrom an existing normal user. Do not query private users for devices. - Create the user with
addOrUpdateUser(). - Re-fetch
listUsersParsed(accountId)and find the new user there. - Store the returned
groupUserID; this is required for updates and deletion.
import { randomUUID } from 'node:crypto'
import { CodeKeyClient } from '@lstrihic/codekey'
const client = new CodeKeyClient(
process.env.CODEKEY_USERNAME!,
process.env.CODEKEY_PASSWORD!
)
const accountId = process.env.CODEKEY_ACCOUNT_ID!
const users = await client.listUsersParsed(accountId)
const device = users[0]?.device
if (!device) {
throw new Error('No normal user exists to source a device id from')
}
const name = `Guest ${Date.now()}`
await client.addOrUpdateUser({
id: accountId,
userStatus: '0',
userType: '1',
name,
device,
dateStart: '11.05.2026',
timeStart: '05:50',
dateEnd: '13.05.2026',
timeEnd: '20:30',
code: '123456',
note: '',
mailTrigger: 'false',
otp: 'false',
openAPILink: randomUUID(),
importID: '0',
})
const created = (await client.listUsersParsed(accountId)).find(
(user) => user.name === name
)
if (!created) {
throw new Error('Created user was not found in the normal user list')
}addOrUpdateUser() sends import_id: '0' automatically for new users when editing is omitted. Passing importID: '0' explicitly is still recommended in generated examples because it mirrors the browser request.
Safe Update Flow
Update an existing normal user by passing editing with the existing userID.
await client.addOrUpdateUser({
id: accountId,
userStatus: existing.userStatus,
userType: existing.userType,
name: existing.name,
device: existing.device,
dateStart: '11.05.2026',
timeStart: '05:50',
dateEnd: '13.05.2026',
timeEnd: '20:30',
code: existing.code,
note: '',
mailTrigger: 'false',
otp: 'false',
openAPILink: existing.openAPILink,
editing: existing.userID,
})Safe Delete Flow
Delete only normal users found through listUsersParsed().
const user = (await client.listUsersParsed(accountId)).find(
(entry) => entry.name === name
)
if (user) {
await client.deleteUser({
id: accountId,
groupUserID: user.groupUserID,
})
}Live Test Cleanup Pattern
When an AI agent creates a live user for testing, use a unique name and delete it in finally.
import type { User } from '@lstrihic/codekey'
const name = `TEST_${Date.now()}`
let created: User | undefined
try {
await client.addOrUpdateUser({ ...request, name, importID: '0' })
created = (await client.listUsersParsed(accountId)).find(
(user) => user.name === name
)
} finally {
if (created) {
await client.deleteUser({
id: accountId,
groupUserID: created.groupUserID,
})
}
}Formats
- Dates sent to the API should use
DD.MM.YYYY, for example11.05.2026. - Times sent to the API should use
HH:MM, for example05:50. - The API may return times as
HH:MMorHH:MM:SS; keep them as strings. getUser()handles both JSON and semicolon-delimited responses from CodeKey.
API Reference
Constructor
new CodeKeyClient(username: string, password: string)Creates a new client instance with automatic authentication and session management.
User Management Methods
listUsers(id: string): Promise<Buffer>
Get all users as raw CSV data.
Parameters:
id- Account ID
Returns: Buffer containing CSV response
const rawUsers = await client.listUsers('24E40CAB556911EFA812F2FABB7CF30C')
console.log(rawUsers.toString())listUsersParsed(id: string): Promise<User[]>
Get all users as parsed objects.
Parameters:
id- Account ID
Returns: Array of User objects
const users = await client.listUsersParsed('24E40CAB556911EFA812F2FABB7CF30C')
for (const user of users) {
console.log(`${user.name} - Code: ${user.code}`)
}getUser(id: string, userID: string): Promise<UserInfo>
Get detailed info for a single user as a parsed object. The CodeKey endpoint can return either JSON or the same semicolon-delimited format used by the list endpoint; both are handled.
Parameters:
id- Account IDuserID- User ID
Returns: UserInfo object
const user = await client.getUser('24E40CAB556911EFA812F2FABB7CF30C', '2685015')
console.log(`${user.name}: ${user.dateStart} - ${user.dateEnd}`)getUserRaw(id: string, userID: string): Promise<Buffer>
Get detailed info for a single user as raw JSON data.
Parameters:
id- Account IDuserID- User ID
Returns: Buffer containing JSON response
const rawUser = await client.getUserRaw('24E40CAB556911EFA812F2FABB7CF30C', '2685015')addOrUpdateUser(req: AddOrUpdateUserRequest): Promise<Buffer>
Create or update a temporary user with time restrictions.
Creating a new user: Omit editing. importID defaults to '0', and may also be passed explicitly.
Updating existing user: Set editing to user ID and omit importID
Parameters:
req- AddOrUpdateUserRequest object
Returns: Buffer containing response
// Create new guest
await client.addOrUpdateUser({
id: '24E40CAB556911EFA812F2FABB7CF30C',
userStatus: '0',
userType: '1',
name: 'New Guest',
device: '15666322',
dateStart: '24.10.2025',
timeStart: '05:50',
dateEnd: '26.10.2025',
timeEnd: '20:30',
code: '543543',
note: '',
mailTrigger: 'false',
otp: 'false',
openAPILink: 'uuid',
importID: '0',
})
// Update existing user
await client.addOrUpdateUser({
id: '24E40CAB556911EFA812F2FABB7CF30C',
userStatus: '0',
userType: '1',
name: 'Updated Name',
device: '15666322',
dateStart: '24.10.2025',
timeStart: '05:50',
dateEnd: '30.12.2025',
timeEnd: '20:30',
code: '246811',
note: '',
mailTrigger: 'false',
otp: 'false',
openAPILink: 'uuid',
editing: '2685015',
})Access Control Methods
updateAccessPeriod(req: UpdateAccessPeriodRequest): Promise<Buffer>
Update access date range for a user.
Parameters:
req- UpdateAccessPeriodRequest object
Returns: Buffer containing response
await client.updateAccessPeriod({
id: '24E40CAB556911EFA812F2FABB7CF30C',
groupUserID: 'group-uuid',
dateStart: '24.10.2025',
dateEnd: '28.11.2025',
userID: '2685015',
actionID: '0',
})updateAccessCode(req: UpdateAccessCodeRequest): Promise<Buffer>
Update door access code for a user.
Parameters:
req- UpdateAccessCodeRequest object
Returns: Buffer containing response
await client.updateAccessCode({
id: '24E40CAB556911EFA812F2FABB7CF30C',
groupUserID: 'group-uuid',
newCode: '246810',
userID: '2685015',
actionID: '0',
name: 'test1',
currentCode: '246811',
userType: '1',
})deleteUser(req: DeleteUserRequest): Promise<Buffer>
Delete a temporary guest user.
Parameters:
req- DeleteUserRequest object
Returns: Buffer containing response
await client.deleteUser({
id: '24E40CAB556911EFA812F2FABB7CF30C',
groupUserID: 'group-uuid',
})TypeScript Support
Full TypeScript support with type definitions included.
import type {
User,
UserInfo,
AddOrUpdateUserRequest,
UpdateAccessPeriodRequest,
UpdateAccessCodeRequest,
DeleteUserRequest,
} from '@lstrihic/codekey'Type Definitions
User - Temporary user with time restrictions
interface User {
userID: string
status: string
userType: string
name: string
device: string
dateStart: string
timeStart: string
dateEnd: string
timeEnd: string
code: string
userStatus: string
deviceName: string
createdAt: string
lastAccess: string
groupUserID: string
openAPILink: string
}UserInfo - Detailed user information
interface UserInfo {
id: string
groupUserID: string
userID: string
status?: string
name: string
device?: string
code: string
dateStart: string
timeStart?: string
dateEnd: string
timeEnd?: string
userType: string
note?: string
userStatus?: string
deviceName?: string
lastAccess?: string
openAPILink?: string
actionID: string
active: boolean
createdAt?: Date | string
updatedAt?: Date | string
}Error Handling
import {
AuthenticationError,
RequestError,
ParseError,
} from '@lstrihic/codekey'
try {
await client.listUsers('account-id')
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Login failed')
} else if (error instanceof RequestError) {
console.error('API request failed:', error.statusCode)
} else if (error instanceof ParseError) {
console.error('Response parsing failed')
}
}Error Types:
AuthenticationError- Login or authentication failedRequestError- API request failed (includes statusCode)ParseError- CSV/JSON parsing failed
Features
- Automatic authentication and session management
- Cookie-based session handling with automatic re-authentication
- Promise-based async operations
- Full TypeScript support
- Clean error handling with custom error classes
- CSV parsing for list operations
- JSON parsing for detailed user info
Usage in Next.js
// app/api/users/route.ts
import { CodeKeyClient } from '@lstrihic/codekey'
import { NextResponse } from 'next/server'
export async function GET() {
const client = new CodeKeyClient(
process.env.CODEKEY_USERNAME!,
process.env.CODEKEY_PASSWORD!
)
try {
const users = await client.listUsersParsed(process.env.CODEKEY_ACCOUNT_ID!)
return NextResponse.json(users)
} catch (error) {
return NextResponse.json({ error: 'Failed to fetch users' }, { status: 500 })
}
}License
MIT
Author
Lovro Strihic
