source_add
Add sources to a NotebookLM notebook—supporting URLs, YouTube, text, files, and Drive documents—individually or in batch, with optional waiting for processing.
Instructions
Add a source to a notebook — single, batch, or in-channel bytes. Accepts a notebook name or ID.
Call in exactly ONE of two modes:
Single mode — pass source_type; it selects the required input:
url/youtube— requireurl(youtube→ a YouTube link).text— requirestext;titleoptional.file— over stdio, requirespath(a local path on the server host). Over the remote (http) connector the host filesystem is unreachable, so it returnsupload_requiredwith two actor paths:human_upload(open the signed URL in a browser) andagent_upload(an agent POSTs the bytes as the raw body);agent_instructionsgives the rule (tryagent_upload, elsehuman_upload.url). Alternatively passbytes_base64to add a SMALL file in-channel (any transport, no signed URL): standard base64 (not URL-safe) ≤ 10,000 chars (≈ 7 KB);filenameseeds the title/extension. A bigger file must take the signed URL (≤ 200 MiB).drive— requiresdocument_id+mime_type(one of google-doc|google-slides|google-sheets|pdf; required, no default — a wrong default fails non-Doc imports, #1827).
The single-mode content inputs are mutually exclusive — supply only the one
your source_type requires (bytes_base64 is the file alternative to
path). An explicit title for url/youtube/drive is honored via a post-add
rename; a miss returns title_override_applied: false (#1960).
Pass wait=true to block until the ONE added source finishes processing and
return the source_wait aggregate (buckets + per-bucket *_count +
total_count) with a top-level source_id (present even on timeout/failure);
timeout/interval tune the poll. wait is single-mode only and NOT for a
remote file signed-URL upload (add it, then source_wait). Without wait
the added source is echoed under source with string kind /
status_label labels; imports are ASYNCHRONOUS so the echo is usually still
processing/preparing — confirm with source_wait or
source_list(status="error"). A failed import is flagged inline
(status_label="error" + a warning); source_wait also flags a READY web
page with suspiciously thin text (dead link/soft-404/paywall).
Batch mode — pass urls (a list of http/https URLs, YouTube links
included) to add many in one call instead of one round-trip each. Each entry is
validated and added independently; the response is an explicit per-item list so
partial failure is never hidden::
{"notebook_id": …, "added": <int>, "failed": <int>,
"results": [{"input": "<url>", "status": "added", "source_id": …,
"title": …, "status_label": …, "warning"?: …},
{"input": "<url>", "status": "error",
"error": {"code": …, "message": …, "retriable": …, "hint"?: …}}]}results is positional (results[i] is for urls[i]); status is
"added" or "error" (the ADD outcome). An "added" item also carries the
source's status_label and, when the add response already reflects a failed
import, an inline warning — same failure-signaling as single mode. A per-URL
input failure (bad URL / 404 / SSRF-blocked host) isolates as an error
item; a fatal service failure (expired auth, rate limit, upstream 5xx) aborts
the whole call. Batch is URL-only: a non-URL entry (plain text, a local path,
file:///ftp://) is reported as a per-item VALIDATION error. The
single-mode named inputs (incl. bytes_base64/filename/wait) are not
valid with urls; allow_internal applies to every entry.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | ||
| path | No | ||
| text | No | ||
| urls | No | ||
| wait | No | ||
| title | No | ||
| timeout | No | ||
| filename | No | ||
| interval | No | ||
| notebook | Yes | ||
| mime_type | No | ||
| document_id | No | ||
| source_type | No | ||
| bytes_base64 | No | ||
| allow_internal | No |