Skip to main content
POST
/
v1
/
oauth
/
token
TypeScript SDK
import { Client } from "@notionhq/client"

const notion = new Client()

const response = await notion.oauth.token({
  client_id: process.env.OAUTH_CLIENT_ID,
  client_secret: process.env.OAUTH_CLIENT_SECRET,
  grant_type: "authorization_code",
  code: "abc123-authorization-code",
  redirect_uri: "https://example.com/callback"
})
curl --request POST \
--url https://api.notion.com/v1/oauth/token \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--header 'Notion-Version: <notion-version>' \
--data '
{
"grant_type": "<string>",
"code": "<string>",
"redirect_uri": "<string>"
}
'
import requests

url = "https://api.notion.com/v1/oauth/token"

payload = {
"grant_type": "<string>",
"code": "<string>",
"redirect_uri": "<string>"
}
headers = {
"Notion-Version": "<notion-version>",
"Authorization": "Basic <encoded-value>",
"Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://api.notion.com/v1/oauth/token",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'grant_type' => '<string>',
'code' => '<string>',
'redirect_uri' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Basic <encoded-value>",
"Content-Type: application/json",
"Notion-Version: <notion-version>"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://api.notion.com/v1/oauth/token"

payload := strings.NewReader("{\n \"grant_type\": \"<string>\",\n \"code\": \"<string>\",\n \"redirect_uri\": \"<string>\"\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Notion-Version", "<notion-version>")
req.Header.Add("Authorization", "Basic <encoded-value>")
req.Header.Add("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://api.notion.com/v1/oauth/token")
.header("Notion-Version", "<notion-version>")
.header("Authorization", "Basic <encoded-value>")
.header("Content-Type", "application/json")
.body("{\n \"grant_type\": \"<string>\",\n \"code\": \"<string>\",\n \"redirect_uri\": \"<string>\"\n}")
.asString();
require 'uri'
require 'net/http'

url = URI("https://api.notion.com/v1/oauth/token")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Notion-Version"] = '<notion-version>'
request["Authorization"] = 'Basic <encoded-value>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"grant_type\": \"<string>\",\n \"code\": \"<string>\",\n \"redirect_uri\": \"<string>\"\n}"

response = http.request(request)
puts response.read_body
{
  "access_token": "<string>",
  "token_type": "<string>",
  "refresh_token": "<string>",
  "bot_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "workspace_icon": "<string>",
  "workspace_name": "<string>",
  "workspace_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "owner": {
    "type": "<string>",
    "user": {
      "type": "<string>",
      "person": {
        "email": "<string>",
        "email_verified": true
      },
      "name": "<string>",
      "avatar_url": "<string>",
      "id": "<string>",
      "object": "<string>"
    }
  },
  "duplicated_template_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "request_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
{
"object": "<unknown>",
"message": "<string>",
"status": "<unknown>",
"additional_data": {}
}
{
"object": "<unknown>",
"message": "<string>",
"code": "invalid_client",
"status": "<unknown>",
"additional_data": {}
}
{
"object": "<unknown>",
"message": "<string>",
"code": "test_env_error",
"status": "<unknown>",
"additional_data": {}
}
{
"object": "<unknown>",
"message": "<string>",
"code": "internal_server_error",
"status": "<unknown>",
"additional_data": {}
}
For step-by-step instructions on how to use this endpoint to create a public connection, check out the Authorization guide.
Redirect URI requirements for public connectionsThe redirect_uri is a required field in the request body for this endpoint if:In most cases, the redirect_uri field is required.This field is not allowed in the request body if:
  • there is one redirect_uri included in the connection’s settings under OAuth Domain & URIs, and the redirect_uri query parameter was not included in the Authorization URL.
Learn more in the public connection section of the Authorization Guide.Note: Each Public API endpoint can return several possible error codes. To see a full description of each type of error code, see the Error codes section of the Status codes documentation.

Authorizations

Authorization
string
header
required

Basic authentication header of the form Basic <encoded-value>, where <encoded-value> is the base64-encoded string username:password.

Headers

Notion-Version
enum<string>
required

The API version to use for this request. The latest version is 2026-03-11.

Available options:
2026-03-11

Body

application/json
grant_type
string
required
Allowed value: "authorization_code"
code
string
required
redirect_uri
string
external_account
object

Response

access_token
string
required
token_type
string
required
Allowed value: "bearer"
refresh_token
string | null
required
bot_id
string<uuid>
required
workspace_icon
string | null
required
workspace_name
string | null
required
workspace_id
string<uuid>
required
owner
User · object
required
duplicated_template_id
string<uuid> | null
required
request_id
string<uuid>