# Introduction and Authentication

> Separate guides will cover what you can *do* with a token (the API endpoints). This doc is strictly about getting a valid access token.

***

### Who this is for

* **Developers** who will write code against our API.
* **Non-technical integrators** using tools like **Zapier, n8n, Make, or Power Automate** — anything that speaks standard OAuth 2.0 / 2.1. You will paste values into form fields; no coding required.

Both audiences follow the same steps. Where the paths diverge, we'll call it out with 🧑‍💻 **Developer** and 🧩 **No-code tool** callouts.

***

### The 60-second version

1. **Ask the STS Cloud team to register your app.** You'll receive a **Client ID** and **Client Secret**.
2. **Send your user to our authorization URL.** They log in and approve access.
3. **Exchange the returned code for an access token.**
4. **Call our API** with `Authorization: Bearer <token>`.
5. **Refresh the token** every hour using the refresh token we send you.

If your no-code tool already has an "OAuth 2.0 (Authorization Code)" connector, you'll only need the four URLs, your client credentials, and a scope list.

***

### Key facts

| Item                        | Value                                                                                                            |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| Protocol                    | OAuth 2.1 (Authorization Code with PKCE)                                                                         |
| Production host             | `https://interfaces.stscloud.com`                                                                                |
| Token type                  | `Bearer` (opaque — do not try to decode)                                                                         |
| Access token lifetime       | **1 hour**                                                                                                       |
| Authorization code lifetime | 10 minutes                                                                                                       |
| Refresh tokens              | Supported (use to get new access tokens)                                                                         |
| PKCE                        | **Required by default** (method `S256`). We can disable per-app for integrations that can't support it — ask us. |
| HTTPS                       | Required in production. `http://localhost` is allowed for local testing.                                         |

***

### Step 1: Register your application

STS Cloud does not currently offer self-service app registration. **Email your STS Cloud account contact** (or `support@salesandcatering.com`) with:

1. **App name** — how it should appear to users on the consent screen.
2. **Redirect URI(s)** — the exact URL(s) we should send users back to after they approve access. One per line. Examples:
   * Developer: `https://your-app.com/oauth/callback`
   * Zapier: `https://zapier.com/dashboard/auth/oauth/return/App<ID>CLIAPI/`
   * Make: `https://www.make.com/oauth/cb/oauth2`
   * Local testing: `http://localhost:3000/oauth/callback`
3. **Scopes you need** — see Available scopes.
4. **Which customer(s)** this integration will serve — OAuth apps are scoped to a specific STS Cloud client/property.
5. **PKCE capability** — default is "yes, I can do PKCE." If your tool can't, tell us so we can disable it for your app (rare).

We will reply with:

* **Client ID** (also called "uid") — public, safe to embed in your app.
* **Client Secret** — **secret**, treat like a password. We show it once; store it securely.

> 🔁 **Lost your secret?** We can regenerate it on request. This invalidates the old one immediately.

***

### Step 2: Send the user to the authorization URL

The STS Cloud Platform API utilizes the **Authorization Code with PKCE** flow and acts on behalf of a user, so *each STS Cloud user who will utilize this API must complete this step*.

When the user clicks "Connect to STS Cloud" in your app, redirect them here:

```
https://interfaces.stscloud.com/oauth/authorize
  ?client_id=YOUR_CLIENT_ID
  &redirect_uri=YOUR_REDIRECT_URI
  &response_type=code
  &scope=accounts_read+bookings_read
  &state=RANDOM_OPAQUE_STRING
  &code_challenge=PKCE_CHALLENGE
  &code_challenge_method=S256
```

#### What each parameter means

| Parameter               | Notes                                                                                                                                         |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `client_id`             | Given to you at registration.                                                                                                                 |
| `redirect_uri`          | **Must exactly match** one of the URIs you registered (trailing slashes matter).                                                              |
| `response_type`         | Always `code`.                                                                                                                                |
| `scope`                 | Space-separated list of scopes (URL-encoded as `+` or `%20`).                                                                                 |
| `state`                 | A random string you generate. We pass it back unchanged so you can verify the response belongs to this request. Required for CSRF protection. |
| `code_challenge`        | PKCE challenge — see below.                                                                                                                   |
| `code_challenge_method` | Always `S256`.                                                                                                                                |

#### 🧑‍💻 Developer: generating PKCE values

```js
// Node example
import { randomBytes, createHash } from "crypto";

const verifier = randomBytes(32).toString("base64url");     // keep this secret until step 4
const challenge = createHash("sha256")
  .update(verifier)
  .digest("base64url");
```

Rules: `code_verifier` is a random 43–128 char URL-safe string. `code_challenge = BASE64URL(SHA256(verifier))` with no padding.

#### 🧩 No-code tool: PKCE

Most modern OAuth 2.0 connectors (Zapier, Make, n8n) handle PKCE automatically when you pick **"OAuth 2.0 (Authorization Code with PKCE)"** — you just paste the URLs and credentials. If the connector only offers plain "Authorization Code" without PKCE, tell STS Cloud and we'll disable PKCE for your app.

#### What happens next

1. User sees our login page (if not already logged in).
2. User sees a consent screen listing your app name and requested scopes.
3. After they approve, we redirect to:

```
YOUR_REDIRECT_URI?code=ONE_TIME_CODE&state=THE_STATE_YOU_SENT
```

Verify `state` matches what you sent. If not, stop and show an error — the request may be forged.

***

### Step 3: Exchange the code for a token

You have **10 minutes** to exchange the code. Make this call from your server (not the browser):

