Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .gitbook.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,13 @@ redirects:
core-concepts/connect-webviews: core-concepts/connect-webviews/README.md
capability-guides/access-systems/understanding-acs-differences: capability-guides/access-systems/README.md
capability-guides/thermostats/creating-and-managing-climate-schedules: capability-guides/thermostats/creating-and-managing-thermostat-schedules.md
capability-guides/access-grants: use-cases/granting-access/README.md
capability-guides/access-grants/access-grant-quick-start: use-cases/granting-access/access-grant-quick-start.md
capability-guides/access-grants/creating-an-access-grant-using-entrances: use-cases/granting-access/creating-an-access-grant-using-entrances.md
capability-guides/access-grants/creating-an-access-grant-using-spaces: use-cases/granting-access/creating-an-access-grant-using-spaces.md
capability-guides/access-grants/delivering-access-methods: use-cases/granting-access/delivering-access-methods.md
capability-guides/access-grants/reservation-access-grants: use-cases/granting-access/reservation-access-grants.md
capability-guides/access-grants/retrieving-access-grants-and-access-methods: use-cases/granting-access/retrieving-access-grants-and-access-methods.md
capability-guides/access-grants/updating-an-access-grant: use-cases/granting-access/updating-an-access-grant.md
capability-guides/access-grants/revoking-an-access-method: use-cases/granting-access/revoking-an-access-method.md
capability-guides/access-grants/deleting-an-access-grant: use-cases/granting-access/deleting-an-access-grant.md
32 changes: 32 additions & 0 deletions codegen/data/code-sample-definitions/access_grants.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,36 @@
---
- title: Create an Access Grant for devices
description:
Creates a new Access Grant that gives a user identity a PIN code on one
or more devices, such as standalone smart locks.
request:
path: /access_grants/create
parameters:
user_identity_id: e3d736c1-540d-4d10-83e5-9a4e135453b4
device_ids:
- 6ba7b811-9dad-11d1-80b4-00c04fd430c8
requested_access_methods:
- mode: code
starts_at: '2025-06-16T16:54:17.946606Z'
ends_at: '2025-06-18T16:54:17.946606Z'
response:
body:
access_grant:
access_grant_id: ef83cca9-5fdf-4ac2-93f3-c21c5a8be54b
access_method_ids:
- a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d
created_at: '2025-06-16T16:54:17.946606Z'
display_name: My Access Grant
ends_at: '2025-06-18T16:54:17.946606Z'
requested_access_methods:
- display_name: PIN Code Credential
mode: code
created_at: '2025-06-16T16:54:17.946606Z'
created_access_method_ids:
- a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d
starts_at: '2025-06-16T16:54:17.946606Z'
user_identity_id: e3d736c1-540d-4d10-83e5-9a4e135453b4
workspace_id: 750fc0bc-4450-4356-8d9f-18c6a3a6b2c7
- title: Create an Access Grant using spaces
description: Creates a new Access Grant using space IDs and an existing user identity.
request:
Expand Down
37 changes: 37 additions & 0 deletions codegen/validate-links.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { existsSync, readdirSync, readFileSync } from 'node:fs'
import { dirname, join, resolve } from 'node:path'

import YAML from 'yaml'

