or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

block-operations.mdclient-configuration.mdcomments.mddata-source-operations.mddatabase-operations.mderror-handling.mdfile-uploads.mdindex.mdoauth-authentication.mdpage-operations.mdpagination-helpers.mdsearch.mduser-management.md

oauth-authentication.mddocs/

0

# OAuth Authentication

1

2

Complete OAuth flow implementation for Notion app integrations including token exchange and management.

3

4

## Capabilities

5

6

### Exchange Authorization Code for Access Token

7

8

Exchange an authorization code for an access token during the OAuth flow.

9

10

```typescript { .api }

11

/**

12

* Exchange authorization code for access token

13

* @param args - OAuth token exchange parameters

14

* @returns Promise resolving to token response

15

*/

16

oauth.token(args: OauthTokenParameters): Promise<OauthTokenResponse>;

17

18

interface OauthTokenParameters {

19

/** OAuth grant type */

20

grant_type: "authorization_code";

21

/** Authorization code from callback */

22

code: string;

23

/** Redirect URI used in authorization */

24

redirect_uri?: string;

25

}

26

27

interface OauthTokenResponse {

28

/** Access token for API requests */

29

access_token: string;

30

/** Token type (always "bearer") */

31

token_type: "bearer";

32

/** Bot user ID associated with the integration */

33

bot_id: string;

34

/** Workspace information */

35

workspace_name?: string;

36

workspace_id?: string;

37

workspace_icon?: string;

38

/** Owner information */

39

owner: {

40

type: "workspace" | "user";

41

user?: {

42

object: "user";

43

id: string;

44

name?: string;

45

avatar_url?: string;

46

type: "person";

47

person?: {

48

email?: string;

49

};

50

};

51

};

52

/** Duplicate properties for legacy compatibility */

53

duplicated_template_id?: string;

54

request_id: string;

55

}

56

```

57

58

**Usage Examples:**

59

60

```typescript

61

// Exchange authorization code for access token

62

const tokenResponse = await notion.oauth.token({

63

grant_type: "authorization_code",

64

code: "authorization-code-from-callback",

65

redirect_uri: "https://yourapp.com/oauth/callback",

66

});

67

68

console.log(tokenResponse.access_token); // Use this for API requests

69

console.log(tokenResponse.workspace_name); // Workspace name

70

console.log(tokenResponse.bot_id); // Bot user ID

71

72

// Create new client with access token

73

const authorizedNotion = new Client({

74

auth: tokenResponse.access_token,

75

});

76

```

77

78

### Revoke Access Token

79

80

Revoke an access token, ending the authorization for the integration.

81

82

```typescript { .api }

83

/**

84

* Revoke an access token

85

* @param args - OAuth token revocation parameters

86

* @returns Promise resolving to revocation response

87

*/

88

oauth.revoke(args: OauthRevokeParameters): Promise<OauthRevokeResponse>;

89

90

interface OauthRevokeParameters {

91

/** Access token to revoke */

92

token: string;

93

}

94

95

interface OauthRevokeResponse {

96

/** Always returns empty object on success */

97

}

98

```

99

100

**Usage Examples:**

101

102

```typescript

103

// Revoke access token

104

await notion.oauth.revoke({

105

token: "access-token-to-revoke",

106

});

107

108

console.log("Token revoked successfully");

109

```

110

111

### Introspect Access Token

112

113

Get information about an access token including its validity and associated workspace.

114

115

```typescript { .api }

116

/**

117

* Introspect an access token

118

* @param args - OAuth token introspection parameters

119

* @returns Promise resolving to introspection response

120

*/

121

oauth.introspect(args: OauthIntrospectParameters): Promise<OauthIntrospectResponse>;

122

123

interface OauthIntrospectParameters {

124

/** Access token to introspect */

125

token: string;

126

}

127

128

interface OauthIntrospectResponse {

129

/** Whether the token is active/valid */

130

active: boolean;

131

/** Token type */

132

token_type?: "bearer";

133

/** Bot user ID */

134

bot_id?: string;

135

/** Workspace information */

136

workspace_name?: string;

137

workspace_id?: string;

138

workspace_icon?: string;

139

/** Owner information */

140

owner?: {

141

type: "workspace" | "user";

142

user?: {

143

object: "user";

144

id: string;

145

name?: string;

146

avatar_url?: string;

147

type: "person";

148

person?: {

149

email?: string;

150

};

151

};

152

};

153

}

154

```

155

156

**Usage Examples:**

157

158

