@foxscheduling/sdk 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +210 -11
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -2,27 +2,105 @@
2
2
 
3
3
  Official Node.js SDK for the [Fox Scheduling Partner API](https://foxscheduling.com/developers).
4
4
 
5
+ Use this package to read and manage bookings, customers, availability, and more on behalf of a Fox Scheduling business — from your own server or integration.
6
+
7
+ **Requirements:** Node.js 18+
8
+
9
+ **Full API reference:** [foxscheduling.com/developers](https://foxscheduling.com/developers)
10
+
11
+ ---
12
+
5
13
  ## Install
6
14
 
7
15
  ```bash
8
16
  npm install @foxscheduling/sdk @foxscheduling/shared
9
17
  ```
10
18
 
11
- ## API key (single business)
19
+ Both packages are required. `@foxscheduling/shared` provides shared types and scope names.
20
+
21
+ ---
22
+
23
+ ## Choose how to authenticate
24
+
25
+ | Method | Best for | Dashboard setup |
26
+ | --- | --- | --- |
27
+ | **API key** | Scripts, cron jobs, or automation for **your own** Fox business | [Developers → API keys](https://foxscheduling.com/dashboard/developers?tab=api-keys) |
28
+ | **OAuth** | SaaS apps where **other people** connect their Fox business to your product | [Developers → OAuth apps](https://foxscheduling.com/dashboard/developers) |
29
+
30
+ If you only need to access a business you own, start with an **API key**. It is the fastest path.
31
+
32
+ ---
33
+
34
+ ## Quick start: API key
35
+
36
+ ### 1. Create a key
37
+
38
+ 1. Sign in to [Fox Scheduling](https://foxscheduling.com).
39
+ 2. Open **Developers → API keys**.
40
+ 3. Pick the business, choose scopes (e.g. `business:read`, `bookings:read`), and create a key.
41
+ 4. Copy the key immediately — it is shown only once. Keys look like `fx_live_...`.
42
+
43
+ ### 2. Call the API
12
44
 
13
45
  ```typescript
14
46
  import { FoxScheduling } from "@foxscheduling/sdk";
15
47
 
16
48
  const fox = new FoxScheduling({
17
- auth: { type: "apiKey", apiKey: process.env.FOX_API_KEY! },
49
+ auth: {
50
+ type: "apiKey",
51
+ apiKey: process.env.FOX_API_KEY!, // fx_live_...
52
+ },
18
53
  });
19
54
 
55
+ // Example: read the connected business profile
20
56
  const business = await fox.business.get();
57
+ console.log(business.name);
58
+ ```
59
+
60
+ ### Available resources
61
+
62
+ After creating a client, use:
63
+
64
+ - `fox.business` — business profile
65
+ - `fox.services` — services
66
+ - `fox.staff` — staff members
67
+ - `fox.availability` — availability rules
68
+ - `fox.bookings` — bookings
69
+ - `fox.customers` — customers
70
+ - `fox.webhooks` — webhook subscriptions
71
+
72
+ All methods return typed data and throw on API errors.
73
+
74
+ ---
75
+
76
+ ## OAuth: connect other users' businesses
77
+
78
+ Use OAuth when you are building an integration (e.g. a CRM or reporting tool) and Fox Scheduling **users** need to authorize your app to access **their** business.
79
+
80
+ OAuth is a browser-based flow. At a high level:
81
+
21
82
  ```
83
+ Your app Fox Scheduling User's browser
84
+ | | |
85
+ |-- 1. Build authorize URL --->| |
86
+ |-- 2. Redirect user -------------------------------------->|
87
+ | |<-- 3. User signs in & allows
88
+ |<-- 4. Redirect to your URL with ?code=... ---------------|
89
+ |-- 5. Exchange code for tokens ->| |
90
+ |-- 6. Call Partner API with stored tokens |
91
+ ```
92
+
93
+ You never type the authorization `code` yourself. Fox appends it to your redirect URL after the user clicks **Allow**.
94
+
95
+ ### Before you write code
22
96
 
23
- Create keys under **SettingsAPI keys** in the Fox Scheduling dashboard.
97
+ 1. Create an OAuth app under **DevelopersOAuth apps**.
98
+ 2. Note the **client ID** and **client secret** (secret is shown once).
99
+ 3. Add a **redirect URI** — the exact URL Fox will send users back to, e.g. `https://your-app.com/oauth/callback`. It must match character-for-character in your code.
24
100
 
25
- ## OAuth (multi-tenant integrations)
101
+ ### Step 1 — Send the user to Fox
102
+
103
+ Create the SDK client and build the authorization URL:
26
104
 
27
105
  ```typescript
28
106
  import { FoxScheduling, FileTokenStore } from "@foxscheduling/sdk";
@@ -32,27 +110,148 @@ const fox = new FoxScheduling({
32
110
  type: "oauth",
33
111
  clientId: process.env.FOX_CLIENT_ID!,
34
112
  clientSecret: process.env.FOX_CLIENT_SECRET!,
35
- redirectUri: "https://your-domain.com/oauth/callback",
113
+ redirectUri: "https://your-app.com/oauth/callback", // must match dashboard
36
114
  tokenStore: new FileTokenStore("./fox-tokens.json"),
37
115
  },
38
116
  });
39
117
 
40
- const { url, codeVerifier } = fox.oauth!.getAuthorizationUrl({
118
+ const { url, codeVerifier, state } = fox.oauth!.getAuthorizationUrl({
41
119
  scopes: ["business:read", "bookings:read"],
42
120
  });
43
- // Redirect user to url, then on callback:
44
- await fox.oauth!.exchangeCode(code, codeVerifier);
45
121
  ```
46
122
 
47
- ## Webhook verification
123
+ **Important:** Before redirecting the user, save `codeVerifier` and `state` somewhere tied to that user session (memory, Redis, database, encrypted cookie, etc.). You need them on the next step.
124
+
125
+ Then redirect the user's browser to `url` (e.g. `res.redirect(url)` in Express).
126
+
127
+ ### Step 2 — Handle the callback
128
+
129
+ When the user approves, Fox redirects to your `redirectUri` with query parameters:
130
+
131
+ ```
132
+ https://your-app.com/oauth/callback?code=AUTHORIZATION_CODE&state=SAME_STATE_YOU_SAVED
133
+ ```
134
+
135
+ In your callback route:
136
+
137
+ 1. Read `code` and `state` from the query string.
138
+ 2. Confirm `state` matches what you saved (prevents CSRF).
139
+ 3. Load the saved `codeVerifier` for that session.
140
+ 4. Exchange the code for tokens.
141
+
142
+ ```typescript
143
+ // Example: Express route GET /oauth/callback
144
+ app.get("/oauth/callback", async (req, res) => {
145
+ const code = req.query.code as string | undefined;
146
+ const returnedState = req.query.state as string | undefined;
147
+
148
+ if (!code) {
149
+ return res.status(400).send("Authorization was denied or failed.");
150
+ }
151
+ if (returnedState !== savedState) {
152
+ return res.status(400).send("Invalid state — possible CSRF.");
153
+ }
154
+
155
+ await fox.oauth!.exchangeCode(code, savedCodeVerifier);
156
+
157
+ // Tokens are saved automatically. Redirect to your app.
158
+ res.redirect("/dashboard");
159
+ });
160
+ ```
161
+
162
+ ### Step 3 — Use the API
163
+
164
+ Once `exchangeCode` succeeds, the SDK stores tokens and attaches them to every request. You can call the same resources as with an API key:
165
+
166
+ ```typescript
167
+ const business = await fox.business.get();
168
+ const bookings = await fox.bookings.list();
169
+ ```
170
+
171
+ The SDK refreshes access tokens automatically before they expire.
172
+
173
+ ### What is `fox-tokens.json`?
174
+
175
+ In the examples above, `FileTokenStore("./fox-tokens.json")` tells the SDK **where to save OAuth tokens on disk**.
176
+
177
+ - **You do not create this file.** The SDK writes it after a successful `exchangeCode`.
178
+ - The path is just an example — use any path you like.
179
+ - **Keep it secret** — it contains refresh tokens. Add it to `.gitignore`.
180
+ - **One file = one connection.** Fine for local scripts or a single test business.
181
+
182
+ Example contents (written by the SDK):
183
+
184
+ ```json
185
+ {
186
+ "accessToken": "eyJhbGciOiJSUzI1NiIs...",
187
+ "refreshToken": "opaque-refresh-token",
188
+ "expiresAt": 1710003600000,
189
+ "scope": "business:read bookings:read",
190
+ "tokenType": "Bearer"
191
+ }
192
+ ```
193
+
194
+ ### Production OAuth apps
195
+
196
+ If many Fox users will connect their businesses, **do not** use one shared file. Implement the `TokenStore` interface and save tokens in your database, keyed by your user ID (or Fox `tenant_id`):
197
+
198
+ ```typescript
199
+ import type { TokenStore, TokenSet } from "@foxscheduling/sdk";
200
+
201
+ class DatabaseTokenStore implements TokenStore {
202
+ constructor(private userId: string) {}
203
+ async load(): Promise<TokenSet | null> { /* read from DB */ }
204
+ async save(tokens: TokenSet): Promise<void> { /* write to DB */ }
205
+ async clear(): Promise<void> { /* delete from DB */ }
206
+ }
207
+ ```
208
+
209
+ For unit tests, use `MemoryTokenStore()` (tokens disappear when the process exits).
210
+
211
+ More detail: [OAuth2 integration guide](https://foxscheduling.com/developers/oauth2)
212
+
213
+ ---
214
+
215
+ ## Webhook signature verification
216
+
217
+ When Fox sends a webhook to your server, verify the `X-Fox-Signature` header:
48
218
 
49
219
  ```typescript
50
220
  import { verifyFoxWebhookSignature } from "@foxscheduling/sdk";
51
221
 
52
222
  const ok = verifyFoxWebhookSignature({
53
- secret: webhookSecret,
223
+ secret: process.env.FOX_WEBHOOK_SECRET!,
54
224
  timestamp: req.headers["x-fox-timestamp"],
55
- rawBody: req.rawBody,
225
+ rawBody: req.rawBody, // unparsed request body string
56
226
  signatureHex: req.headers["x-fox-signature"],
57
227
  });
228
+
229
+ if (!ok) {
230
+ return res.status(401).send("Invalid signature");
231
+ }
58
232
  ```
233
+
234
+ Your HTTP framework must give you the **raw** body (before JSON parsing) for verification to work.
235
+
236
+ ---
237
+
238
+ ## Scopes
239
+
240
+ Each API key or OAuth request uses scopes such as:
241
+
242
+ `business:read`, `services:read`, `staff:read`, `availability:read`, `availability:write`, `bookings:read`, `bookings:write`, `customers:read`, `customers:write`, `webhooks:read`, `webhooks:write`
243
+
244
+ Request only the scopes your integration needs. See the [scope reference](https://foxscheduling.com/developers/oauth2#scopes).
245
+
246
+ ---
247
+
248
+ ## Links
249
+
250
+ - [Developers hub](https://foxscheduling.com/developers)
251
+ - [OAuth2 guide](https://foxscheduling.com/developers/oauth2)
252
+ - [API key guide](https://foxscheduling.com/developers/api-key)
253
+ - [Developers dashboard](https://foxscheduling.com/dashboard/developers)
254
+
255
+ ## Support
256
+
257
+ Questions or integration help: [foxscheduling.com/contact](https://foxscheduling.com/contact)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foxscheduling/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Official Fox Scheduling Partner API SDK",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.cjs",