Skip to content

JavaScript Examples

These examples demonstrate how to use the Tailwind API with JavaScript and TypeScript.

Setup

// No additional dependencies needed - fetch is built into Node.js 18+
const API_URL = 'https://api-v1.tailwind.ai';
const API_KEY = process.env.TAILWIND_API_KEY;
const headers = {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
};

List Accounts

async function listAccounts() {
const response = await fetch(`${API_URL}/v1/accounts`, { headers });
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const { data } = await response.json();
return data.accounts;
}
// Usage
const accounts = await listAccounts();
console.log('Accounts:', accounts);

List Boards

async function listBoards(accountId) {
const response = await fetch(
`${API_URL}/v1/accounts/${accountId}/boards`,
{ headers }
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const { data } = await response.json();
return data.boards;
}
// Usage
const boards = await listBoards('acc_123456');
console.log('Boards:', boards);

Create and Schedule a Post

async function createPost(accountId, postData) {
const response = await fetch(
`${API_URL}/v1/accounts/${accountId}/posts`,
{
method: 'POST',
headers,
body: JSON.stringify(postData)
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.error?.message || 'Failed to create post');
}
const { data } = await response.json();
return data.post;
}
// Usage - Create a scheduled post
const post = await createPost('acc_123456', {
mediaUrl: 'https://example.com/my-image.jpg',
title: 'Amazing Recipe',
description: 'Try this delicious recipe! #recipes #cooking',
url: 'https://myblog.com/recipe',
boardId: 'board_789',
altText: 'A colorful plate of food',
sendAt: '2024-01-20T14:00:00Z'
});
console.log('Created post:', post.id);
console.log('Status:', post.status);

Create a Draft Post

// Omit sendAt to create a draft
const draft = await createPost('acc_123456', {
mediaUrl: 'https://example.com/my-image.jpg',
title: 'Draft for Review',
description: 'I will schedule this later',
boardId: 'board_789'
});
console.log('Draft created:', draft.id);
// draft.status will be 'draft'

Schedule a Draft

async function schedulePost(accountId, postId, sendAt) {
const response = await fetch(
`${API_URL}/v1/accounts/${accountId}/posts/${postId}/schedule`,
{
method: 'POST',
headers,
body: JSON.stringify({ sendAt })
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.error?.message || 'Failed to schedule post');
}
const { data } = await response.json();
return data.post;
}
// Usage
const scheduled = await schedulePost(
'acc_123456',
'post_abc123',
'2024-01-25T09:00:00Z'
);
console.log('Scheduled for:', new Date(scheduled.sendAt * 1000));

List Posts with Filtering

async function listPosts(accountId, options = {}) {
const params = new URLSearchParams();
if (options.status) params.set('status', options.status);
if (options.limit) params.set('limit', options.limit.toString());
if (options.cursor) params.set('cursor', options.cursor);
if (options.startDate) params.set('startDate', options.startDate);
if (options.endDate) params.set('endDate', options.endDate);
const url = `${API_URL}/v1/accounts/${accountId}/posts?${params}`;
const response = await fetch(url, { headers });
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const { data } = await response.json();
return {
posts: data.posts,
cursor: data.cursor
};
}
// List queued posts (default)
const queued = await listPosts('acc_123456');
console.log('Queued posts:', queued.posts.length);
// List drafts
const drafts = await listPosts('acc_123456', { status: 'draft' });
console.log('Drafts:', drafts.posts.length);
// List sent posts in a date range
const sent = await listPosts('acc_123456', {
status: 'sent',
startDate: '2024-01-01T00:00:00Z',
endDate: '2024-01-31T23:59:59Z',
limit: 100
});
console.log('Sent in January:', sent.posts.length);

Delete a Post

async function deletePost(accountId, postId) {
const response = await fetch(
`${API_URL}/v1/accounts/${accountId}/posts/${postId}`,
{
method: 'DELETE',
headers
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.error?.message || 'Failed to delete post');
}
return true;
}
// Usage
await deletePost('acc_123456', 'post_abc123');
console.log('Post deleted');

Complete Example: Bulk Scheduler

/**
* Schedule multiple posts with a delay between each
*/
async function bulkSchedule(accountId, posts) {
const results = [];
for (const postData of posts) {
try {
const post = await createPost(accountId, postData);
results.push({ success: true, post });
console.log(`Scheduled: ${post.id}`);
// Wait 200ms between requests to avoid rate limits
await new Promise(resolve => setTimeout(resolve, 200));
} catch (error) {
results.push({ success: false, error: error.message, data: postData });
console.error(`Failed:`, error.message);
}
}
return results;
}
// Usage
const postsToSchedule = [
{
mediaUrl: 'https://example.com/image1.jpg',
title: 'Post 1',
description: 'First post',
boardId: 'board_789',
sendAt: '2024-01-20T09:00:00Z'
},
{
mediaUrl: 'https://example.com/image2.jpg',
title: 'Post 2',
description: 'Second post',
boardId: 'board_789',
sendAt: '2024-01-20T14:00:00Z'
},
{
mediaUrl: 'https://example.com/image3.jpg',
title: 'Post 3',
description: 'Third post',
boardId: 'board_789',
sendAt: '2024-01-20T19:00:00Z'
}
];
const results = await bulkSchedule('acc_123456', postsToSchedule);
console.log(`Scheduled ${results.filter(r => r.success).length} posts`);

TypeScript Types

interface Account {
id: string;
userId: string;
displayName: string;
username: string;
avatarUrl: string | null;
tokenAuthorized: boolean;
isDomainVerified: boolean;
createdAt: string;
}
interface Board {
id: string;
name: string;
isCollaborator: boolean;
isSecret: boolean;
}
interface Post {
id: string;
status: 'draft' | 'queued' | 'sent' | 'uploading';
mediaUrl: string;
mediaType: 'image' | 'video';
title: string | null;
description: string | null;
url: string | null;
boardId: string | null;
altText: string | null;
sendAt: number | null;
sentAt: number | null;
createdAt: number;
pinId: string | null;
}
interface CreatePostInput {
mediaUrl: string;
mediaType?: 'image' | 'video';
title?: string;
description?: string;
url?: string;
boardId?: string;
altText?: string;
sendAt?: string;
}

Error Handling

async function safeApiCall(fn) {
try {
return await fn();
} catch (error) {
if (error.message.includes('401')) {
console.error('Authentication failed. Check your API key.');
} else if (error.message.includes('429')) {
console.error('Rate limit exceeded. Please wait before retrying.');
} else if (error.message.includes('404')) {
console.error('Resource not found. Check your IDs.');
} else {
console.error('API error:', error.message);
}
throw error;
}
}
// Usage
const accounts = await safeApiCall(() => listAccounts());