> For the complete documentation index, see [llms.txt](https://api.salesandcatering.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://api.salesandcatering.com/platform-api/introduction-and-authentication.md).

# 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.
