@axid-dev/types
v0.1.0
Published
TypeScript types for the axid bot REST API. Auto-generated from the OpenAPI spec — autocomplete + compile-time validation for /api/v1 endpoints, the 11 stable block schemas, and error codes.
Maintainers
Readme
@axid-dev/types
TypeScript types for the axid bot REST API. Auto-generated from the OpenAPI spec — autocomplete + compile-time validation for /api/v1 endpoints, the 11 stable block schemas, and error codes.
pnpm add -D @axid-dev/types
# or
npm install --save-dev @axid-dev/typesWhy
Without types, every fetch returns any and every block prop is a runtime gamble:
const res = await fetch('https://axid.app/api/v1/channels/CID/messages', {
method: 'POST',
body: JSON.stringify({
content_json: {
/* ??? */
},
}),
});
const data = await res.json(); // anyWith @axid-dev/types:
import type { SendMessageRequest, SendMessageResponse, AlertBannerBlock } from '@axid-dev/types';
const banner: AlertBannerBlock = {
text: 'Production outage in us-east-1.',
variant: 'critical', // ← TS error: '"critical"' is not assignable to '"info" | "warning" | "success" | "error"'
};Quick reference
Common imports — flat names, no namespace digging:
import type {
// Endpoint request/response
SendMessageRequest,
SendMessageResponse,
ListMessagesQuery,
ListMessagesResponse,
CreateAgentRequest,
CreateAgentResponse,
// Resources
Message,
Channel,
User,
Workspace,
Pagination,
// Blocks (11 stable)
Block,
TextBlock,
HeadingBlock,
AlertBannerBlock,
ButtonGroupBlock,
LinearIssueCardBlock,
// ...
// Block helpers
UrlButton,
ActionIdButton,
RichTextInput,
// Errors
ErrorCode,
ApiError,
} from '@axid-dev/types';For operations not surfaced as named aliases (the long tail beyond ~13 core endpoints), reach into the namespaces:
import type { operations, components } from '@axid-dev/types';
type ListWorkspaceMembersResponse =
operations['listWorkspaceMembers']['responses'][200]['content']['application/json'];
type DmConversation = components['schemas']['DmConversation'];Examples
Send a plain-text message
import type { SendMessageRequest, SendMessageResponse } from '@axid-dev/types';
const body: SendMessageRequest = { content: 'Hello from my bot 👋' };
const res = await fetch(`https://axid.app/api/v1/channels/${channelId}/messages`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AXID_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
const json = (await res.json()) as SendMessageResponse;
console.log('posted', json.data?.id);Send a block message
import type { SendMessageRequest, AlertBannerBlock, LinearIssueCardBlock } from '@axid-dev/types';
const banner: AlertBannerBlock = {
text: 'Production outage in progress — us-east-1 affected.', // markdown string OK
variant: 'error',
actionLabel: 'View runbook',
actionUrl: 'https://runbooks.example.com/api-down',
};
const issueCard: LinearIssueCardBlock = {
id: 'AXD-284',
url: 'https://linear.app/axid/issue/AXD-284',
title: 'Thread auto-naming fails on CJK',
state: { name: 'In progress', tone: 'blue' },
};
const body: SendMessageRequest = {
content: 'Production outage — AXD-284',
content_json: {
type: 'doc',
content: [
{
type: 'block_alert_banner',
attrs: { blockName: 'alert_banner', props: banner, version: 1 },
},
{
type: 'block_linear_issue_card',
attrs: { blockName: 'linear_issue_card', props: issueCard, version: 1 },
},
],
},
};Narrow a Block union
import type { Block } from '@axid-dev/types';
function summarize(node: Block): string {
switch (node.type) {
case 'block_alert_banner':
return `[${node.attrs.props.variant}] alert`; // ← variant narrowed to "info" | "warning" | "success" | "error"
case 'block_button_group':
return `${node.attrs.props.buttons.length} buttons`;
case 'block_linear_issue_card':
return `Linear ${node.attrs.props.id}`;
default:
return node.type;
}
}Handle button XOR
import type { UrlButton, ActionIdButton, ButtonGroupBlock } from '@axid-dev/types';
const urlBtn: UrlButton = {
label: 'View issue',
url: 'https://linear.app/axid/issue/AXD-284',
style: 'primary',
};
const actionBtn: ActionIdButton = {
label: 'Approve deploy',
actionId: 'approve_deploy',
style: 'secondary',
};
const block: ButtonGroupBlock = { buttons: [urlBtn, actionBtn] };
// ❌ TS error — both url and actionId on one button:
// const bad: UrlButton = { label: 'x', url: 'https://...', actionId: 'y' };Check error codes
import type { ApiError, ErrorCode } from '@axid-dev/types';
const res = await fetch(/* ... */);
if (!res.ok) {
const err = (await res.json()) as ApiError;
// err.error.code autocompletes with known stable codes
if (err.error.code === 'rate_limited') {
const retryAfter = res.headers.get('Retry-After');
// ... back off ...
}
}Authentication
API keys are issued from Workspace Settings → API Keys in the axid app. Send as a Bearer header:
Authorization: Bearer axid_live_<your_key>Full guide: axid.gitbook.io/docs.
Versioning
@axid-dev/types follows semver tied to the OpenAPI feature level (FL):
| Change | Bump | | ----------------------------------------------------------------------------------- | --------- | | API breaking change (FL major bump, required field added, enum value removed) | major | | API additive change (new endpoint, new block, new optional field, enum value added) | minor | | Alias added (new helper type) | minor | | Alias signature changed | major | | Generator tool update with no output change | patch | | Docstring / README / changelog | patch |
Current FL: 5. The version of @axid-dev/types and the FL are not 1:1 — the package version tracks alias surface stability, not the API itself.
Not in scope (0.1.0)
- Runtime helpers — block builders, type guards, validators. Coming in 0.2.0 if needed.
- SDK client —
axid.messages.send(...)style. Tracked separately as@axid-dev/sdk. - JavaScript-only consumers —
@axid-dev/typesonly ships.d.ts+ an empty.jsbundle.
Updating
The types are regenerated from docs/api/openapi.yaml on every PR that touches the yaml (CI gate). If the published version is behind, run:
pnpm --filter @axid-dev/types generate
pnpm --filter @axid-dev/types buildLinks
License
MIT.
