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

# Quickstart

> Run a campaign end to end through the API — project, ad copy, channels, budget, approval.

This walkthrough creates a live campaign with `curl`. Everything here is also available in the [console](https://console.aflux.ai); the API just makes each step explicit.

<Note>
  A campaign commits its **entire budget** the moment you create it. Top up your balance first — see [Deposits](/billing/deposits) — and use a small budget while you are finding your feet.
</Note>

## Before you start

<Steps>
  <Step title="Get an API key">
    In the console, open **Settings → API keys** and create one. The full key is shown **once**, at creation. It looks like `sk-af-v1-` followed by 32 hex characters. See [API keys](/account/api-keys).
  </Step>

  <Step title="Export it">
    ```bash theme={null}
    export AFLUX_KEY="sk-af-v1-..."
    export AFLUX_API="https://backend.aflux.ai/api/v1"
    ```
  </Step>
</Steps>

Every request below sends the key as a bearer token:

```bash theme={null}
curl -H "Authorization: Bearer $AFLUX_KEY" "$AFLUX_API/users/me"
```

## 1. Upload a logo

A project needs a logo. Uploads are two calls: reserve a slot, then send the bytes.

```bash theme={null}
UPLOAD=$(curl -s -X POST "$AFLUX_API/uploads/init" \
  -H "Authorization: Bearer $AFLUX_KEY" -H "Content-Type: application/json" \
  -d '{"assetKind":"PROJECT_LOGO","contentType":"image/png","sizeBytes":48123,"originalName":"logo.png"}')

UPLOAD_ID=$(echo "$UPLOAD" | jq -r .uploadId)

LOGO=$(curl -s -X PUT "$AFLUX_API/uploads/$UPLOAD_ID/content" \
  -H "Authorization: Bearer $AFLUX_KEY" -H "Content-Type: application/octet-stream" \
  --data-binary @logo.png)

LOGO_ID=$(echo "$LOGO" | jq -r .assetId)
```

`sizeBytes` and `contentType` are checked against the actual bytes you send, so they have to be right. Limits are in [Media](/guides/media).

## 2. Create a project

Let Aflux read your site first — it drafts the name, description and brand colours for you.

```bash theme={null}
curl -s -X POST "$AFLUX_API/projects/analyze-url" \
  -H "Authorization: Bearer $AFLUX_KEY" -H "Content-Type: application/json" \
  -d '{"url":"https://example.com","sourceType":"WEBSITE"}'
```

Then generate the AI context — the business description every later step reasons from — and create the project:

```bash theme={null}
CONTEXT=$(curl -s -X POST "$AFLUX_API/projects/context/generate" \
  -H "Authorization: Bearer $AFLUX_KEY" -H "Content-Type: application/json" \
  -d "{\"name\":\"Example\",\"description\":\"A DeFi wallet for TON\",
       \"logoLightAssetId\":\"$LOGO_ID\",\"brandColors\":[\"#5bc8ff\"],
       \"sourceUrl\":\"https://example.com\"}")

PROJECT=$(curl -s -X POST "$AFLUX_API/projects" \
  -H "Authorization: Bearer $AFLUX_KEY" -H "Content-Type: application/json" \
  -d "{\"sourceType\":\"WEBSITE\",\"sourceUrl\":\"https://example.com\",
       \"name\":\"Example\",\"description\":\"A DeFi wallet for TON\",
       \"logoLightAssetId\":\"$LOGO_ID\",\"brandColors\":[\"#5bc8ff\"],
       \"aiContext\":$(echo "$CONTEXT" | jq -c .aiContext)}")

PROJECT_ID=$(echo "$PROJECT" | jq -r .id)
```

See [Projects](/guides/projects) for what the context is used for and how to revise it.

## 3. Write and validate the ad copy

```bash theme={null}
COPY=$(curl -s -X POST "$AFLUX_API/campaigns/generate-ad-copy" \
  -H "Authorization: Bearer $AFLUX_KEY" -H "Content-Type: application/json" \
  -d "{\"projectContext\":$(echo "$PROJECT" | jq -c .aiContext),
       \"userNotes\":\"Announce our new staking feature. Friendly, no hype.\",
       \"objective\":\"TRAFFIC\",\"destinationUrl\":\"https://example.com/staking\"}")

curl -s -X POST "$AFLUX_API/campaigns/ad-copy/validate" \
  -H "Authorization: Bearer $AFLUX_KEY" -H "Content-Type: application/json" \
  -d "{\"text\":$(echo "$COPY" | jq .adCopy),\"destinationUrl\":\"https://example.com/staking\"}"
```

Validation answers with **every** problem at once, each positioned so an editor can underline it. Campaign creation applies exactly the same rules, so a text that validates is a text that creates. See [Ad copy](/guides/ad-copy).

## 4. Find channels

```bash theme={null}
MATCH=$(curl -s -X POST "$AFLUX_API/campaigns/match-channels-by-prompt" \
  -H "Authorization: Bearer $AFLUX_KEY" -H "Content-Type: application/json" \
  -d '{"prompt":"TON and DeFi channels, 20K+ subscribers, English-speaking traders"}')

MATCH_TOKEN=$(echo "$MATCH" | jq -r .matchToken)
echo "$MATCH" | jq '.filters, (.channels | length)'
```

<Warning>
  Keep the `matchToken`. Campaign creation consumes exactly one token and buys exactly the channels cached under it. A channel that is not in that search cannot be bought.
</Warning>

`filters` shows how your sentence was read — `20K+ subscribers` comes back as `minSubscribers: 20000`. If it read you wrong, correct the prompt and search again. See [Finding channels](/guides/finding-channels).

## 5. Ask for a budget spread

```bash theme={null}
DIST=$(curl -s -X POST "$AFLUX_API/campaigns/distribution/suggest" \
  -H "Authorization: Bearer $AFLUX_KEY" -H "Content-Type: application/json" \
  -d '{"budget":"500.00","startsAt":"2026-09-15","endsAt":"2026-09-30","objective":"TRAFFIC"}')
```

Each day comes back with an amount and a `recommendation` of `AI_BEST`, `NORMAL` or `LOW_TRAFFIC`.

## 6. Create the campaign

```bash theme={null}
CAMPAIGN=$(curl -s -X POST "$AFLUX_API/campaigns" \
  -H "Authorization: Bearer $AFLUX_KEY" -H "Content-Type: application/json" \
  -d "{\"idempotencyKey\":\"$(uuidgen)\",
       \"matchToken\":\"$MATCH_TOKEN\",
       \"projectId\":\"$PROJECT_ID\",
       \"name\":\"Staking launch\",
       \"destinationUrl\":\"https://example.com/staking?utm_source={channel}&utm_campaign={campaign}\",
       \"adCopy\":$(echo "$COPY" | jq .adCopy),
       \"platform\":\"TELEGRAM\",
       \"objective\":\"TRAFFIC\",
       \"distributionType\":\"RECOMMENDED\",
       \"mediaAssetIds\":[],
       \"budget\":\"500.00\",
       \"startsAt\":\"2026-09-15\",
       \"endsAt\":\"2026-09-30\",
       \"dailyDistribution\":$(echo "$DIST" | jq -c '[.days[] | {date, amount}]'),
       \"approvalMode\":\"USER\",
       \"creativeChangesAllowed\":true}")

CAMPAIGN_ID=$(echo "$CAMPAIGN" | jq -r .id)
```

Two things worth noticing:

* `{channel}` and `{campaign}` in `destinationUrl` are substituted per placement, so your own analytics can tell channels apart. See [Campaigns](/guides/campaigns).
* `idempotencyKey` makes a retried request safe. Reuse the same UUID when you retry; use a fresh one for a genuinely new campaign.

## 7. Approve the deals

The agent now contacts channel owners. Poll the placements:

```bash theme={null}
curl -s "$AFLUX_API/campaigns/$CAMPAIGN_ID/placements" \
  -H "Authorization: Bearer $AFLUX_KEY" | jq '.items[] | {channelUsername, status, agreedCost, agreedDate}'
```

When one reaches `PENDING_APPROVAL`, read what was agreed and approve it:

```bash theme={null}
curl -s -X POST "$AFLUX_API/campaign-placements/$PLACEMENT_ID/approve" \
  -H "Authorization: Bearer $AFLUX_KEY"
```

Approval is what commits money to that channel. See [Placements](/guides/placements) for the full status list and what each one means.

## 8. Read the results

```bash theme={null}
curl -s "$AFLUX_API/campaigns/$CAMPAIGN_ID/analytics" -H "Authorization: Bearer $AFLUX_KEY"
```

Views and reactions arrive after publication and settle roughly 48 hours later; clicks are measured on our own redirect. [Analytics](/guides/analytics) explains what each figure does and does not include.

## Next

<CardGroup cols={2}>
  <Card title="Concepts" icon="book" href="/concepts">
    The vocabulary — projects, campaigns, placements, balance.
  </Card>

  <Card title="MCP server" icon="robot" href="/mcp/overview">
    Do all of the above from your own AI agent instead.
  </Card>
</CardGroup>
