Skip to main content
AI/MLjeremylongshore

grammarly-upgrade-migration

'Upgrade and migration guidance for Grammarly API version changes. Use

Stars
2,267
Source
jeremylongshore/claude-code-plugins-plus-skills
Updated
2026-05-31
Slug
jeremylongshore--claude-code-plugins-plus-skills--grammarly-upgrade-migration
View on GitHubRaw SKILL.md

// install — copy + paste into any project

mkdir -p .claude/skills && curl -fsSL https://raw.githubusercontent.com/jeremylongshore/claude-code-plugins-plus-skills/HEAD/plugins/saas-packs/grammarly-pack/skills/grammarly-upgrade-migration/SKILL.md -o .claude/skills/grammarly-upgrade-migration.md

Drops the SKILL.md into .claude/skills/grammarly-upgrade-migration.md. Works with Claude Code, Cursor, and any agent that loads SKILL.md files from .claude/skills/.

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.headers.get("x-grammarly-api-version") ?? "unknown";
    const deprecated = res.headers.get("x-grammarly-deprecated");
    if (deprecated) console.warn(`${api} endpoint deprecated: ${deprecated}`);
  }
  return { scores: "v2", aiDetection: "v1", plagiarism: "v1", latestAvailable: versions };
}

Migration Checklist

  • Audit codebase for all api.grammarly.com endpoint references
  • Map each endpoint to its current API version (v1 vs. v2)
  • Check if Writing Score v2 response includes new sub-score categories
  • Verify AI Detection confidence threshold changes between versions
  • Update plagiarism check response parser if source attribution format changed
  • Test OAuth token flow — scope names may differ between API versions
  • Validate suggestion category enums (clarity, engagement, delivery, correctness)
  • Update error handling for new rate limit headers in v2
  • Check if text submission size limits changed between versions
  • Run A/B comparison of v1 vs. v2 scores on sample corpus to verify parity

Schema Migration

// Grammarly scores response changed from flat scores to structured breakdown
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): NewScoreResponse {
  const toLabel = (s: number) => (s >= 80 ? "Strong" : s >= 60 ? "Good" : "Needs work");
  return {
    overall: { score: old.overall, label: toLabel(old.overall) },
    dimensions: (["correctness", "clarity", "engagement", "delivery"] as const).map((name) => ({
      name,
      score: old[name],
      label: toLabel(old[name]),
      suggestions: [],
    })),
    metadata: { wordCount: 0, readingTime: 0, apiVersion: "v1-migrated" },
  };
}

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 ${this.apiKey}`, "Content-Type": "application/json" },
        body: JSON.stringify({ text }),
      });
      if (!res.ok) throw new Error(`Grammarly ${api} ${res.status}`);
      return await res.json();
    } catch (err) {
      const fallback = this.fallbackMap[api];
      if (fallback !== version) {
        console.warn(`Falling back ${api} from ${version} to ${fallback}`);
        this.versionMap[api] = fallback;
        return this.checkText(text, api);
      }
      throw 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

Prerequisites

  • Pinned current and target versions, compatibility assessment, sandbox fixtures, and an owner for each breaking contract.
  • Versioned configuration/schema backups and an approved downgrade or integration-disable procedure.
  • Synthetic text and least-privilege test identities to prove the upgrade does not broaden access or retention.

Instructions

  1. Inventory client, schema, configuration, authorization, telemetry, and text-retention changes between versions.
  2. Upgrade in sandbox, run bounded regression fixtures, and compare response shape, error handling, authorization, and retention behavior with baseline.
  3. Promote through staging and a canary integration only after approval; do not combine unrelated configuration changes.
  4. Monitor stated rollback triggers, then promote in stages or restore the exact pinned prior revision with redacted evidence.
  5. Update the compatibility record only after both canary and rollback exercises complete.

Output

Produce an upgrade receipt with from/to versions, affected contracts, fixture and canary outcomes, authorization/retention results, owner approval, compatibility decision, and rollback revision. Exclude source text and credentials.

Examples

from=client-r12; to=client-r13; sandbox=pass; staging=pass; retention=unchanged; canary=held; rollback=r12 is a defensible upgrade record.

Resources

Next Steps

For CI pipeline integration, see grammarly-ci-integration.