> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sapt.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Schedule your first post in four calls.

We'll take a video file and put it on Instagram for Friday morning.

<Note>
  You need an API key and a project with at least one connected social account.
  Both come from the [Sapt dashboard](https://app.sapt.ai).
</Note>

```bash theme={null}
export SAPT_API_KEY="sapt_…"
export PROJECT_ID="…"
```

## 1. Find the account

```bash theme={null}
curl "https://api.sapt.ai/socials/accounts/$PROJECT_ID" \
  -H "Authorization: ApiKey $SAPT_API_KEY"
```

Take the `id` of the Instagram entry — that is your `socialAccountId`.

## 2. Upload the video

Stream the raw bytes with the file's own content type:

```bash theme={null}
curl -X PUT \
  "https://api.sapt.ai/socials/media/$PROJECT_ID/stream-upload?filename=reel.mp4" \
  -H "Authorization: ApiKey $SAPT_API_KEY" \
  -H "Content-Type: video/mp4" \
  --data-binary @reel.mp4
```

Keep `data.handle` from the response — both `stagingId` and `ext`.

## 3. Schedule the post

```bash theme={null}
curl -X POST "https://api.sapt.ai/socials/posts/$PROJECT_ID" \
  -H "Authorization: ApiKey $SAPT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "socialAccountId": "9f1c2f7a-4c9e-4a1d-9d0e-8a5b6c7d8e9f",
    "platform": "instagram",
    "mediaType": "REELS",
    "caption": "New drop, Friday.",
    "uploadedHandles": [{ "stagingId": "stg_01JQ…", "ext": "mp4" }],
    "scheduledFor": "2026-09-11T14:00:00Z",
    "timezone": "America/New_York"
  }'
```

The response carries the post with `status: "scheduled"`. Keep `data.post.id`.

## 4. Check on it

```bash theme={null}
curl "https://api.sapt.ai/socials/posts/$PROJECT_ID/$POST_ID/status" \
  -H "Authorization: ApiKey $SAPT_API_KEY"
```

At the scheduled time it moves to `queued`, then `publishing`, then `published`
with a `permalink`. If something goes wrong it becomes `failed` and
`errorMessage` says why.

## All together

```typescript theme={null}
const API = 'https://api.sapt.ai'
const auth = { Authorization: `ApiKey ${process.env.SAPT_API_KEY}` }
const projectId = process.env.PROJECT_ID!

// 1. Pick a live Instagram account.
const accountsRes = await fetch(`${API}/socials/accounts/${projectId}`, { headers: auth })
const { data: accountData } = await accountsRes.json()
const account = accountData.accounts.find(
  (a) => a.platform === 'instagram' && a.isActive
)
if (!account) throw new Error('No active Instagram account on this project')

// 2. Stage the video.
const uploadRes = await fetch(
  `${API}/socials/media/${projectId}/stream-upload?filename=reel.mp4`,
  {
    method: 'PUT',
    headers: { ...auth, 'Content-Type': 'video/mp4' },
    body: await Bun.file('reel.mp4').arrayBuffer(),
  }
)
const { data: upload } = await uploadRes.json()

// 3. Put it on the calendar.
const postRes = await fetch(`${API}/socials/posts/${projectId}`, {
  method: 'POST',
  headers: { ...auth, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    socialAccountId: account.id,
    platform: 'instagram',
    mediaType: 'REELS',
    caption: 'New drop, Friday.',
    uploadedHandles: [upload.handle],
    scheduledFor: '2026-09-11T14:00:00Z',
    timezone: 'America/New_York',
  }),
})

const { data } = await postRes.json()
console.log(`Scheduled ${data.post.id} for ${data.post.scheduledFor}`)
```

## Next

<CardGroup cols={2}>
  <Card title="Social publishing" icon="calendar" href="/docs/mintlify/social/overview">
    Platforms, media types, and the post lifecycle in full.
  </Card>

  <Card title="Publish immediately" icon="paper-plane" href="/docs/mintlify/social/publishing">
    Skip the calendar, and handle failures.
  </Card>
</CardGroup>
