diff --git a/_snippets/graphql/add-members-to-tier.mdx b/_snippets/graphql/add-members-to-tier.mdx
index 2aaae95..9f550a4 100644
--- a/_snippets/graphql/add-members-to-tier.mdx
+++ b/_snippets/graphql/add-members-to-tier.mdx
@@ -37,7 +37,7 @@ mutation addMembersToTier($input: AddMembersToTierInput!) {
"companyId": "co_123"
}
],
- "tierId": "tier_123"
+ "tierIdentifier": { "externalId": "XXX" }
}
}
```
diff --git a/_snippets/graphql/remove-members-from-tier.mdx b/_snippets/graphql/remove-members-from-tier.mdx
index d2bb4a8..87e7f5e 100644
--- a/_snippets/graphql/remove-members-from-tier.mdx
+++ b/_snippets/graphql/remove-members-from-tier.mdx
@@ -25,8 +25,7 @@ mutation removeMembersFromTier($input: RemoveMembersFromTierInput!) {
{
"companyId": "co_123"
}
- ],
- "tierId": "tier_123"
+ ]
}
}
```
diff --git a/_snippets/typescript-sdk/add-members-to-tier.mdx b/_snippets/typescript-sdk/add-members-to-tier.mdx
index 8a6651f..48fdc57 100644
--- a/_snippets/typescript-sdk/add-members-to-tier.mdx
+++ b/_snippets/typescript-sdk/add-members-to-tier.mdx
@@ -12,7 +12,7 @@ const res = await client.addMembersToTier({
companyId: 'co_123',
},
],
- tierId: 'tier_123',
+ tierIdentifier: { externalId: 'XXX' },
});
if (res.error) {
diff --git a/_snippets/typescript-sdk/remove-members-from-tier.mdx b/_snippets/typescript-sdk/remove-members-from-tier.mdx
index 93c5e6b..9169b0d 100644
--- a/_snippets/typescript-sdk/remove-members-from-tier.mdx
+++ b/_snippets/typescript-sdk/remove-members-from-tier.mdx
@@ -12,7 +12,6 @@ const res = await client.removeMembersFromTier({
companyId: 'co_123',
},
],
- tierId: 'tier_123',
});
if (res.error) {
diff --git a/api-reference/graphql/threads/thread-fields.mdx b/api-reference/graphql/threads/thread-fields.mdx
index c892076..4965b4e 100644
--- a/api-reference/graphql/threads/thread-fields.mdx
+++ b/api-reference/graphql/threads/thread-fields.mdx
@@ -10,7 +10,12 @@ Thread fields can be required. When they are required, their value must be set i
For interacting with thread fields via the API, every field has a `key` defined in its schema. Keys make it possible to quickly refer to a thread field without having to know its ID in the schema. For example if you have a field called "Product Area" the key you might choose for the key to be `product_area`.
-### Upsert a field
+### Upsert a thread field
+
+To upsert a thread field you need an API key with the following permissions:
+
+- `threadField:create`
+- `threadField:update`
@@ -21,7 +26,11 @@ For interacting with thread fields via the API, every field has a `key` defined
-### Delete a field
+### Delete a thread field
+
+To delete a thread field you need an API key with the following permissions:
+
+- `threadField:delete`
diff --git a/api-reference/graphql/tiers/add-members.mdx b/api-reference/graphql/tiers/add-members.mdx
index 24896e9..71f01ff 100644
--- a/api-reference/graphql/tiers/add-members.mdx
+++ b/api-reference/graphql/tiers/add-members.mdx
@@ -5,6 +5,8 @@ sidebarTitle: 'Add companies & tenants'
You can add multiple tenants and companies to a tier in a single mutation.
+Companies and tenants can only be in a single tier.
+
For this mutation you need the following permissions:
- `tierMembership:read`
diff --git a/api-reference/graphql/tiers/remove-members.mdx b/api-reference/graphql/tiers/remove-members.mdx
index 255f952..c2ac7df 100644
--- a/api-reference/graphql/tiers/remove-members.mdx
+++ b/api-reference/graphql/tiers/remove-members.mdx
@@ -3,7 +3,7 @@ title: 'Remove companies and tenants to tiers'
sidebarTitle: 'Remove companies & tenants'
---
-You can remove companies and tenants from a tier manually in the UI or via the API.
+You can remove companies and tenants from the tiers they are part of manually in the UI or via the API.
For this mutation you need the following permissions:
diff --git a/api-reference/webhooks.mdx b/api-reference/webhooks.mdx
index ee24ea9..41483f7 100644
--- a/api-reference/webhooks.mdx
+++ b/api-reference/webhooks.mdx
@@ -88,7 +88,7 @@ being processed.
Webhook requests are sent as an `HTTP POST` request to the webhook target URL.
-### Headers [#headers]
+### Headers
- `Accept`: `application/json`
- `Content-Type`: `application/json`
@@ -119,7 +119,7 @@ The JSON schema for Plain the webhook request body can be found [here](https://c
| `workspaceId` | `string` | The ID of the workspace where the Plain event originated |
| `payload` | `object` | The Plain event's payload [(Example)](/api-reference/webhooks/thread-created); |
-### Webhook Metadata [#webhook-metadata]
+### Webhook Metadata
All the following fields are also sent as [HTTP headers](#headers).
diff --git a/api-reference/webhooks/typescript.mdx b/api-reference/webhooks/typescript.mdx
new file mode 100644
index 0000000..7a333e0
--- /dev/null
+++ b/api-reference/webhooks/typescript.mdx
@@ -0,0 +1,36 @@
+---
+title: 'Webhooks and Typescript'
+sidebarTitle: 'Using Typescript'
+---
+
+When using webhooks with Typescript, you can use a utility called `parsePlainWebhook` in the Typescript SDK to parse the webhook requests.
+
+This makes sure your code is 100% type safe and that all requests are correctly validated.
+
+```ts
+import Express from 'express';
+import { parsePlainWebhook } from '@team-plain/typescript-sdk';
+
+const app = Express();
+
+app.post('/handler/', function (req: Express.Request, res: Express.Response) {
+ const parseResult = parsePlainWebhook(req.body);
+
+ // If this errors it means the request is not valid
+ // you can safely ignore it!
+ if (parseResult.error) {
+ res.status(400);
+ return;
+ }
+
+ // This is now fully typed and safe to use.
+ const webhookBody = parseResult.data;
+
+ // You can use the eventType to filter down to a specific event type
+ if (webhookBody.payload.eventType === 'thread.thread_created') {
+ console.log(webhookBody.payload.thread.id);
+ }
+
+ res.status(200);
+});
+```
diff --git a/mint.json b/mint.json
index 55e89d9..b05787c 100644
--- a/mint.json
+++ b/mint.json
@@ -217,6 +217,7 @@
"group": "Webhooks",
"pages": [
"api-reference/webhooks",
+ "api-reference/webhooks/typescript",
"api-reference/webhooks/thread-created",
"api-reference/webhooks/thread-status-transitioned",
"api-reference/webhooks/thread-assignment-transitioned",
diff --git a/tiers.mdx b/tiers.mdx
index 90b1e7b..c59ba58 100644
--- a/tiers.mdx
+++ b/tiers.mdx
@@ -21,3 +21,9 @@ When configuring an SLA you can set when you want to be warned of a breach. For
SLAs can also be driven by priority of threads. This allows you to have a different SLAs for "Urgent" vs "Normal" priority threads. If you have configure multiple SLAs for the same priority then only the first SLA will apply.
If you want to create a 'default' SLA then you can need to first create a tier and make that the default in your settings. Then you can configure SLAs like you would on any other tier.
+
+### Business hours
+
+By default SLAs apply at all times. They can be configured to only count working hours by toggling on **Only during business hours**.
+
+To configure business hours go to **Settings** → **Business hours**