```typescript

159

// Check if token is valid

160

const introspection = await notion.oauth.introspect({

161

token: "access-token-to-check",

162

});

163

164

if (introspection.active) {

165

console.log("Token is valid");

166

console.log(`Workspace: ${introspection.workspace_name}`);

167

console.log(`Bot ID: ${introspection.bot_id}`);

168

} else {

169

console.log("Token is invalid or expired");

170

}

171

172

// Validate token before making API calls

173

async function validateAndUseToken(token: string) {

174

const introspection = await notion.oauth.introspect({ token });

175

176

if (!introspection.active) {

177

throw new Error("Token is invalid");

178

}

179

180

// Token is valid, use it for API calls

181

const client = new Client({ auth: token });

182

return client;

183

}

184

```

185

186

## Complete OAuth Flow Example

187

188

```typescript

189

import { Client } from "@notionhq/client";

190

191

// OAuth configuration

192

const CLIENT_ID = "your-oauth-client-id";

193

const CLIENT_SECRET = "your-oauth-client-secret";

194

const REDIRECT_URI = "https://yourapp.com/oauth/callback";

195

196

// Step 1: Redirect user to Notion OAuth URL

197

function getAuthorizationUrl() {

198

const baseUrl = "https://api.notion.com/v1/oauth/authorize";

199

const params = new URLSearchParams({

200

client_id: CLIENT_ID,

201

response_type: "code",

202

owner: "user", // or "workspace"

203

redirect_uri: REDIRECT_URI,

204

});

205

206

return `${baseUrl}?${params.toString()}`;

207

}

208

209

// Step 2: Handle OAuth callback and exchange code for token

210

async function handleOAuthCallback(code: string) {

211

// Create client with client credentials for token exchange

212

const notion = new Client();

213

214

const tokenResponse = await notion.oauth.token({

215

grant_type: "authorization_code",

216

code: code,

217

redirect_uri: REDIRECT_URI,

218

});

219

220

// Store the access token securely

221

const accessToken = tokenResponse.access_token;

222

223

// Create authenticated client for user

224

const userNotion = new Client({

225

auth: accessToken,

226

});

227

228

return {

229

client: userNotion,

230

tokenInfo: tokenResponse,

231

};

232

}

233

234

// Step 3: Validate token periodically

235

async function validateStoredToken(token: string) {

236

const notion = new Client();

237

238

const introspection = await notion.oauth.introspect({

239

token: token,

240

});

241

242

return introspection.active;

243

}

244

245

// Step 4: Revoke token when user disconnects

246

async function disconnectIntegration(token: string) {

247

const notion = new Client();

248

249

await notion.oauth.revoke({

250

token: token,

251

});

252

253

console.log("Integration disconnected");

254

}

255

```

256

257

## OAuth Client Authentication

258

259

For OAuth endpoints, the client must be configured with client credentials:

260

261

```typescript

262

// Configure client for OAuth operations

263

const oauthClient = new Client({

264

auth: {

265

client_id: "your-client-id",

266

client_secret: "your-client-secret",

267

},

268

});

269

270

// Or use the generic request method

271

const tokenResponse = await notion.request({

272

path: "oauth/token",

273

method: "post",

274

body: {

275

grant_type: "authorization_code",

276

code: "auth-code",

277

redirect_uri: "redirect-uri",

278

},

279

auth: {

280

client_id: "your-client-id",

281

client_secret: "your-client-secret",

282

},

283

});

284

```

285

286

## Types

287

288

```typescript { .api }

289

interface OauthTokenParameters {

290

grant_type: "authorization_code";

291

code: string;

292

redirect_uri?: string;

293

}

294

295

interface OauthTokenResponse {

296

access_token: string;

297

token_type: "bearer";

298

bot_id: string;

299

workspace_name?: string;

300

workspace_id?: string;

301

workspace_icon?: string;

302

owner: {

303

type: "workspace" | "user";

304

user?: {

305

object: "user";

306

id: string;

307

name?: string;

308

avatar_url?: string;

309

type: "person";

310

person?: {

311

email?: string;

312

};

313

};

314

};

315

duplicated_template_id?: string;

316

request_id: string;

317

}

318

319

interface OauthRevokeParameters {

320

token: string;

321

}

322

323

interface OauthRevokeResponse {

324

// Empty object on success

325

}

326

327

interface OauthIntrospectParameters {

328

token: string;

329

}

330

331

interface OauthIntrospectResponse {

332

active: boolean;

333

token_type?: "bearer";

334

bot_id?: string;

335

workspace_name?: string;

336

workspace_id?: string;

337

workspace_icon?: string;

338

owner?: {

339

type: "workspace" | "user";

340

user?: {

341

object: "user";

342

id: string;

343

name?: string;

344

avatar_url?: string;

345

type: "person";

346

person?: {

347

email?: string;

348

};

349

};

350

};

351

}

352

```