Gemini fine-tuning (tunedModels) — deprecated, service returns 501
Status: DOCUMENTED (REST reference and discovery still describe the full resource) · DEPRECATED (guide: "we no longer have a model available which supports fine-tuning in the Gemini API or AI Studio" since Gemini 1.5 Flash-001 was deprecated in May 2025) · RETIRED in practice: GET /v1beta/tunedModels, GET /v1beta/tunedModels/{id}, GET …/permissions and POST /v1beta/tunedModels (empty body) all return 501 UNIMPLEMENTED "Operation is not implemented, or supported, or enabled." (live 2026-09-18). Nothing was created.
Sources: Model tuning guide · Tuning reference · All methods · discovery v1beta rev. 20260918 (tunedModels.*, tunedModels.permissions.*, tunedModels.operations.*) · python-genai TuningJob, TuningJobState ("not supported in Gemini API").
Last verified: 2026-09-18. Twins: endpoints fragment (api_family tuning), parameters/gemini-tuning.json, objects TunedModel, TuningTask…, CreateTunedModelMetadata, Permission, lifecycle TunedModel.
1. Where tuning lives now
Supervised fine-tuning of Gemini models is offered on Gemini Enterprise Agent Platform / Vertex AI (google-genai with vertexai=True: client.tunings.tune(...) → TuningJob with JobState/TuningJobState). Gemma models can be tuned outside the API (open weights). The Gemini Developer API keeps the tunedModels resource only for compatibility; the guide invites feedback on the developer forum.
2. Resource and methods (as documented)
| Method | Path | Body / query | Returns | Live |
|---|---|---|---|---|
| create | POST /v1beta/tunedModels?tunedModelId= |
TunedModel {displayName, description, baseModel | tunedModelSource, tuningTask{trainingData{examples{examples[{textInput, output}]}}, hyperparameters{epochCount, batchSize, learningRate | learningRateMultiplier}}, temperature, topP, topK, readerProjectNumbers[]} |
Operation (metadata CreateTunedModelMetadata {tunedModel, totalSteps, completedSteps, completedPercent, snapshots[]}) |
501 (empty body probe) |
| list | GET /v1beta/tunedModels?pageSize=(10, max 1000)&pageToken=&filter= (owner:me, writers:me, readers:me, readers:everyone) |
— | {tunedModels[], nextPageToken} |
501 |
| get | GET /v1beta/tunedModels/{id} |
— | TunedModel |
501 |
| patch | PATCH /v1beta/tunedModels/{id}?updateMask= |
TunedModel |
TunedModel |
not tested |
| delete | DELETE /v1beta/tunedModels/{id} |
— | {} |
not tested (destructive) |
| generate | POST /v1beta/tunedModels/{id}:generateContent / :streamGenerateContent / legacy :generateText |
GenerateContentRequest |
GenerateContentResponse |
not tested |
| batch | POST /v1beta/tunedModels/{id}:batchGenerateContent / :asyncBatchEmbedContent |
batch envelope | Operation |
not tested |
| transferOwnership | POST /v1beta/tunedModels/{id}:transferOwnership |
{emailAddress} |
{} |
not tested |
| permissions | GET/POST /v1beta/tunedModels/{id}/permissions, GET/PATCH/DELETE …/permissions/{p} |
Permission {granteeType USER|GROUP|EVERYONE, emailAddress, role OWNER|WRITER|READER} |
Permission / list |
list on bogus id → 501 |
| operations | GET /v1beta/tunedModels/{id}/operations[/{op}] |
— | Operation / list |
bogus → 400 Request contains an invalid argument. |
Historic constraints: tunedModelId regex [a-z]([a-z0-9-]{0,38}[a-z0-9])?; displayName ≤ 40 chars; hyperparameter defaults epochs 5, batch 4 or 16, learning rate 0.001 or 0.0002 (by dataset size), multiplier 1.0; examples must all be the same type (text in / text out).
3. Lifecycle (documented)
TunedModel.state: CREATING → ACTIVE | FAILED (STATE_UNSPECIFIED unused). Progress via the operation's CreateTunedModelMetadata and tuningTask.snapshots[] {step, epoch, meanLoss, computeTime}; tuningTask.startTime / completeTime. Tuned models are addressed as tunedModels/{id} in generateContent and were reachable only with the owner's credentials (API-key sharing via permissions / readerProjectNumbers).
4. Live log (2026-09-18, $0)
| Call | Result |
|---|---|
GET /v1beta/tunedModels?pageSize=5 |
501 UNIMPLEMENTED |
GET /v1beta/tunedModels/bogus-model |
501 |
GET /v1beta/tunedModels/bogus-model/permissions |
501 |
GET /v1beta/tunedModels/bogus-model/operations/bogus |
400 INVALID_ARGUMENT |
POST /v1beta/tunedModels {} |
501 |
A 501 could in theory be per-project ("or enabled"), but combined with the guide's statement the honest reading is that the developer-API tuning service is switched off. Tests: tests/gemini/test_tuning.py asserts status in (200, 501) and records the message.