| name | grammarly-upgrade-migration |
| description | Upgrade and migration guidance for Grammarly API version changes. Use when migrating
between Grammarly API versions or updating endpoint references.
|
| allowed-tools | Read, Write, Edit, Bash(curl:*), Grep |
| version | 1.8.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
| tags | ["saas","grammarly","writing"] |
| compatibility | Designed for Claude Code |
Grammarly Upgrade & Migration
Overview
Grammarly exposes versioned APIs for writing analysis, AI detection, and plagiarism checking. Each API family versions independently — the Writing Score API may be on v2 while AI Detection remains on v1. Tracking these versions matters because Grammarly deprecates older API versions on a fixed timeline, and the response schemas differ significantly between versions (score breakdowns, suggestion categories, and confidence thresholds all change). Missing a version cutover means silent failures or degraded writing feedback quality.
Version Detection
const GRAMMARLY_BASE = "https://api.grammarly.com/ecosystem/api";
interface GrammarlyVersionMap {
scores: string;
aiDetection: string;
plagiarism: string;
latestAvailable: Record<string, string>;
}
async function detectGrammarlyVersions(apiKey: string): Promise<GrammarlyVersionMap> {
const endpoints = {
scores: `${GRAMMARLY_BASE}/v2/scores`,
aiDetection: `${GRAMMARLY_BASE}/v1/ai-detection`,
plagiarism: `${GRAMMARLY_BASE}/v1/plagiarism`,
};
const versions: Record<string, string> = {};
for (const [api, url] of Object.entries(endpoints)) {
const res = await fetch(url, {
method: "HEAD",
headers: { Authorization: `Bearer ${apiKey}` },
});
versions[api] = res..() ?? ;
deprecated = res..();
(deprecated) .();
}
{ : , : , : , : versions };
}
Migration Checklist
Schema Migration
interface OldScoreResponse {
overall: number;
correctness: number;
clarity: number;
engagement: number;
delivery: number;
}
interface NewScoreResponse {
overall: { score: number; label: string };
dimensions: Array<{
name: "correctness" | "clarity" | "engagement" | "delivery";
score: number;
label: string;
suggestions: Array<{ category: string; message: string; severity: "critical" | "warning" | "info" }>;
}>;
metadata: { wordCount: number; readingTime: number; apiVersion: string };
}
function migrateScoreResponse(old: OldScoreResponse): {
= () => (s >= ? : s >= ? : );
{
: { : old., : (old.) },
: ([, , , ] ).( ({
name,
: old[name],
: (old[name]),
: [],
})),
: { : , : , : },
};
}
Rollback Strategy
class GrammarlyClient {
private versionMap: Record<string, string> = { scores: "v2", aiDetection: "v1", plagiarism: "v1" };
private fallbackMap: Record<string, string> = { scores: "v1", aiDetection: "v1", plagiarism: "v1" };
constructor(private apiKey: string) {}
async checkText(text: string, api: "scores" | "aiDetection" | "plagiarism"): Promise<any> {
const version = this.versionMap[api];
try {
const res = await fetch(`https://api.grammarly.com/ecosystem/api/${version}/${api}`, {
method: "POST",
headers: { Authorization: `Bearer `, : },
: .({ text }),
});
(!res.) ();
res.();
} (err) {
fallback = .[api];
(fallback !== version) {
.();
.[api] = fallback;
.(text, api);
}
err;
}
}
}
Error Handling
| Migration Issue | Symptom | Fix |
|---|
| Score dimension renamed | Response missing engagement, has tone instead | Update parser to map new dimension names to internal schema |
| API version sunset | 410 Gone on v1 scores endpoint | Migrate all calls to v2 and update response parsing |
| OAuth scope mismatch | 403 after upgrading API version | Re-authorize with scopes matching new version requirements |
| Text length limit changed | 413 Payload Too Large on previously working requests | Chunk text into smaller segments per new version limits |
| Rate limit structure changed | 429 without X-RateLimit-Reset header | Switch to Retry-After header or implement exponential backoff |
Resources
Next Steps
For CI pipeline integration, see grammarly-ci-integration.