技能 编程开发 Grammarly API迁移与版本控制

Grammarly API迁移与版本控制

v20260423
grammarly-upgrade-migration
本技能提供Grammarly API版本升级和迁移的完整指南。它详细介绍了如何处理不同API版本间的兼容性问题、数据结构的变化(如评分维度),并指导用户实现健壮的API调用和回滚策略,确保写作分析的连续性。
获取技能
198 次下载
概览

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

Resources

Next Steps

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

信息
Category 编程开发
Name grammarly-upgrade-migration
版本 v20260423
大小 5.92KB
更新时间 2026-04-28
语言