> ## Documentation Index
> Fetch the complete documentation index at: https://developer.demand-iq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API Quickstart

> Create and send a personalized presentation to a homeowner using the REST API.

This guide walks through the same flow as the [Quickstart](/ai-presentations/quickstart) — build a template, generate narrated slides, and send a homeowner their personalized presentation link — but entirely over the REST API. Use it as the starting point for integrating AI Presentations into your own CRM, lead platform, or backend.

<Note>
  The dashboard calls them **Templates**, but the API uses the original term **deck**. A deck in the API is the same thing as a template in the UI. A **presentation** is a personalized instance of a deck, created for one homeowner.
</Note>

## Before you start

* Your organization must be provisioned in AI Presentations. If you're not sure, contact your Demand IQ account manager.
* You'll need dashboard login credentials — the API authenticates with a session cookie.
* All requests go to the production base URL: `https://presentations.demand-iq.com`

## Step 1: Authenticate

Deck and presentation endpoints authenticate with a session cookie obtained from `POST /api/auth/login`. Log in once and store the cookie — the examples below use a curl cookie jar (`-b cookies.txt`) to send it on every request:

```bash theme={null}
curl -c cookies.txt -X POST https://presentations.demand-iq.com/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "you@yourcompany.com",
    "password": "••••••••"
  }'
```

A `401 Unauthorized` on any later request means the session has expired — log in again to refresh the cookie.

## Step 2: Create a deck

A deck holds your slides, narration, FAQs, and branding. Create one with a name and a `deckContext` — background about the audience and purpose that guides the AI narration, so the more specific the better.

Set `"type": "image-based"` — the AI generation endpoint in the next step only works on image-based decks and returns a `400` for the default `structured` type:

```bash theme={null}
curl -b cookies.txt -X POST https://presentations.demand-iq.com/api/decks \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Spring Solar Pitch",
    "type": "image-based",
    "deckContext": "Residential solar for storm-damage leads. Audience: homeowners aged 40-65 in the Southeast US."
  }'
```

The response includes the new deck:

```json theme={null}
{
  "deck": {
    "id": "3f6f2c1e-8a4b-4b6e-9f2d-1c5a7e9b0d42",
    "name": "Spring Solar Pitch",
    "type": "image-based",
    "isActive": true,
    "createdBy": "a1b4c8d2-6e3f-4f7a-9c0b-5d2e8f1a3b6c",
    "createdAt": "2026-07-06T17:04:00.000Z",
    "updatedAt": "2026-07-06T17:04:00.000Z"
  }
}
```

Save the `id` — it's the `{deckId}` used in every request that follows.

<Tip>
  Already have your deck as a PowerPoint file? `POST /api/decks/import?source=pptx` creates the deck and its slides from a `.pptx` file in one call, using each slide's speaker notes as its narration script. It replaces steps 2 and 3 — see [Import a PowerPoint presentation](/ai-presentations/guides/deck-types#import-a-powerpoint-presentation).
</Tip>

## Step 3: Generate slides from your images

Send your slide images to the generate endpoint as `multipart/form-data`. AI Presentations runs each image through vision analysis, writes a narration script, and synthesizes spoken audio. Images are processed in the order you attach them, and each must be PNG, JPG, or WebP under 10 MB:

```bash theme={null}
curl -b cookies.txt -X POST \
  https://presentations.demand-iq.com/api/decks/{deckId}/generate \
  -F "images=@slide-01.png" \
  -F "images=@slide-02.png" \
  -F "images=@slide-03.png"
```

Generation runs in the background — the endpoint returns immediately with a job ID:

```json theme={null}
{
  "jobId": "9b1d4e7a-2c3f-4a5b-8d6e-0f1a2b3c4d5e",
  "status": "started",
  "totalSlides": 3
}
```

Poll the status endpoint until `status` is `completed`. Generation usually takes under a minute:

```bash theme={null}
curl -b cookies.txt \
  https://presentations.demand-iq.com/api/decks/{deckId}/generate/status
```

```json theme={null}
{
  "jobId": "9b1d4e7a-2c3f-4a5b-8d6e-0f1a2b3c4d5e",
  "status": "processing",
  "currentSlide": 2,
  "totalSlides": 3,
  "progress": 33,
  "error": null,
  "slidesCreated": 1,
  "faqsCreated": 0,
  "createdAt": "2026-07-06T17:05:00.000Z",
  "completedAt": null
}
```

`progress` counts only finished slides, so it shows 33 while slide 2 of 3 is still generating. A completed or failed job always reports 100.

`slidesCreated` and `faqsCreated` report how many slide and FAQ rows exist right now. If you render slides as they land, refresh on these counts rather than `currentSlide` — `currentSlide` marks when a slide *starts*, so its content isn't readable until a full slide's work later. FAQs are written in one batch after the last slide, so `faqsCreated` stays 0 until near the end.

To watch every deck in your organization with one request instead of polling each deck, call `GET /api/decks/generation-status`. It returns the latest unsettled job per deck, keyed by deck ID; a deck absent from the map has nothing running.

If `status` comes back `failed`, the `error` field explains why. To review or tweak what was generated, list the slides with `GET /api/decks/{deckId}/slides` and edit scripts with `PUT /api/slides/{slideId}`.

## Step 4: Set up branding (recommended)

Branding controls the colors and logo homeowners see throughout the presentation. `palette` and `cta` are required by the schema; the `cta` block ships alongside the branding record but is not what drives the main action button — that label is resolved from the deck's action config (see [Deck types](/ai-presentations/guides/deck-types) and the `action-configs` endpoints in [Contracts](/ai-presentations/guides/contracts)):

