This guide walks you through authenticating with OAuth 2.0, creating a notebook, adding a source, and polling until processing completes.
Set up with a coding agent (Recommended)
Click Show prompt, copy the prompt, and paste it into your coding agent (such as Claude Code or Cursor) to automate Google Cloud project setup, OAuth authentication, and your first API call:
Help me set up and test the Gemini Notebook API (https://notebook.googleapis.com/v1). Follow these exact steps:
1. Check if the `gcloud` CLI is installed and authenticated (`gcloud auth list`). Ask me which Google Cloud PROJECT_ID to use (or show `gcloud config get-value project` / `gcloud projects list --limit=10` so I can pick one).
2. Enable the Gemini Notebook API on that project:
gcloud services enable notebook.googleapis.com --project="$PROJECT_ID"
3. Authenticate Application Default Credentials (ADC) with the required `notebook` OAuth scope (standard `gcloud auth print-access-token` does not include this scope). Run or ask me to run:
gcloud auth application-default login --scopes="https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/notebook"
4. Mint a bearer token:
ACCESS_TOKEN=$(gcloud auth application-default print-access-token)
5. Verify the setup by calling the REST API with both `Authorization: Bearer $ACCESS_TOKEN` and `x-goog-user-project: $PROJECT_ID` headers:
- Create a notebook: POST https://notebook.googleapis.com/v1/notebooks with `{"display_name": "Agent Quickstart"}`
- Add a source: POST https://notebook.googleapis.com/v1/{notebook.name}/sources with `{"display_name": "Gemini API Docs", "web_content": {"url": "https://ai.google.dev/gemini-api/docs"}}`
- Poll GET https://notebook.googleapis.com/v1/{source.name} every 2 seconds until `state` is `ACTIVE`.1. Prerequisites and authentication
Before you start, make sure you meet the following prerequisites:
- Personal Google Account: During the Public Preview, the Gemini Notebook
API is only available for personal Google Accounts. Requests from Google
Workspace accounts fail with
403 PERMISSION_DENIED(WORKSPACE_ACCOUNT_NOT_SUPPORTED). - One-time Gemini Notebook sign-in: Sign in to
Gemini Notebook at least once with the Google
Account you plan to use. If the account has never signed in to Gemini
Notebook, creating a notebook fails with
404 NOT_FOUND(Account not found for user.).
If configuring manually, enable the Gemini Notebook API
(notebook.googleapis.com) in your Google Cloud project and generate an
OAuth 2.0 access token using the Google Cloud CLI (gcloud):
export PROJECT_ID="YOUR_PROJECT_ID"
# Enable the Gemini Notebook API in your Google Cloud project
gcloud services enable notebook.googleapis.com --project="$PROJECT_ID"
# Authenticate with Application Default Credentials and the Gemini Notebook API scope
gcloud auth application-default login \
--scopes="https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/notebook"
export ACCESS_TOKEN=$(gcloud auth application-default print-access-token)
export API_ROOT="https://notebook.googleapis.com/v1"
2. Create a notebook
Create a notebook to hold your sources:
REST
NOTEBOOK=$(curl -s -X POST "${API_ROOT}/notebooks" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "x-goog-user-project: ${PROJECT_ID}" \
-H "Content-Type: application/json" \
-d '{"display_name": "Autonomous Agent Research"}')
export NOTEBOOK_NAME=$(echo "$NOTEBOOK" | python3 -c "import sys, json; print(json.load(sys.stdin)['name'])")
echo "Created notebook: $NOTEBOOK_NAME"
Python
import os
import requests
API_ROOT = "https://notebook.googleapis.com/v1"
ACCESS_TOKEN = os.environ["ACCESS_TOKEN"]
PROJECT_ID = os.environ["PROJECT_ID"]
headers = {
"Authorization": f"Bearer {ACCESS_TOKEN}",
"x-goog-user-project": PROJECT_ID,
"Content-Type": "application/json",
}
resp = requests.post(f"{API_ROOT}/notebooks", headers=headers, json={
"display_name": "Autonomous Agent Research"
})
notebook = resp.json()
notebook_name = notebook["name"]
print(f"Created notebook: {notebook_name}")
3. Add a source
Add a public web URL, YouTube video URL, plain text, or Markdown string to your notebook:
REST
SOURCE=$(curl -s -X POST "${API_ROOT}/${NOTEBOOK_NAME}/sources" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "x-goog-user-project: ${PROJECT_ID}" \
-H "Content-Type: application/json" \
-d '{
"display_name": "Gemini API Guide",
"web_content": {"url": "https://ai.google.dev/gemini-api/docs"}
}')
export SOURCE_NAME=$(echo "$SOURCE" | python3 -c "import sys, json; print(json.load(sys.stdin)['name'])")
echo "Adding source: $SOURCE_NAME"
Python
resp = requests.post(f"{API_ROOT}/{notebook_name}/sources", headers=headers, json={
"display_name": "Gemini API Guide",
"web_content": {"url": "https://ai.google.dev/gemini-api/docs"}
})
source = resp.json()
source_name = source["name"]
print(f"Adding source: {source_name}")
4. Check source processing status
Source ingestion is asynchronous. Poll GetSource until state reaches
ACTIVE or FAILED:
REST
curl -s -X GET "${API_ROOT}/${SOURCE_NAME}" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "x-goog-user-project: ${PROJECT_ID}" | python3 -c "import sys, json; print(json.load(sys.stdin)['state'])"
# Output: ACTIVE
Python
import time
while True:
resp = requests.get(f"{API_ROOT}/{source_name}", headers=headers).json()
state = resp.get("state")
if state == "ACTIVE":
print("Source is ACTIVE and ready.")
break
elif state == "FAILED":
print(f"Source processing failed: {resp.get('error')}")
break
time.sleep(2)