```http
POST https://interfaces.stscloud.com/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&code=ONE_TIME_CODE
&redirect_uri=YOUR_REDIRECT_URI
&code_verifier=THE_VERIFIER_YOU_KEPT_FROM_STEP_3
```

#### Response

```json
{
  "access_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
  "scope": "accounts_read bookings_read",
  "created_at": 1713100000
}
```

Store both the `access_token` and `refresh_token`. Tokens are opaque — don't try to decode them.

#### 🧩 No-code tool

Your connector usually handles this exchange invisibly after you paste:

* **Authorization URL:** `https://interfaces.stscloud.com/oauth/authorize`
* **Access Token URL:** `https://interfaces.stscloud.com/oauth/token`
* **Client ID / Client Secret:** from registration
* **Scopes:** space-separated, e.g. `accounts_read bookings_read`

***

### Step 4: Call the API endpoint

Include the access token on every API request:

```http
GET https://interfaces.stscloud.com/api/v1/accounts
Authorization: Bearer YOUR_ACCESS_TOKEN
```

The base path for API resources is `/api/v1/...`. The specific endpoints, request shapes, and required scopes are covered in a separate guide.

***

### Step 5: Refresh before expiry

Access tokens expire after 1 hour. Get a new one without bothering the user:

```http
POST https://interfaces.stscloud.com/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&refresh_token=YOUR_REFRESH_TOKEN
```

The response is the same shape as Step 4 and will include a **new** refresh token. **Replace your stored refresh token every time** — the old one is invalidated.

No-code tools handle refresh automatically.

***

### Revoking a token (optional)

When a user disconnects your app, revoke the token so it stops working immediately:

```http
POST https://interfaces.stscloud.com/oauth/revoke
Content-Type: application/x-www-form-urlencoded

token=ACCESS_OR_REFRESH_TOKEN
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
```

Returns `200 OK` on success.

***

### Checking what a token has access to

Useful for debugging:

```http
GET https://interfaces.stscloud.com/oauth/token/info
Authorization: Bearer YOUR_ACCESS_TOKEN
```

Returns the token's scopes, the owning application, and the resource owner (user).

***

### Available scopes

Request only what you need — customers are more likely to approve narrow scopes.

| Scope                                  | Grants                                   |
| -------------------------------------- | ---------------------------------------- |
| `public`                               | Default. Public/non-sensitive data.      |
| `profile`                              | The logged-in user's basic profile.      |
| `users_read`                           | Read user records.                       |
| `accounts_read /` `contacts_read`      | Read customer accounts and contacts.     |
| `bookings_read` / `bookings_write`     | Read/modify bookings.                    |
| `documents_read` / `documents_write`   | Read/modify proposals.                   |
| `properties_read` / `properties_write` | Read/modify property records.            |
| `proposal_assistant`                   | Use the AI proposal generation endpoint. |

If you need a scope combination not listed, ask.

***

### Rate limits

To protect shared infrastructure we apply per-endpoint limits. If you exceed them you'll get `HTTP 429 Too Many Requests` with a `Retry-After` header.

| Endpoint                    | Limit                     |
| --------------------------- | ------------------------- |
| `/oauth/token`              | 10 / minute               |
| `/oauth/authorize`          | 30 / minute               |
| `/api/v1/*` (authenticated) | \~1000 / minute per token |
| `/api/v1/bookings`          | 100 / minute              |
| `/api/v1/accounts`          | 200 / minute              |

Backing off and retrying on 429 is good practice.

***

### Testing your integration

1. Ask STS Cloud for **sandbox credentials** — we have several sandboxes you can use to test specific use-cases.
2. We provide a **test landing page** at `/oauth/callback` that displays the `code` and `state` so you can verify the redirect without wiring up your backend yet.
3. Run through steps 2-5 end-to-end with a test user before pointing at a real customer's account.

***

### Common problems

| Symptom                                         | Likely cause                                                                                                                  |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `invalid_redirect_uri`                          | Your `redirect_uri` doesn't exactly match what's registered. Trailing slashes, `http` vs `https`, and port numbers all count. |
| `invalid_grant` on token exchange               | Code already used, expired (>10 min), or `code_verifier` doesn't match the `code_challenge`.                                  |
| `invalid_client`                                | Wrong client secret, or you regenerated it and didn't update your app.                                                        |
| Consent screen keeps appearing                  | Normal for untrusted (third-party) apps. Only first-party STS apps skip the prompt.                                           |
| 401 on API calls                                | Token expired. Refresh it. Also confirm you're sending `Authorization: Bearer <token>` (note the space).                      |
| 403 on API calls                                | Token is valid but lacks the required scope. Re-authorize with the broader scope list.                                        |
| Can't register — "restricted to administrators" | Expected. Registration is handled by STS Cloud staff — email us (see Step 1).                                                 |

***

### Quick reference

Copy-paste values for an OAuth 2.0 connector:

```
Authorization URL:  https://interfaces.stscloud.com/oauth/authorize
Token URL:          https://interfaces.stscloud.com/oauth/token
Revoke URL:         https://interfaces.stscloud.com/oauth/revoke
Discovery URL:      https://interfaces.stscloud.com/.well-known/oauth-authorization-server
Token placement:    Authorization header, "Bearer <token>"
PKCE:               S256 (required unless we disable it for your app)
Default scopes:     public
Scope separator:    space
```

***

### Getting help

* **Registration & credentials:** your STS Cloud account contact or `support@salesandcatering.com`.
* **API questions:** reference the API endpoint documentation (separate guides) or contact us.
* **Security issues:** please email `support@salesandcatering.com` rather than filing a public issue.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://api.salesandcatering.com/platform-api/introduction-and-authentication.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