```bash theme={null}
curl -b cookies.txt -X PUT \
  https://presentations.demand-iq.com/api/decks/{deckId}/branding \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Solar",
    "palette": {
      "primary": "#1a73e8",
      "primaryLight": "#4a9af5",
      "accent": "#fbbc04",
      "neutral": "#5f6368",
      "text": "#202124"
    },
    "cta": {
      "headline": "Ready to go solar?",
      "body": "Lock in your quote before the spring rush.",
      "buttonText": "Get My Quote",
      "buttonUrl": "https://acmesolar.example.com/quote"
    }
  }'
```

To add a logo or rep avatar, upload the image first with `POST /api/images/upload` (multipart, `file` field; JPG, PNG, WebP, or SVG up to 10 MB) and pass the returned S3 key as `logo` or `avatar`. Deleting an image with `DELETE /api/images/{imageId}` returns `409 Conflict` while any deck or presentation still references it, along with a list of where it's used. Clear those references first.

You can also seed the live Q\&A with your own answers — AI Presentations matches these during the presentation and responds with your exact wording:

```bash theme={null}
curl -b cookies.txt -X POST \
  https://presentations.demand-iq.com/api/decks/{deckId}/faqs \
  -H "Content-Type: application/json" \
  -d '{
    "userQuestion": "How long does installation take?",
    "cannedAnswer": "Most installations are completed in a single day once permits are approved."
  }'
```

## Step 5: Create and send a presentation

Create a personalized presentation for the homeowner. Provide a `homeowner` object (creates a new Core prospect from those details), an existing `prospect_id` (reuses a Core prospect's contact and roof data), or both (attaches the existing prospect but uses the `homeowner` fields you send as-is for personalization). At least one of the two is required. For the `homeowner` path, `first_name`, `address`, `city`, and `country` are required; the address is validated via Google Geocoding, so a `422` with code `INVALID_ADDRESS` means it couldn't be resolved. A `422` with code `PROSPECT_NOT_FOUND` means the `prospect_id` isn't visible to your credential, and a `401` with code `CORE_AUTH_REJECTED` means your session or API key doesn't have the required Core prospect scopes.

If the deck's slides from Step 3 are still generating, the request is refused with a `409` and code `DECK_GENERATING`. A presentation is a permanent snapshot of the deck at creation time, so one taken mid-generation would be permanently missing slides. Wait for the status endpoint to report `completed`, then retry.

```bash theme={null}
curl -b cookies.txt -X POST \
  https://presentations.demand-iq.com/api/decks/{deckId}/presentations \
  -H "Content-Type: application/json" \
  -d '{
    "homeowner": {
      "first_name": "Dana",
      "last_name": "Rivera",
      "address": "1234 Maple Street",
      "city": "Charlotte",
      "state": "NC",
      "zip": "28205",
      "country": "US",
      "email": "dana@example.com",
      "phone": "+1 704 555 0123"
    }
  }'
```

Or, to build the presentation from an existing Core prospect:

```bash theme={null}
curl -b cookies.txt -X POST \
  https://presentations.demand-iq.com/api/decks/{deckId}/presentations \
  -H "Content-Type: application/json" \
  -d '{
    "prospect_id": "prospect_01H8XYZ..."
  }'
```

The shareable URL comes back immediately:

```json theme={null}
{
  "deck_presentation_id": "7c2e5f8b-1a4d-4e6f-9b3c-8d0e2f4a6b1c",
  "url": "https://presentations.demand-iq.com/p/7c2e5f8b-1a4d-4e6f-9b3c-8d0e2f4a6b1c",
  "status": "pending"
}
```

Personalized audio may still be rendering in the background. If you want to wait until everything is ready before sending the link, poll the presentation status — it moves through `pending` → `generating` → `ready` (with a `phase` field showing what's happening while it generates):

```bash theme={null}
curl https://presentations.demand-iq.com/api/presentations/{presentationId}/status
```

```json theme={null}
{
  "id": "7c2e5f8b-1a4d-4e6f-9b3c-8d0e2f4a6b1c",
  "status": "ready",
  "deck_id": "3f6f2c1e-8a4b-4b6e-9f2d-1c5a7e9b0d42",
  "created_at": "2026-07-06T17:10:00.000Z",
  "updated_at": "2026-07-06T17:11:30.000Z"
}
```

Once it's `ready`, deliver the `url` to the homeowner however your platform sends messages — text, email, or straight from your CRM. When they open it, they'll see your branded landing page with their name and address woven into the narration.

## Fetching the OpenAPI spec

Every environment serves its own live OpenAPI 3.0 document at `/presentations/openapi.json`. The spec always matches the code the environment is running, so you can point client-side codegen (OpenAPI Generator, `openapi-typescript`, and similar tools) at it directly:

```bash theme={null}
curl https://presentations.demand-iq.com/presentations/openapi.json
```

The route is public and cached for 5 minutes. The first entry in `servers` reflects the environment serving the request, so a `curl` against stage returns a spec whose `servers[0]` is the stage URL.

## What's next

* **API Reference** — every endpoint in this guide, plus slides, Q\&A settings, narration, voices, and activity, is documented in full in the sidebar
* [Setting up your first template](/ai-presentations/guides/deck-types) — template library, duplication, and personalization tokens
* [Branding](/ai-presentations/guides/branding) — full walkthrough of every branding option
* [FAQs](/ai-presentations/guides/faqs) — how to get the most out of the Q\&A system
