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'};npm install axiosimport axios from 'axios';
const api = axios.create({ baseURL: 'https://api-v1.tailwind.ai', headers: { 'Authorization': `Bearer ${process.env.TAILWIND_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;}
// Usageconst 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;}
// Usageconst 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 postconst 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 draftconst 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;}
// Usageconst 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 draftsconst drafts = await listPosts('acc_123456', { status: 'draft' });console.log('Drafts:', drafts.posts.length);
// List sent posts in a date rangeconst 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;}
// Usageawait 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;}
// Usageconst 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; }}
// Usageconst accounts = await safeApiCall(() => listAccounts());