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

# Quickstart

> Make your first API call in under 5 minutes.

## 1. Create an API key

Go to **Settings > API Keys** in your Propal dashboard and click **Create API Key**.

1. Give it a descriptive name (e.g., "My CRM Integration")
2. Select the permissions (scopes) it needs
3. Click **Create Key**

<Warning>
  Copy your API key immediately. It is only shown once. Store it in environment variables or a secrets manager.
</Warning>

## 2. List your proposals

Test your key by listing your proposals:

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl https://api.propal.io/v1/proposals \
    -H "Authorization: Bearer pp_live_YOUR_API_KEY"
  ```

  ```javascript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const response = await fetch("https://api.propal.io/v1/proposals", {
    headers: {
      Authorization: "Bearer pp_live_YOUR_API_KEY",
    },
  });

  const { data, pagination } = await response.json();
  console.log(`Found ${pagination.total_count} proposals`);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import requests

  response = requests.get(
      "https://api.propal.io/v1/proposals",
      headers={"Authorization": "Bearer pp_live_YOUR_API_KEY"},
  )

  data = response.json()
  print(f"Found {data['pagination']['total_count']} proposals")
  ```
</CodeGroup>

Expected response:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "data": [
    {
      "proposal_id": "550e8400-e29b-41d4-a716-446655440000",
      "title": "Website Redesign Proposal",
      "deal_status": "pending",
      "page_status": "draft",
      "lead_name": "Acme Corp",
      "proposal_created_at": "2026-04-01T10:30:00.000Z"
    }
  ],
  "pagination": {
    "has_more": false,
    "next_cursor": null,
    "total_count": 1
  }
}
```

## 3. Create a proposal

Create a proposal from one of your templates:

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST https://api.propal.io/v1/proposals \
    -H "Authorization: Bearer pp_live_YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "template_id": "YOUR_TEMPLATE_ID",
      "title": "Q2 Partnership Proposal",
      "slug": "q2-partnership-2026",
      "lead_id": "YOUR_LEAD_ID",
      "language": "en",
      "settings": {
        "allow_client_to_sign": true,
        "allow_payment": true
      }
    }'
  ```

  ```javascript Node.js theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const response = await fetch("https://api.propal.io/v1/proposals", {
    method: "POST",
    headers: {
      Authorization: "Bearer pp_live_YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      template_id: "YOUR_TEMPLATE_ID",
      title: "Q2 Partnership Proposal",
      slug: "q2-partnership-2026",
      lead_id: "YOUR_LEAD_ID",
      language: "en",
      settings: {
        allow_client_to_sign: true,
        allow_payment: true,
      },
    }),
  });

  const proposal = await response.json();
  console.log(`Created proposal: ${proposal.id}`);
  ```
</CodeGroup>

<Tip>
  Omit `template_id` to create a blank proposal with an empty editor.
</Tip>

## 4. Publish the proposal

Once your proposal is ready, publish it to make it accessible to your client:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X POST https://api.propal.io/v1/proposals/PROPOSAL_ID/publish \
  -H "Authorization: Bearer pp_live_YOUR_API_KEY"
```

Your proposal is now live and accessible to your client.

## 5. Upload a file (optional)

File uploads use a **two-step signed URL flow** — the file never transits through the API server, so there's no size limit.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Step 1: Request a signed upload URL
curl -X POST https://api.propal.io/v1/media/files \
  -H "Authorization: Bearer pp_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "hero.png", "content_type": "image/png"}'
```

The response includes an `uploadUrl`:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "id": "a1b2c3d4-...",
  "name": "hero.png",
  "path": "org_id/uuid.png",
  "uploadUrl": "https://xxx.supabase.co/storage/v1/object/upload/sign/..."
}
```

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Step 2: Upload the file directly to the signed URL
curl -X PUT "UPLOAD_URL_FROM_STEP_1" \
  -H "Content-Type: image/png" \
  --data-binary @hero.png
```

<Info>
  The signed URL is valid for **1 hour**. The file record is created in Propal immediately in step 1 — step 2 uploads the actual binary to storage.
</Info>

## Next steps

<CardGroup cols={2}>
  <Card title="Authentication" icon="key-round" href="/api-reference/authentication">
    API key scopes and security best practices.
  </Card>

  <Card title="Pagination" icon="list" href="/api-reference/pagination">
    Cursor-based pagination for listing resources.
  </Card>

  <Card title="Error handling" icon="triangle-alert" href="/api-reference/errors">
    Handle errors gracefully in your integration.
  </Card>

  <Card title="Create from CRM" icon="arrow-right-left" href="/api-reference/guides/create-proposal-from-crm">
    Full guide: create proposals from your CRM pipeline.
  </Card>
</CardGroup>
