A simple and easy to use client for the Notion API
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Complete OAuth flow implementation for Notion app integrations including token exchange and management.
Exchange an authorization code for an access token during the OAuth flow.
/**
* Exchange authorization code for access token
* @param args - OAuth token exchange parameters
* @returns Promise resolving to token response
*/
oauth.token(args: OauthTokenParameters): Promise<OauthTokenResponse>;
interface OauthTokenParameters {
/** OAuth grant type */
grant_type: "authorization_code";
/** Authorization code from callback */
code: string;
/** Redirect URI used in authorization */
redirect_uri?: string;
}
interface OauthTokenResponse {
/** Access token for API requests */
access_token: string;
/** Token type (always "bearer") */
token_type: "bearer";
/** Bot user ID associated with the integration */
bot_id: string;
/** Workspace information */
workspace_name?: string;
workspace_id?: string;
workspace_icon?: string;
/** Owner information */
owner: {
type: "workspace" | "user";
user?: {
object: "user";
id: string;
name?: string;
avatar_url?: string;
type: "person";
person?: {
email?: string;
};
};
};
/** Duplicate properties for legacy compatibility */
duplicated_template_id?: string;
request_id: string;
}Usage Examples:
// Exchange authorization code for access token
const tokenResponse = await notion.oauth.token({
grant_type: "authorization_code",
code: "authorization-code-from-callback",
redirect_uri: "https://yourapp.com/oauth/callback",
});
console.log(tokenResponse.access_token); // Use this for API requests
console.log(tokenResponse.workspace_name); // Workspace name
console.log(tokenResponse.bot_id); // Bot user ID
// Create new client with access token
const authorizedNotion = new Client({
auth: tokenResponse.access_token,
});Revoke an access token, ending the authorization for the integration.
/**
* Revoke an access token
* @param args - OAuth token revocation parameters
* @returns Promise resolving to revocation response
*/
oauth.revoke(args: OauthRevokeParameters): Promise<OauthRevokeResponse>;
interface OauthRevokeParameters {
/** Access token to revoke */
token: string;
}
interface OauthRevokeResponse {
/** Always returns empty object on success */
}Usage Examples:
// Revoke access token
await notion.oauth.revoke({
token: "access-token-to-revoke",
});
console.log("Token revoked successfully");Get information about an access token including its validity and associated workspace.
/**
* Introspect an access token
* @param args - OAuth token introspection parameters
* @returns Promise resolving to introspection response
*/
oauth.introspect(args: OauthIntrospectParameters): Promise<OauthIntrospectResponse>;
interface OauthIntrospectParameters {
/** Access token to introspect */
token: string;
}
interface OauthIntrospectResponse {
/** Whether the token is active/valid */
active: boolean;
/** Token type */
token_type?: "bearer";
/** Bot user ID */
bot_id?: string;
/** Workspace information */
workspace_name?: string;
workspace_id?: string;
workspace_icon?: string;
/** Owner information */
owner?: {
type: "workspace" | "user";
user?: {
object: "user";
id: string;
name?: string;
avatar_url?: string;
type: "person";
person?: {
email?: string;
};
};
};
}Usage Examples:
// Check if token is valid
const introspection = await notion.oauth.introspect({
token: "access-token-to-check",
});
if (introspection.active) {
console.log("Token is valid");
console.log(`Workspace: ${introspection.workspace_name}`);
console.log(`Bot ID: ${introspection.bot_id}`);
} else {
console.log("Token is invalid or expired");
}
// Validate token before making API calls
async function validateAndUseToken(token: string) {
const introspection = await notion.oauth.introspect({ token });
if (!introspection.active) {
throw new Error("Token is invalid");
}
// Token is valid, use it for API calls
const client = new Client({ auth: token });
return client;
}import { Client } from "@notionhq/client";
// OAuth configuration
const CLIENT_ID = "your-oauth-client-id";
const CLIENT_SECRET = "your-oauth-client-secret";
const REDIRECT_URI = "https://yourapp.com/oauth/callback";
// Step 1: Redirect user to Notion OAuth URL
function getAuthorizationUrl() {
const baseUrl = "https://api.notion.com/v1/oauth/authorize";
const params = new URLSearchParams({
client_id: CLIENT_ID,
response_type: "code",
owner: "user", // or "workspace"
redirect_uri: REDIRECT_URI,
});
return `${baseUrl}?${params.toString()}`;
}
// Step 2: Handle OAuth callback and exchange code for token
async function handleOAuthCallback(code: string) {
// Create client with client credentials for token exchange
const notion = new Client();
const tokenResponse = await notion.oauth.token({
grant_type: "authorization_code",
code: code,
redirect_uri: REDIRECT_URI,
});
// Store the access token securely
const accessToken = tokenResponse.access_token;
// Create authenticated client for user
const userNotion = new Client({
auth: accessToken,
});
return {
client: userNotion,
tokenInfo: tokenResponse,
};
}
// Step 3: Validate token periodically
async function validateStoredToken(token: string) {
const notion = new Client();
const introspection = await notion.oauth.introspect({
token: token,
});
return introspection.active;
}
// Step 4: Revoke token when user disconnects
async function disconnectIntegration(token: string) {
const notion = new Client();
await notion.oauth.revoke({
token: token,
});
console.log("Integration disconnected");
}For OAuth endpoints, the client must be configured with client credentials:
// Configure client for OAuth operations
const oauthClient = new Client({
auth: {
client_id: "your-client-id",
client_secret: "your-client-secret",
},
});
// Or use the generic request method
const tokenResponse = await notion.request({
path: "oauth/token",
method: "post",
body: {
grant_type: "authorization_code",
code: "auth-code",
redirect_uri: "redirect-uri",
},
auth: {
client_id: "your-client-id",
client_secret: "your-client-secret",
},
});interface OauthTokenParameters {
grant_type: "authorization_code";
code: string;
redirect_uri?: string;
}
interface OauthTokenResponse {
access_token: string;
token_type: "bearer";
bot_id: string;
workspace_name?: string;
workspace_id?: string;
workspace_icon?: string;
owner: {
type: "workspace" | "user";
user?: {
object: "user";
id: string;
name?: string;
avatar_url?: string;
type: "person";
person?: {
email?: string;
};
};
};
duplicated_template_id?: string;
request_id: string;
}
interface OauthRevokeParameters {
token: string;
}
interface OauthRevokeResponse {
// Empty object on success
}
interface OauthIntrospectParameters {
token: string;
}
interface OauthIntrospectResponse {
active: boolean;
token_type?: "bearer";
bot_id?: string;
workspace_name?: string;
workspace_id?: string;
workspace_icon?: string;
owner?: {
type: "workspace" | "user";
user?: {
object: "user";
id: string;
name?: string;
avatar_url?: string;
type: "person";
person?: {
email?: string;
};
};
};
}Install with Tessl CLI
npx tessl i tessl/npm-notionhq--client