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

# Quickstart

> Make your first authenticated Daysync Integration API call and walk a typical read → write flow.

This walkthrough goes from "Daysync just approved my application" to "I've called the API as a real user." Plan for \~15 minutes.

## Before you start

You should have:

* **`x-api-key`** (`dk_live_…`) and **`x-api-secret`** (`ds_…`) for your app — these double as your OAuth **client ID / client secret** (see [Authentication](/authentication) and [Apply for API Access](/apply-for-access))
* A **registered redirect URI**. For this walkthrough we'll use Postman's callback — add `https://oauth.pstmn.io/v1/callback` to your app's **Redirect URIs** in the [Integrations Portal](https://integrations.daysync.com) first (it takes effect instantly)
* A real Daysync user account (sign up at [app.daysync.com](https://app.daysync.com) if you don't have one)
* Terminal access with `curl`, `jq`, and `openssl`

<Tip>
  Export everything as shell variables now — every step below references them. Your API key/secret are the OAuth client credentials; there is no separate shared client.

  ```bash theme={null}
  export DAYSYNC_API_KEY="dk_live_…"
  export DAYSYNC_API_SECRET="ds_…"
  export DAYSYNC_REDIRECT_URI="https://oauth.pstmn.io/v1/callback"
  ```
</Tip>

## Step 1 — Generate a PKCE pair

PKCE (S256) is **required** on every authorization. Generate a `code_verifier` and its `code_challenge`:

```bash theme={null}
export DAYSYNC_CODE_VERIFIER=$(openssl rand -base64 96 | tr -d '\n=+/' | cut -c1-64)
export DAYSYNC_CODE_CHALLENGE=$(printf '%s' "$DAYSYNC_CODE_VERIFIER" \
  | openssl dgst -sha256 -binary | openssl base64 | tr -d '=\n' | tr '/+' '_-')
echo "verifier=$DAYSYNC_CODE_VERIFIER"
echo "challenge=$DAYSYNC_CODE_CHALLENGE"
```

Keep the **verifier** for Step 3; the **challenge** goes in the authorize URL below.

## Step 2 — Get a user authorization code

Open this URL in a browser (the line breaks are for reading; remove them before pasting):

```text theme={null}
https://integrations.daysync.com/authorize
  ?response_type=code
  &client_id=YOUR_API_KEY
  &redirect_uri=https://oauth.pstmn.io/v1/callback
  &scope=openid+email+daysync-api/tours.read+daysync-api/organization.read
  &state=xyz123
  &code_challenge=YOUR_CODE_CHALLENGE
  &code_challenge_method=S256
```

You'll sign in with your Daysync account (the portal's normal login), then see a consent screen naming your app and the requested permissions. After you approve, the browser redirects to:

```text theme={null}
https://oauth.pstmn.io/v1/callback?code=ABCDEFG…&state=xyz123
```

Copy the `code` value out of the URL bar.

```bash theme={null}
export DAYSYNC_AUTH_CODE="ABCDEFG…"
```

<Warning>
  Authorization codes expire in \~5 minutes and are single-use. If Step 3 fails with `invalid_grant`, redo Step 1–2 to get a fresh code (a fresh PKCE pair too).
</Warning>

## Step 3 — Exchange the code for tokens

Authenticate the client with HTTP Basic auth (`-u`) using your **API key and secret**, and include the PKCE `code_verifier`:

```bash theme={null}
curl -sS -X POST https://integrations.daysync.com/api/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -u "$DAYSYNC_API_KEY:$DAYSYNC_API_SECRET" \
  -d "grant_type=authorization_code" \
  -d "code=$DAYSYNC_AUTH_CODE" \
  -d "redirect_uri=$DAYSYNC_REDIRECT_URI" \
  -d "code_verifier=$DAYSYNC_CODE_VERIFIER" | jq .
```

Response:

```json theme={null}
{
  "access_token": "eyJraWQ…",
  "refresh_token": "eyJjdHk…",
  "token_type": "Bearer",
  "expires_in": 3412,
  "scope": "daysync-api/tours.read daysync-api/organization.read"
}
```

Capture the tokens. Treat `scope` as the authoritative record of what the user consented to, and `expires_in` as the token's **real** remaining life (it can be less than 3600 — refresh when it nears zero):

```bash theme={null}
export DAYSYNC_ACCESS_TOKEN="eyJraWQ…"
export DAYSYNC_REFRESH_TOKEN="eyJjdHk…"
```

## Step 4 — List the user's organizations

This is the canonical first API call. Every integration starts here because every other resource is scoped to an organization.

```bash theme={null}
curl -sS "https://integration.daysync.com/v1/organizations" \
  -H "x-api-key: $DAYSYNC_API_KEY" \
  -H "x-api-secret: $DAYSYNC_API_SECRET" \
  -H "Authorization: Bearer $DAYSYNC_ACCESS_TOKEN" | jq .
```

Response (abbreviated — see the [Organizations endpoint reference](/endpoints/organizations) for the full field list):

```json theme={null}
{
  "status": true,
  "message": "Success",
  "data": [
    {
      "id": "5f8c9b2a-…",
      "name": "Acme Touring",
      "loggedInUserRole": { "id": 1, "name": "org_admin" },
      "orgUserCount": 12,
      "is_trial": false
    }
  ]
}
```

Capture an `org_id` for the next step:

```bash theme={null}
export DAYSYNC_ORG_ID="5f8c9b2a-…"
```

## Step 5 — List tours for that organization

```bash theme={null}
curl -sS "https://integration.daysync.com/v1/tours?org_id=$DAYSYNC_ORG_ID" \
  -H "x-api-key: $DAYSYNC_API_KEY" \
  -H "x-api-secret: $DAYSYNC_API_SECRET" \
  -H "Authorization: Bearer $DAYSYNC_ACCESS_TOKEN" | jq .
```

You should see the tours that user has access to. If you get an empty array, sign in at [app.daysync.com](https://app.daysync.com) and create a tour, then re-run.

## Step 6 — Refresh the access token

Access tokens expire in ≈60 minutes. Refresh tokens last 30 days. Refresh with the **same** client credentials — no PKCE needed on refresh:

```bash theme={null}
curl -sS -X POST https://integrations.daysync.com/api/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -u "$DAYSYNC_API_KEY:$DAYSYNC_API_SECRET" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=$DAYSYNC_REFRESH_TOKEN" | jq .
```

The response has the same shape as Step 3 (without `scope`). Keep reusing the refresh token until it expires after 30 days; when it does, the call fails with `400 invalid_grant` and you send the user through the authorization flow again.

## Going to production

<Warning>
  This walkthrough used Postman's callback URL (`https://oauth.pstmn.io/v1/callback`) for the OAuth flow. **You've validated that your credentials work — but you haven't tested your own production OAuth flow yet.**

  Before going live: add your own callback URL under **Redirect URIs** on your app in the [Integrations Portal](https://integrations.daysync.com) (see [Callback URLs](/callback-urls)), then re-run Step 2 with `redirect_uri=<your-registered-callback>` to exercise the same flow your real users will go through.
</Warning>

## What's next

<CardGroup cols={2}>
  <Card title="Common Workflows" icon="diagram-project" href="/common-workflows">
    End-to-end recipes — full tour setup, sync loops, guest list management.
  </Card>

  <Card title="Endpoint Reference" icon="list-tree" href="/endpoints/tours">
    Every endpoint with request bodies, response shapes, and required scopes.
  </Card>

  <Card title="Scopes" icon="lock" href="/scopes">
    Which scopes you need to request for each endpoint.
  </Card>

  <Card title="Errors" icon="triangle-exclamation" href="/errors">
    Every HTTP status code and machine-readable error code.
  </Card>
</CardGroup>

## Trouble?

<AccordionGroup>
  <Accordion title="invalid_grant on token exchange">
    Authorization codes expire fast (\~5 minutes) and are single-use, and the `code_verifier` must match the `code_challenge` you sent in Step 2. Redo Step 1–2 for a fresh PKCE pair and code, then run Step 3 promptly.
  </Accordion>

  <Accordion title="invalid_request: PKCE S256 (code_challenge) is required">
    Your authorize URL is missing `code_challenge` or `code_challenge_method=S256`. PKCE is mandatory — generate the pair in Step 1 and include both parameters.
  </Accordion>

  <Accordion title="401 Unauthorized on API call">
    Most likely missing or wrong `x-api-key` / `x-api-secret`. Confirm the values from your provisioning email, paying attention to trailing whitespace.
  </Accordion>

  <Accordion title="403 INSUFFICIENT_SCOPE">
    Your partner credentials weren't issued with the scope this endpoint requires. Cross-reference the endpoint's required scope on [Scopes & Permissions](/scopes), then email `support@daysync.com` to request additional scopes.
  </Accordion>

  <Accordion title="'This application's redirect URL is not registered'">
    The `redirect_uri` in your authorize URL isn't on your app's allowlist. Add it under **Redirect URIs** in the [Integrations Portal](https://integrations.daysync.com) — it takes effect immediately. See [Callback URLs](/callback-urls) for the exact-match rules.
  </Accordion>
</AccordionGroup>
