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

# Quickstart

> Get your first query running in under 5 minutes.

## Overview

DynamoSQL lets you query your DynamoDB tables with SQL. This guide walks through obtaining an access token and running your first query against the API.

## Prerequisites

* A DynamoSQL account -- sign up at [dynamosql.com](https://dynamosql.com)
* Your `clientId` and `clientSecret` from the portal

## Step 1 -- Obtain an access token

Exchange your API client credentials for a bearer token:

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.dynamosql.com/v1/auth/token \
    -H "Content-Type: application/json" \
    -d '{
      "clientId": "YOUR_CLIENT_ID",
      "clientSecret": "YOUR_CLIENT_SECRET"
    }'
  ```

  ```python Python theme={null}
  import requests

  resp = requests.post(
      "https://api.dynamosql.com/v1/auth/token",
      json={
          "clientId": "YOUR_CLIENT_ID",
          "clientSecret": "YOUR_CLIENT_SECRET",
      },
  )
  token = resp.json()["data"]["accessToken"]
  ```

  ```javascript Node.js theme={null}
  const resp = await fetch("https://api.dynamosql.com/v1/auth/token", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      clientId: "YOUR_CLIENT_ID",
      clientSecret: "YOUR_CLIENT_SECRET",
    }),
  });
  const { accessToken } = (await resp.json()).data;
  ```

  ```typescript TypeScript theme={null}
  const resp = await fetch("https://api.dynamosql.com/v1/auth/token", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      clientId: "YOUR_CLIENT_ID",
      clientSecret: "YOUR_CLIENT_SECRET",
    }),
  });
  const { accessToken }: { accessToken: string } = (await resp.json()).data;
  ```
</CodeGroup>

The token is valid for one hour. Cache and reuse it; refresh it with `POST /v1/auth/refresh` when it expires.

## Step 2 -- Run a query

Call `POST /v1/query` with your bearer token:

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.dynamosql.com/v1/query \
    -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "sql": "SELECT * FROM myschema.orders LIMIT 10",
      "mode": "execute"
    }'
  ```

  ```python Python theme={null}
  import requests

  resp = requests.post(
      "https://api.dynamosql.com/v1/query",
      headers={"Authorization": f"Bearer {token}"},
      json={
          "sql": "SELECT * FROM myschema.orders LIMIT 10",
          "mode": "execute",
      },
  )
  result = resp.json()
  ```

  ```javascript Node.js theme={null}
  const resp = await fetch("https://api.dynamosql.com/v1/query", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${accessToken}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      sql: "SELECT * FROM myschema.orders LIMIT 10",
      mode: "execute",
    }),
  });
  const result = await resp.json();
  ```

  ```typescript TypeScript theme={null}
  const resp = await fetch("https://api.dynamosql.com/v1/query", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${accessToken}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      sql: "SELECT * FROM myschema.orders LIMIT 10",
      mode: "execute",
    }),
  });
  const result = await resp.json();
  ```
</CodeGroup>

## Step 3 -- Interpret the response

A successful response looks like this:

```json theme={null}
{
  "success": true,
  "data": {
    "columns": ["order_id", "customer_id", "total"],
    "data": [
      [1001, "cust-42", 99.99],
      [1002, "cust-07", 14.50]
    ],
    "firstRowIdx": 0,
    "resumeIdx": 10,
    "planTime": 3,
    "execTime": 42
  }
}
```

* **`success`** -- always check this first. If `false`, read `error` and `detailedError`.
* **`data.columns`** -- column names in the same order as each row array.
* **`data.data`** -- array of rows (each row is an array of values).
* **`data.resumeIdx`** -- present when there are more rows; pass it back to fetch the next page.
* **`data.planTime`** / **`data.execTime`** -- parse+plan time and total elapsed time in milliseconds.

<Note>
  `resumeIdx` is **absent** (not `null`) when the result set is exhausted. Always use `"resumeIdx" in data` (not `data.resumeIdx !== null`) to test for more pages.
</Note>

## Next steps

* [Authentication](/guides/authentication) -- principal types, scopes, and token refresh
* [Pagination](/guides/pagination) -- looping through large result sets
* [SQL Reference](/sql-reference/overview) -- what SQL is supported