import {
baseUrl,
type SiteSection,
Expand All @@ -12,6 +14,36 @@ function findSiteSection(filePath: string): SiteSection | undefined {
return siteSections.find(({ root }) => filePath.startsWith(root + '/'))
}

// Each site section has its own .gitbook.yaml with a redirects map.
// A URL covered by a redirect is not broken: GitBook resolves it.
// (validate-redirects separately ensures every redirect target exists.)
const sectionConfigPaths: Record<string, string> = {
Guides: '.gitbook.yaml',
'API Reference': join('docs', 'api-reference', '.gitbook.yaml'),
'Brand Guides': join('docs', 'brand-guides', '.gitbook.yaml'),
}

const sectionRedirects = new Map<string, Set<string>>()

function getSectionRedirects(sectionName: string): Set<string> {
const cached = sectionRedirects.get(sectionName)
if (cached != null) return cached

const redirectPaths = new Set<string>()
const configPath = sectionConfigPaths[sectionName]
if (configPath != null && existsSync(configPath)) {
const config = YAML.parse(readFileSync(configPath, 'utf-8')) as {
redirects?: Record<string, string>
}
for (const key of Object.keys(config.redirects ?? {})) {
redirectPaths.add(key.replace(/^\//, ''))
}
}

sectionRedirects.set(sectionName, redirectPaths)
return redirectPaths
}

const absoluteUrlPattern = new RegExp(
`${baseUrl.replaceAll('.', '\\.')}[^)"<>\\s]+`,
'g',
Expand Down Expand Up @@ -83,6 +115,11 @@ function checkAbsoluteUrl(file: string, line: number, rawUrl: string): void {
const targetMd = `${targetRoot}.md`
const targetReadme = join(targetRoot, 'README.md')

// A URL covered by a .gitbook.yaml redirect resolves on the published site.
if (getSectionRedirects(section.name).has(pagePath.replace(/^\//, ''))) {
return
}

if (!existsSync(targetMd) && !existsSync(targetReadme)) {
brokenLinks.push({
file,
Expand Down
120 changes: 120 additions & 0 deletions docs/api-reference/_blueprint.json
Original file line number Diff line number Diff line change
Expand Up @@ -5064,6 +5064,126 @@
],
"workspaceScope": "required",
"codeSamples": [
{
"title": "Create an Access Grant for devices",
"description": "Creates a new Access Grant that gives a user identity a PIN code on one or more devices, such as standalone smart locks.",
"request": {
"path": "/access_grants/create",
"parameters": {
"user_identity_id": "e3d736c1-540d-4d10-83e5-9a4e135453b4",
"device_ids": [
"6ba7b811-9dad-11d1-80b4-00c04fd430c8"
],
"requested_access_methods": [
{
"mode": "code"
}
],
"starts_at": "2025-06-16T16:54:17.946606Z",
"ends_at": "2025-06-18T16:54:17.946606Z"
}
},
"response": {
"body": {
"access_grant": {
"access_grant_id": "ef83cca9-5fdf-4ac2-93f3-c21c5a8be54b",
"access_method_ids": [
"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d"
],
"created_at": "2025-06-16T16:54:17.946606Z",
"display_name": "My Access Grant",
"ends_at": "2025-06-18T16:54:17.946606Z",
"requested_access_methods": [
{
"display_name": "PIN Code Credential",
"mode": "code",
"created_at": "2025-06-16T16:54:17.946606Z",
"created_access_method_ids": [
"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d"
]
}
],
"starts_at": "2025-06-16T16:54:17.946606Z",
"user_identity_id": "e3d736c1-540d-4d10-83e5-9a4e135453b4",
"workspace_id": "750fc0bc-4450-4356-8d9f-18c6a3a6b2c7"
}
}
},
"code": {
"javascript": {
"title": "JavaScript",
"sdkName": "javascript",
"request": "await seam.accessGrants.create({\n user_identity_id: \"e3d736c1-540d-4d10-83e5-9a4e135453b4\",\n device_ids: [\"6ba7b811-9dad-11d1-80b4-00c04fd430c8\"],\n requested_access_methods: [{ mode: \"code\" }],\n starts_at: \"2025-06-16T16:54:17.946606Z\",\n ends_at: \"2025-06-18T16:54:17.946606Z\",\n});",
"response": "{\n \"access_grant_id\": \"ef83cca9-5fdf-4ac2-93f3-c21c5a8be54b\",\n \"access_method_ids\": [\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"],\n \"created_at\": \"2025-06-16T16:54:17.946606Z\",\n \"display_name\": \"My Access Grant\",\n \"ends_at\": \"2025-06-18T16:54:17.946606Z\",\n \"requested_access_methods\": [\n {\n \"display_name\": \"PIN Code Credential\",\n \"mode\": \"code\",\n \"created_at\": \"2025-06-16T16:54:17.946606Z\",\n \"created_access_method_ids\": [\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"]\n }\n ],\n \"starts_at\": \"2025-06-16T16:54:17.946606Z\",\n \"user_identity_id\": \"e3d736c1-540d-4d10-83e5-9a4e135453b4\",\n \"workspace_id\": \"750fc0bc-4450-4356-8d9f-18c6a3a6b2c7\"\n}",
"request_syntax": "javascript",
"response_syntax": "json"
},
"python": {
"title": "Python",
"sdkName": "python",
"request": "seam.access_grants.create(\n user_identity_id=\"e3d736c1-540d-4d10-83e5-9a4e135453b4\",\n device_ids=[\"6ba7b811-9dad-11d1-80b4-00c04fd430c8\"],\n requested_access_methods=[{\"mode\": \"code\"}],\n starts_at=\"2025-06-16T16:54:17.946606Z\",\n ends_at=\"2025-06-18T16:54:17.946606Z\",\n)",
"response": "AccessGrant(\n access_grant_id=\"ef83cca9-5fdf-4ac2-93f3-c21c5a8be54b\",\n access_method_ids=[\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"],\n created_at=\"2025-06-16T16:54:17.946606Z\",\n display_name=\"My Access Grant\",\n ends_at=\"2025-06-18T16:54:17.946606Z\",\n requested_access_methods=[\n {\n \"display_name\": \"PIN Code Credential\",\n \"mode\": \"code\",\n \"created_at\": \"2025-06-16T16:54:17.946606Z\",\n \"created_access_method_ids\": [\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"],\n }\n ],\n starts_at=\"2025-06-16T16:54:17.946606Z\",\n user_identity_id=\"e3d736c1-540d-4d10-83e5-9a4e135453b4\",\n workspace_id=\"750fc0bc-4450-4356-8d9f-18c6a3a6b2c7\",\n)",
"request_syntax": "python",
"response_syntax": "python"
},
"ruby": {
"title": "Ruby",
"sdkName": "ruby",
"request": "seam.access_grants.create(\n user_identity_id: \"e3d736c1-540d-4d10-83e5-9a4e135453b4\",\n device_ids: [\"6ba7b811-9dad-11d1-80b4-00c04fd430c8\"],\n requested_access_methods: [{ mode: \"code\" }],\n starts_at: \"2025-06-16T16:54:17.946606Z\",\n ends_at: \"2025-06-18T16:54:17.946606Z\",\n)",
"response": "{\n \"access_grant_id\" => \"ef83cca9-5fdf-4ac2-93f3-c21c5a8be54b\",\n \"access_method_ids\" => [\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"],\n \"created_at\" => \"2025-06-16T16:54:17.946606Z\",\n \"display_name\" => \"My Access Grant\",\n \"ends_at\" => \"2025-06-18T16:54:17.946606Z\",\n \"requested_access_methods\" => [\n {\n display_name: \"PIN Code Credential\",\n mode: \"code\",\n created_at: \"2025-06-16T16:54:17.946606Z\",\n created_access_method_ids: [\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"],\n },\n ],\n \"starts_at\" => \"2025-06-16T16:54:17.946606Z\",\n \"user_identity_id\" => \"e3d736c1-540d-4d10-83e5-9a4e135453b4\",\n \"workspace_id\" => \"750fc0bc-4450-4356-8d9f-18c6a3a6b2c7\",\n}",
"request_syntax": "ruby",
"response_syntax": "ruby"
},
"php": {
"title": "PHP",
"sdkName": "php",
"request": "$seam->access_grants->create(\n user_identity_id: \"e3d736c1-540d-4d10-83e5-9a4e135453b4\",\n device_ids: [\"6ba7b811-9dad-11d1-80b4-00c04fd430c8\"],\n requested_access_methods: [[\"mode\" => \"code\"]],\n starts_at: \"2025-06-16T16:54:17.946606Z\",\n ends_at: \"2025-06-18T16:54:17.946606Z\",\n);",
"response": "[\n \"access_grant_id\" => \"ef83cca9-5fdf-4ac2-93f3-c21c5a8be54b\",\n \"access_method_ids\" => [\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"],\n \"created_at\" => \"2025-06-16T16:54:17.946606Z\",\n \"display_name\" => \"My Access Grant\",\n \"ends_at\" => \"2025-06-18T16:54:17.946606Z\",\n \"requested_access_methods\" => [\n [\n \"display_name\" => \"PIN Code Credential\",\n \"mode\" => \"code\",\n \"created_at\" => \"2025-06-16T16:54:17.946606Z\",\n \"created_access_method_ids\" => [\n \"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\",\n ],\n ],\n ],\n \"starts_at\" => \"2025-06-16T16:54:17.946606Z\",\n \"user_identity_id\" => \"e3d736c1-540d-4d10-83e5-9a4e135453b4\",\n \"workspace_id\" => \"750fc0bc-4450-4356-8d9f-18c6a3a6b2c7\",\n];",
"request_syntax": "php",
"response_syntax": "php"
},
"seam_cli": {
"title": "Seam CLI",
"sdkName": "seam_cli",
"request": "seam access-grants create --user_identity_id \"e3d736c1-540d-4d10-83e5-9a4e135453b4\" --device_ids [\"6ba7b811-9dad-11d1-80b4-00c04fd430c8\"] --requested_access_methods [{\"mode\":\"code\"}] --starts_at \"2025-06-16T16:54:17.946606Z\" --ends_at \"2025-06-18T16:54:17.946606Z\"",
"response": "{\n \"access_grant_id\": \"ef83cca9-5fdf-4ac2-93f3-c21c5a8be54b\",\n \"access_method_ids\": [\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"],\n \"created_at\": \"2025-06-16T16:54:17.946606Z\",\n \"display_name\": \"My Access Grant\",\n \"ends_at\": \"2025-06-18T16:54:17.946606Z\",\n \"requested_access_methods\": [\n {\n \"display_name\": \"PIN Code Credential\",\n \"mode\": \"code\",\n \"created_at\": \"2025-06-16T16:54:17.946606Z\",\n \"created_access_method_ids\": [\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"]\n }\n ],\n \"starts_at\": \"2025-06-16T16:54:17.946606Z\",\n \"user_identity_id\": \"e3d736c1-540d-4d10-83e5-9a4e135453b4\",\n \"workspace_id\": \"750fc0bc-4450-4356-8d9f-18c6a3a6b2c7\"\n}",
"request_syntax": "bash",
"response_syntax": "json"
},
"go": {
"title": "Go",
"sdkName": "go",
"request": "package main\n\nimport api \"github.com/seamapi/go\"\n\nfunc main() {\n\tclient.AccessGrants.Create(\n\t\tcontext.Background(),\n\t\tapi.AccessGrantsCreateRequest{\n\t\t\tUserIdentityId: api.String(\"e3d736c1-540d-4d10-83e5-9a4e135453b4\"),\n\t\t\tDeviceIds: [1]string{api.String(\"6ba7b811-9dad-11d1-80b4-00c04fd430c8\")},\n\t\t\tRequestedAccessMethods: [1]api.AccessGrantsCreateRequestRequestedAccessMethodsItem{api.AccessGrantsCreateRequestRequestedAccessMethods{Mode: api.String(\"code\")}},\n\t\t\tStartsAt: api.String(\"2025-06-16T16:54:17.946606Z\"),\n\t\t\tEndsAt: api.String(\"2025-06-18T16:54:17.946606Z\"),\n\t\t},\n\t)\n}",
"response": "api.AccessGrant{AccessGrantId: \"ef83cca9-5fdf-4ac2-93f3-c21c5a8be54b\", AccessMethodIds: []string{\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"}, CreatedAt: \"2025-06-16T16:54:17.946606Z\", DisplayName: \"My Access Grant\", EndsAt: \"2025-06-18T16:54:17.946606Z\", RequestedAccessMethods: []AccessGrantRequestedAccessMethods{api.AccessGrantRequestedAccessMethodsRequestedAccessMethods{DisplayName: \"PIN Code Credential\", Mode: \"code\", CreatedAt: \"2025-06-16T16:54:17.946606Z\", CreatedAccessMethodIds: []string{\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"}}}, StartsAt: \"2025-06-16T16:54:17.946606Z\", UserIdentityId: \"e3d736c1-540d-4d10-83e5-9a4e135453b4\", WorkspaceId: \"750fc0bc-4450-4356-8d9f-18c6a3a6b2c7\"}",
"request_syntax": "go",
"response_syntax": "go"
},
"java": {
"title": "Java",
"sdkName": "java",
"request": "seam.accessGrants().create(AccessGrantsCreateRequest.builder().userIdentityId(\"e3d736c1-540d-4d10-83e5-9a4e135453b4\")\n.deviceIds(List.of(\"6ba7b811-9dad-11d1-80b4-00c04fd430c8\"))\n.requestedAccessMethods(List.of(Map.of(\"mode\", \"code\")))\n.startsAt(\"2025-06-16T16:54:17.946606Z\")\n.endsAt(\"2025-06-18T16:54:17.946606Z\").build());",
"response": "{\n \"access_grant_id\": \"ef83cca9-5fdf-4ac2-93f3-c21c5a8be54b\",\n \"access_method_ids\": [\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"],\n \"created_at\": \"2025-06-16T16:54:17.946606Z\",\n \"display_name\": \"My Access Grant\",\n \"ends_at\": \"2025-06-18T16:54:17.946606Z\",\n \"requested_access_methods\": [\n {\n \"display_name\": \"PIN Code Credential\",\n \"mode\": \"code\",\n \"created_at\": \"2025-06-16T16:54:17.946606Z\",\n \"created_access_method_ids\": [\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"]\n }\n ],\n \"starts_at\": \"2025-06-16T16:54:17.946606Z\",\n \"user_identity_id\": \"e3d736c1-540d-4d10-83e5-9a4e135453b4\",\n \"workspace_id\": \"750fc0bc-4450-4356-8d9f-18c6a3a6b2c7\"\n}",
"request_syntax": "java",
"response_syntax": "json"
},
"csharp": {
"title": "C#",
"sdkName": "csharp",
"request": "seam.AccessGrants.Create(userIdentityId: \"e3d736c1-540d-4d10-83e5-9a4e135453b4\", deviceIds: new string[] { \"6ba7b811-9dad-11d1-80b4-00c04fd430c8\"} , requestedAccessMethods: new object[] { new { mode = \"code\" }} , startsAt: \"2025-06-16T16:54:17.946606Z\", endsAt: \"2025-06-18T16:54:17.946606Z\")",
"response": "{\n \"access_grant_id\": \"ef83cca9-5fdf-4ac2-93f3-c21c5a8be54b\",\n \"access_method_ids\": [\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"],\n \"created_at\": \"2025-06-16T16:54:17.946606Z\",\n \"display_name\": \"My Access Grant\",\n \"ends_at\": \"2025-06-18T16:54:17.946606Z\",\n \"requested_access_methods\": [\n {\n \"display_name\": \"PIN Code Credential\",\n \"mode\": \"code\",\n \"created_at\": \"2025-06-16T16:54:17.946606Z\",\n \"created_access_method_ids\": [\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"]\n }\n ],\n \"starts_at\": \"2025-06-16T16:54:17.946606Z\",\n \"user_identity_id\": \"e3d736c1-540d-4d10-83e5-9a4e135453b4\",\n \"workspace_id\": \"750fc0bc-4450-4356-8d9f-18c6a3a6b2c7\"\n}",
"request_syntax": "csharp",
"response_syntax": "json"
},
"curl": {
"title": "cURL",
"sdkName": "curl",
"request": "curl --include --request POST \"https://connect.getseam.com/access_grants/create\" \\\n --header \"Authorization: Bearer $SEAM_API_KEY\" \\\n --json @- <<EOF\n{\n \"user_identity_id\": \"e3d736c1-540d-4d10-83e5-9a4e135453b4\",\n \"device_ids\": [\n \"6ba7b811-9dad-11d1-80b4-00c04fd430c8\"\n ],\n \"requested_access_methods\": [\n {\n \"mode\": \"code\"\n }\n ],\n \"starts_at\": \"2025-06-16T16:54:17.946606Z\",\n \"ends_at\": \"2025-06-18T16:54:17.946606Z\"\n}\nEOF",
"response": "{\n \"access_grant\": {\n \"access_grant_id\": \"ef83cca9-5fdf-4ac2-93f3-c21c5a8be54b\",\n \"access_method_ids\": [\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"],\n \"created_at\": \"2025-06-16T16:54:17.946606Z\",\n \"display_name\": \"My Access Grant\",\n \"ends_at\": \"2025-06-18T16:54:17.946606Z\",\n \"requested_access_methods\": [\n {\n \"display_name\": \"PIN Code Credential\",\n \"mode\": \"code\",\n \"created_at\": \"2025-06-16T16:54:17.946606Z\",\n \"created_access_method_ids\": [\"a1b2c3d4-e5f6-4a3b-2c1d-0e9f8a7b6c5d\"]\n }\n ],\n \"starts_at\": \"2025-06-16T16:54:17.946606Z\",\n \"user_identity_id\": \"e3d736c1-540d-4d10-83e5-9a4e135453b4\",\n \"workspace_id\": \"750fc0bc-4450-4356-8d9f-18c6a3a6b2c7\"\n }\n}",
"request_syntax": "bash",
"response_syntax": "json"
}
}
},
{
"title": "Create an Access Grant using spaces",
"description": "Creates a new Access Grant using space IDs and an existing user identity.",
Expand Down
Loading
Loading