ElmapiCMS JavaScript SDK
JavaScript/TypeScript SDK for the ElmapiCMS Content API, admin APIs, and Project Auth (end-user) APIs.
Install
npm install @elmapicms/js-sdk
Quick Start
import { createClient } from '@elmapicms/js-sdk'
const client = createClient({
baseUrl: 'https://your-instance.example/api',
projectId: 'your-project-uuid',
apiKey: 'your-project-api-token',
})
baseUrl is required (self-hosted instance API root). apiKey is a project Sanctum token from the project’s API tokens settings (sent as Authorization: Bearer … with the project-id header).
Upgrading from 0.4.x? See MIGRATING.md.
API Examples
Project / Collections / Locales
const project = await client.project.get()
const collections = await client.collections.list()
const postsCollection = await client.collections.get('posts')
await client.project.locales.add('tr')
await client.project.locales.setDefault('en')
await client.project.locales.remove('fr')
End-user auth (projectUserAuth)
For password login and session APIs, extend the client with storage for access and refresh tokens (example uses localStorage in the browser):
const client = createClient({
baseUrl: 'https://your-instance.example/api',
projectId: 'your-project-uuid',
apiKey: 'your-project-api-token',
projectUserAuth: {
autoRefresh: true,
tokenStorage: {
getAccessToken: () => localStorage.getItem('elmapi_user_access') ?? undefined,
setAccessToken: (token) =>
token
? localStorage.setItem('elmapi_user_access', token)
: localStorage.removeItem('elmapi_user_access'),
getRefreshToken: () => localStorage.getItem('elmapi_user_refresh') ?? undefined,
setRefreshToken: (token) =>
token
? localStorage.setItem('elmapi_user_refresh', token)
: localStorage.removeItem('elmapi_user_refresh'),
clear: () => {
localStorage.removeItem('elmapi_user_access')
localStorage.removeItem('elmapi_user_refresh')
},
},
},
})
User Login (password)
import { AuthorizationError } from '@elmapicms/js-sdk'
try {
await client.signInWithPassword({
email: 'user@example.com',
password: 'super-secure-password',
})
console.log(client.getSession())
} catch (e) {
if (e instanceof AuthorizationError && e.details && typeof e.details === 'object' && 'verification_token' in e.details) {
const { verification_token } = e.details as { verification_token?: string }
}
}
Email verification: The API may issue verification_token (sign-up when required, blocked login 403 on AuthorizationError.details, or resendVerificationEmail). Your app owns templates and delivery; confirm with confirmVerificationEmail.
Content
const posts = await client.content.list('posts', {
state: 'published',
locale: 'en',
where: { title: { like: 'hello' } },
sort: 'created_at:desc',
paginate: 20,
})
const entry = await client.content.get('posts', 'entry-uuid')
const created = await client.content.create('posts', {
locale: 'en',
state: 'draft',
data: { title: 'My post' },
})
await client.content.update('posts', created.uuid ?? created.data?.uuid, {
data: { title: 'Updated title' },
})
await client.content.publish('posts', 'entry-uuid')
await client.content.unpublish('posts', 'entry-uuid')
await client.content.discardDraft('posts', 'entry-uuid')
const versions = await client.content.versions.list('posts', 'entry-uuid')
Saves (update / patch / bulkUpdate) do not change publish state. Use publish / unpublish / versions.* / discardDraft explicitly.
state: 'published' on list / get returns the published snapshot, not live draft field values. Use state: 'draft' for draft/preview reads.
Assets
const assets = await client.assets.list({ type: 'image', paginate: 50 })
const uploaded = await client.assets.upload(file, { alt_text: 'Hero' })
Webhooks
const hooks = await client.webhooks.list()
await client.webhooks.create({
name: 'Notify',
url: 'https://example.com/hook',
events: ['content.created'],
sources: ['api', 'cms'],
})
Error Handling
All errors extend ElmapiError. Specific subclasses include AuthenticationError, AuthorizationError, NotFoundError, ValidationError, RateLimitError, ServerError, NetworkError, and TimeoutError.
License
MIT