Skip to content
Back to skills

2955 Stability 8fc228e6

ASecurity

**Status:** Active **Last Updated:** 2026-01-21 This document describes the stability guarantees and versioning policy for `notebooklm-py`.

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
documentationpythongobashdebugginggitapisecuritydocumentation

Works with

  • cli
  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2955-stability_8fc228e6 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2955 Stability 8fc228e6?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2955 Stability 8fc228e6
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2955-stability-8fc228e6/badge)](https://www.skillsdirectory.com/skills/tools-only-2955-stability-8fc228e6)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# API Stability and Versioning

**Status:** Active
**Last Updated:** 2026-01-21

This document describes the stability guarantees and versioning policy for `notebooklm-py`.

## Important Context

This library uses **undocumented Google APIs**. Unlike official Google APIs, there are:

- **No stability guarantees from Google**
- **No deprecation notices** before changes
- **No SLAs or support**

Google can change the underlying APIs at any time, which may break this library without warning.

## Versioning Policy

We follow [Semantic Versioning](https://semver.org/) with modifications for our unique situation:

### Version Format: `MAJOR.MINOR.PATCH`

| Change Type | Version Bump | Example |
|-------------|--------------|---------|
| RPC method ID fixes (Google changed something) | PATCH | 0.1.0 → 0.1.1 |
| Bug fixes | PATCH | 0.1.1 → 0.1.2 |
| New features (backward compatible) | MINOR | 0.1.2 → 0.2.0 |
| Public API breaking changes | MAJOR | 0.2.0 → 1.0.0 |

### Special Considerations

1. **RPC ID Changes = Patch Release**
   - When Google changes internal RPC method IDs, we release a patch
   - These are "bug fixes" from our perspective, not breaking changes
   - Users should always use the latest patch version

2. **Python API Stability**
   - Public API (items in `__all__`) is stable within a major version
   - Breaking changes require a major version bump
   - Deprecated APIs are marked with `DeprecationWarning` and documented

## Public API Surface

The following are considered **public API** and are subject to stability guarantees:

### Stable (Won't break without major version bump)

```python
# Client
NotebookLMClient
NotebookLMClient.from_storage()
NotebookLMClient.notebooks
NotebookLMClient.sources
NotebookLMClient.artifacts
NotebookLMClient.chat
NotebookLMClient.research
NotebookLMClient.notes
NotebookLMClient.settings
NotebookLMClient.sharing

# Types
Notebook, Source, Artifact, Note
GenerationStatus, AskResult
NotebookDescription, ConversationTurn
ShareStatus, SharedUser, SourceFulltext

# Exceptions (all inherit from NotebookLMError)
NotebookLMError                    # Base exception
RPCError, AuthError, RateLimitError, RPCTimeoutError, ServerError
NetworkError, DecodingError, UnknownRPCMethodError
ClientError, ConfigurationError, ValidationError
# Domain-specific
SourceError, SourceAddError, SourceProcessingError, SourceTimeoutError, SourceNotFoundError
NotebookError, NotebookNotFoundError
ArtifactError, ArtifactDownloadError, ArtifactNotFoundError, ArtifactNotReadyError, ArtifactParseError
ChatError

# Enums
AudioFormat, VideoFormat, ExportType
SourceType, ArtifactType, SourceStatus
ShareAccess, SharePermission, ShareViewLevel
ChatGoal, ChatResponseLength, ChatMode

# Auth
AuthTokens, DEFAULT_STORAGE_PATH
```

### Internal (May change without notice)

```python
# These are NOT part of the public API:
notebooklm.rpc.*          # RPC protocol internals
notebooklm._core.*        # Core infrastructure
notebooklm._*.py          # All underscore-prefixed modules
notebooklm.auth.*         # Auth internals (except AuthTokens)
```

To use internal APIs, import them explicitly:
```python
# Explicit import for power users (may break)
from notebooklm.rpc import RPCMethod, encode_rpc_request
```

## Deprecation Policy

1. **Deprecation Notice**: Deprecated features emit `DeprecationWarning`
2. **Documentation**: Deprecations are noted in docstrings and CHANGELOG
3. **Removal Timeline**: Deprecated features are removed in the next major version
4. **Migration Guide**: Breaking changes include migration instructions

### Currently Deprecated

The following are deprecated and will be removed in **v0.4.0**:

| Deprecated | Replacement | Notes |
|------------|-------------|-------|
| `Source.source_type` | `Source.kind` | Returns `SourceType` str enum |
| `Artifact.artifact_type` | `Artifact.kind` | Returns `ArtifactType` str enum |
| `Artifact.variant` | `Artifact.kind` | Use `.is_quiz` / `.is_flashcards` |
| `SourceFulltext.source_type` | `SourceFulltext.kind` | Returns `SourceType` str enum |
| `StudioContentType` | `ArtifactType` | Str enum for user-facing code |

## Migration Guides

### Migrating from v0.2.x to v0.3.0

Version 0.3.0 introduces **deprecated** attributes that emit `DeprecationWarning` when accessed.
These will be removed in v0.4.0. Update your code now to avoid breakage.

#### 1. `Source.source_type` → `Source.kind`

**Before (deprecated):**
```python
source = await client.sources.list(notebook_id)[0]
if source.source_type == "pdf":  # ⚠️ Emits DeprecationWarning
    print("This is a PDF")
```

**After (recommended):**
```python
from notebooklm import SourceType

source = await client.sources.list(notebook_id)[0]

# Option 1: Use enum comparison (recommended)
if source.kind == SourceType.PDF:
    print("This is a PDF")

# Option 2: Use string comparison (str enum supports this)
if source.kind == "pdf":
    print("This is a PDF")
```

**Available `SourceType` values:**
`GOOGLE_DOCS`, `GOOGLE_SLIDES`, `GOOGLE_SPREADSHEET`, `PDF`, `PASTED_TEXT`, `WEB_PAGE`, `YOUTUBE`, `MARKDOWN`, `DOCX`, `CSV`, `IMAGE`, `MEDIA`, `UNKNOWN`

#### 2. `Artifact.artifact_type` → `Artifact.kind`

**Before (deprecated):**
```python
from notebooklm import StudioContentType  # ⚠️ Emits DeprecationWarning

artifact = await client.artifacts.list(notebook_id)[0]
if artifact.artifact_type == StudioContentType.AUDIO:  # ⚠️ Emits DeprecationWarning
    print("This is an audio artifact")
```

**After (recommended):**
```python
from notebooklm import ArtifactType

artifact = await client.artifacts.list(notebook_id)[0]

# Option 1: Use enum comparison (recommended)
if artifact.kind == ArtifactType.AUDIO:
    print("This is an audio artifact")

# Option 2: Use string comparison (str enum supports this)
if artifact.kind == "audio":
    print("This is an audio artifact")
```

**Available `ArtifactType` values:**
`AUDIO`, `VIDEO`, `REPORT`, `QUIZ`, `FLASHCARDS`, `MIND_MAP`, `INFOGRAPHIC`, `SLIDE_DECK`, `DATA_TABLE`, `UNKNOWN`

#### 3. `Artifact.variant` → `Artifact.kind` or helpers

**Before (deprecated):**
```python
if artifact.artifact_type == 4 and artifact.variant == 2:  # ⚠️ Deprecated
    print("This is a quiz")
```

**After (recommended):**
```python
# Option 1: Use .kind
if artifact.kind == ArtifactType.QUIZ:
    print("This is a quiz")

# Option 2: Use helper properties
if artifact.is_quiz:
    print("This is a quiz")
if artifact.is_flashcards:
    print("These are flashcards")
```

#### Why These Changes?

1. **Stability**: The `.kind` property abstracts internal integer codes that Google may change
2. **Usability**: String enums work in comparisons, logging, and serialization
3. **Future-proofing**: Unknown types return `UNKNOWN` with a warning instead of crashing

## What Happens When Google Breaks Things

When Google changes their internal APIs:

1. **Detection**: Automated RPC health check runs nightly (see below)
2. **Investigation**: Identify changed method IDs using browser devtools
3. **Fix**: Update `rpc/types.py` with new method IDs
4. **Release**: Push patch release as soon as possible

### Automated RPC Health Check

A nightly GitHub Action (`rpc-health.yml`) monitors all 35+ RPC methods for ID changes.

**What it verifies:**
- The RPC method ID we send matches the ID returned in the response envelope
- Example: `LIST_NOTEBOOKS` sends `wXbhsf` → response must contain `wXbhsf`

**What it does NOT verify:**
- Response data correctness (E2E tests cover this)
- Response schema validation (too fragile across 35+ methods)
- Business logic (out of scope for monitoring)

**Why this design:**
- Google's breaking change pattern is silent ID changes, not schema changes
- Error responses still contain the method ID, so we detect mismatches even on API errors
- A mismatch means `rpc/types.py` needs updating, triggering a patch release

**On mismatch detection:**
- GitHub Issue auto-created with `bug`, `rpc-breakage`, and `automated` labels
- Report shows expected vs actual IDs and which `RPCMethod` entries need updating

**Configuration:**
- `NOTEBOOKLM_RPC_DELAY`: Delay between RPC calls in seconds (default: 1.0)

**Manual trigger:** `gh workflow run rpc-health.yml`

### How to Report API Breakage

1. Check [GitHub Issues](https://github.com/teng-lin/notebooklm-py/issues) for existing reports
2. If not reported, open an issue with:
   - Error message (especially any RPC error codes)
   - Which operation failed
   - When it started failing
3. See [RPC Development Guide](rpc-development.md) for debugging

### Self-Recovery

If the library breaks before we release a fix:

1. Open browser devtools on NotebookLM
2. Perform the failing operation manually
3. Find the new RPC method ID in Network tab
4. Temporarily patch your local copy:
   ```python
   # In your code, before using the library
   from notebooklm.rpc.types import RPCMethod
   RPCMethod.SOME_METHOD._value_ = "NewMethodId"
   ```

## Upgrade Recommendations

### Stay Current

```bash
# Always use latest patch version
pip install --upgrade notebooklm-py
```

### Pin Appropriately

```toml
# pyproject.toml - recommended
dependencies = [
    "notebooklm-py>=0.1,<1.0",  # Accept patches and minors
]

# requirements.txt - for reproducibility
notebooklm-py==0.1.0  # Exact version (but update regularly!)
```

### Test Before Upgrading

```bash
# Test in development first
pip install notebooklm-py==X.Y.Z
pytest
```

## Questions?

- **Bug reports**: [GitHub Issues](https://github.com/teng-lin/notebooklm-py/issues)
- **Discussions**: [GitHub Discussions](https://github.com/teng-lin/notebooklm-py/discussions)
- **Security issues**: See [SECURITY.md](../SECURITY.md)

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.