Skip to content

TypeScript SDK

The official TypeScript/JavaScript client library for AMP.

Installation

npm install @ubiship/amp
# or
yarn add @ubiship/amp
# or
pnpm add @ubiship/amp

Quick Start

import { AMP } from '@ubiship/amp';

const client = new AMP('amp_live_xxxxxxxxxxxxx');

// Create a mission
const mission = await client.missions.create({
  name: 'TypeScript SDK Test',
  objectives: ['Test the SDK'],
  platforms: ['twitter'],
  duration_days: 7,
});

console.log(`Created mission: ${mission.id}`);

Configuration

Client Options

const client = new AMP('amp_live_xxx', {
  baseURL: 'https://custom.api.url',
  timeout: 60000,
  maxRetries: 3,
});

Environment Variables

// Reads AMP_API_KEY from process.env
const client = new AMP();

Resources

Missions

// List missions
const missions = await client.missions.list({
  status: 'active',
  limit: 20,
});

// Create mission
const mission = await client.missions.create({
  name: 'My Mission',
  objectives: ['Drive awareness'],
  platforms: ['twitter', 'linkedin'],
  constraints: {
    tone: 'professional',
    cadence: 'daily',
    posts_per_day: 2,
    require_approval: true,
  },
  duration_days: 30,
});

// Get mission
const mission = await client.missions.retrieve('msn_xxx');

// Update mission
const mission = await client.missions.update('msn_xxx', {
  constraints: {
    posts_per_day: 3,
  },
});

// Pause mission
const mission = await client.missions.pause('msn_xxx');

// Resume mission
const mission = await client.missions.resume('msn_xxx');

// Delete mission
await client.missions.delete('msn_xxx');

// Get status
const status = await client.missions.status('msn_xxx');

Content

// List content
const content = await client.content.list({
  mission_id: 'msn_xxx',
  status: 'pending_review',
});

// Get content
const item = await client.content.retrieve('cnt_xxx');

// Preview content
const preview = await client.content.preview('cnt_xxx');

// Approve content
const approved = await client.content.approve('cnt_xxx', {
  notes: 'Looks good',
});

// Reject content
const rejected = await client.content.reject('cnt_xxx', {
  reason: 'Too casual',
  feedback: 'Use professional tone',
  regenerate: true,
});

// Schedule content
const scheduled = await client.content.schedule('cnt_xxx', {
  scheduled_for: '2024-01-16T14:00:00Z',
});

Analytics

// Overview
const overview = await client.analytics.overview({
  period: '30d',
});

// Mission analytics
const analytics = await client.analytics.mission('msn_xxx');

// Costs
const costs = await client.analytics.costs({
  period: '30d',
});

// Performance breakdown
const performance = await client.analytics.performance({
  period: '30d',
  breakdown: ['platform', 'type'],
});

Error Handling

import { AMP, AMPError, RateLimitError, NotFoundError } from '@ubiship/amp';

try {
  const mission = await client.missions.retrieve('msn_xxx');
} catch (error) {
  if (error instanceof NotFoundError) {
    console.log('Mission not found');
  } else if (error instanceof RateLimitError) {
    console.log(`Rate limited. Retry after ${error.retryAfter}s`);
    await sleep(error.retryAfter * 1000);
  } else if (error instanceof AMPError) {
    console.log(`API error: ${error.code} - ${error.message}`);
  } else {
    throw error;
  }
}

Pagination

Automatic Iteration

// Async iterator
for await (const mission of client.missions.list({ limit: 20 })) {
  console.log(mission.id);
}

Manual Pagination

let page = await client.missions.list({ limit: 20 });

while (true) {
  for (const mission of page.data) {
    console.log(mission.id);
  }

  if (!page.has_more) break;
  page = await client.missions.list({
    limit: 20,
    starting_after: page.data[page.data.length - 1].id,
  });
}

Webhooks

Express Middleware

import express from 'express';
import { AMP } from '@ubiship/amp';

const app = express();
const client = new AMP('amp_live_xxx');

app.post('/webhooks/amp', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-amp-signature'] as string;
  const timestamp = req.headers['x-amp-timestamp'] as string;

  try {
    const event = client.webhooks.constructEvent(
      req.body,
      signature,
      timestamp,
      process.env.WEBHOOK_SECRET!
    );

    switch (event.type) {
      case 'content.published':
        console.log('Content published:', event.data.content_id);
        break;
      case 'mission.completed':
        console.log('Mission completed:', event.data.mission_id);
        break;
    }

    res.status(200).send('OK');
  } catch (err) {
    res.status(401).send('Invalid signature');
  }
});

TypeScript Types

import type {
  Mission,
  MissionCreateParams,
  Content,
  ContentStatus,
  Platform,
  Analytics,
} from '@ubiship/amp';

function processMission(mission: Mission): void {
  console.log(mission.id, mission.status);
}

const params: MissionCreateParams = {
  name: 'Typed Mission',
  objectives: ['Type safety'],
  platforms: ['twitter' as Platform],
  duration_days: 30,
};

Testing

import { AMP, MockAMP } from '@ubiship/amp';

// Use test mode
const client = new AMP('amp_test_xxx');

// Or use mock client
const mockClient = new MockAMP();
mockClient.missions.create.mockResolvedValue({
  id: 'msn_test',
  status: 'active',
});

// Jest example
jest.mock('@ubiship/amp');
const mockedAMP = jest.mocked(AMP);

Node.js & Browser

The SDK works in both Node.js and browser environments:

// Node.js
import { AMP } from '@ubiship/amp';

// Browser (with bundler)
import { AMP } from '@ubiship/amp';

// Browser (CDN)
<script src="https://cdn.amp.dev/sdk/amp.min.js"></script>
<script>
  const client = new AMP.default('amp_live_xxx');
</script>

Browser Security

Never expose your API key in client-side code. Use a backend proxy for browser applications.