diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index d4f6f299..2deaa4a0 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "3.0.0"
+ ".": "3.1.0-rc.1"
}
diff --git a/.stats.yml b/.stats.yml
index 45b858e1..eced2fee 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 30
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/writerai/writer-275de8f7afa2d37404ebebc082dda35e70ab94437de270b5bc6e2fdc94c9fdae.yml
-openapi_spec_hash: 4d4a9ba232d19a6180e6d4a7d5566103
-config_hash: 8701b1a467238f1afdeceeb7feb1adc6
+configured_endpoints: 29
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/writerai/writer-c998c7cab6c43a698deb813179849e0379db494eef2a34f751616486d6bb0e25.yml
+openapi_spec_hash: aba09dae66d0e96b08ea2ac4e9113f09
+config_hash: 85d9c08b6b71fad459240bc6f401eac7
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b7570184..840bc64c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,29 @@
# Changelog
+## 3.1.0-rc.1 (2026-07-13)
+
+Full Changelog: [v3.0.0...v3.1.0-rc.1](https://github.com/writer/writer-node/compare/v3.0.0...v3.1.0-rc.1)
+
+### Features
+
+* **api:** remove translation endpoint ([b1d8bff](https://github.com/writer/writer-node/commit/b1d8bff85f424352ab8e7718d5bdd05b279b4c08))
+
+
+### Bug Fixes
+
+* **client:** send content-type header for requests with an omitted optional body ([2678ce2](https://github.com/writer/writer-node/commit/2678ce22ceb1aaf6fb7edf6032e1f29ce2466442))
+
+
+### Documentation
+
+* **api:** updates to API spec ([8498778](https://github.com/writer/writer-node/commit/849877848176d847e5620efb689b3331d99b2e45))
+
+
+### Build System
+
+* **deps:** Bump the npm_and_yarn group across 2 directories with 10 updates ([ccb86ee](https://github.com/writer/writer-node/commit/ccb86eeceb82098f0419f081d2f54b7ace86599c))
+* **deps:** Bump the npm_and_yarn group across 2 directories with 2 updates ([0311758](https://github.com/writer/writer-node/commit/0311758d83930bacceaab702f4303533c4ffd384))
+
## 3.0.0 (2026-06-02)
Full Changelog: [v3.0.0...v3.0.0](https://github.com/writer/writer-node/compare/v3.0.0...v3.0.0)
diff --git a/api.md b/api.md
index 30c4d049..c6cdb4b4 100644
--- a/api.md
+++ b/api.md
@@ -147,17 +147,6 @@ Methods:
- client.tools.parsePdf(fileID, { ...params }) -> ToolParsePdfResponse
- client.tools.webSearch({ ...params }) -> ToolWebSearchResponse
-# Translation
-
-Types:
-
-- TranslationRequest
-- TranslationResponse
-
-Methods:
-
-- client.translation.translate({ ...params }) -> TranslationResponse
-
# Vision
Types:
diff --git a/package.json b/package.json
index 4577ad04..95246393 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "writer-sdk",
- "version": "3.0.0",
+ "version": "3.1.0-rc.1",
"description": "The official TypeScript library for the Writer API",
"author": "Writer ",
"types": "dist/index.d.ts",
diff --git a/packages/mcp-server/manifest.json b/packages/mcp-server/manifest.json
index a870fd12..dbdeb9c7 100644
--- a/packages/mcp-server/manifest.json
+++ b/packages/mcp-server/manifest.json
@@ -1,7 +1,7 @@
{
"dxt_version": "0.2",
"name": "writer-sdk-mcp",
- "version": "3.0.0",
+ "version": "3.1.0-rc.1",
"description": "The official MCP Server for the Writer API",
"author": {
"name": "Writer",
diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json
index 7b32ac90..5ee0286f 100644
--- a/packages/mcp-server/package.json
+++ b/packages/mcp-server/package.json
@@ -1,6 +1,6 @@
{
"name": "writer-sdk-mcp",
- "version": "3.0.0",
+ "version": "3.1.0-rc.1",
"description": "The official MCP Server for the Writer API",
"author": "Writer ",
"types": "dist/index.d.ts",
diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts
index 332af849..dab826df 100644
--- a/packages/mcp-server/src/code-tool-worker.ts
+++ b/packages/mcp-server/src/code-tool-worker.ts
@@ -136,7 +136,6 @@ const fuse = new Fuse(
'client.files.upload',
'client.tools.parsePdf',
'client.tools.webSearch',
- 'client.translation.translate',
'client.vision.analyze',
],
{ threshold: 1, shouldSort: true },
diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts
index 8cc33329..4519f51f 100644
--- a/packages/mcp-server/src/local-docs-search.ts
+++ b/packages/mcp-server/src/local-docs-search.ts
@@ -1091,48 +1091,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [
},
},
},
- {
- name: 'translate',
- endpoint: '/v1/translation',
- httpMethod: 'post',
- summary: 'Translate text',
- description: 'Translate text from one language to another.',
- stainlessPath: '(resource) translation > (method) translate',
- qualified: 'client.translation.translate',
- params: [
- 'formality: boolean;',
- 'length_control: boolean;',
- 'mask_profanity: boolean;',
- "model: 'palmyra-translate';",
- 'source_language_code: string;',
- 'target_language_code: string;',
- 'text: string;',
- ],
- response: '{ data: string; }',
- markdown:
- "## translate\n\n`client.translation.translate(formality: boolean, length_control: boolean, mask_profanity: boolean, model: 'palmyra-translate', source_language_code: string, target_language_code: string, text: string): { data: string; }`\n\n**post** `/v1/translation`\n\nTranslate text from one language to another.\n\n### Parameters\n\n- `formality: boolean`\n Whether to use formal or informal language in the translation. See the [list of languages that support formality](https://dev.writer.com/api-reference/translation-api/language-support#formality). If the language does not support formality, this parameter is ignored.\n\n- `length_control: boolean`\n Whether to control the length of the translated text. See the [list of languages that support length control](https://dev.writer.com/api-reference/translation-api/language-support#length-control). If the language does not support length control, this parameter is ignored.\n\n- `mask_profanity: boolean`\n Whether to mask profane words in the translated text. See the [list of languages that do not support profanity masking](https://dev.writer.com/api-reference/translation-api/language-support#profanity-masking). If the language does not support profanity masking, this parameter is ignored.\n\n- `model: 'palmyra-translate'`\n The model to use for translation.\n\n- `source_language_code: string`\n The [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes) language code of the original text to translate. For example, `en` for English, `zh` for Chinese, `fr` for French, `es` for Spanish. If the language has a variant, the code appends the two-digit [ISO-3166 country code](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes). For example, Mexican Spanish is `es-MX`. See the [list of supported languages and language codes](https://dev.writer.com/api-reference/translation-api/language-support).\n\n- `target_language_code: string`\n The [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes) language code of the target language for the translation. For example, `en` for English, `zh` for Chinese, `fr` for French, `es` for Spanish. If the language has a variant, the code appends the two-digit [ISO-3166 country code](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes). For example, Mexican Spanish is `es-MX`. See the [list of supported languages and language codes](https://dev.writer.com/api-reference/translation-api/language-support).\n\n- `text: string`\n The text to translate. Maximum of 100,000 words.\n\n### Returns\n\n- `{ data: string; }`\n\n - `data: string`\n\n### Example\n\n```typescript\nimport Writer from 'writer-sdk';\n\nconst client = new Writer();\n\nconst translationResponse = await client.translation.translate({\n formality: true,\n length_control: true,\n mask_profanity: true,\n model: 'palmyra-translate',\n source_language_code: 'en',\n target_language_code: 'es',\n text: 'Hello, world!',\n});\n\nconsole.log(translationResponse);\n```",
- perLanguage: {
- typescript: {
- method: 'client.translation.translate',
- example:
- "import Writer from 'writer-sdk';\n\nconst client = new Writer({\n apiKey: process.env['WRITER_API_KEY'], // This is the default and can be omitted\n});\n\nconst translationResponse = await client.translation.translate({\n formality: true,\n length_control: true,\n mask_profanity: true,\n model: 'palmyra-translate',\n source_language_code: 'en',\n target_language_code: 'es',\n text: 'Hello, world!',\n});\n\nconsole.log(translationResponse.data);",
- },
- python: {
- method: 'translation.translate',
- example:
- 'import os\nfrom writerai import Writer\n\nclient = Writer(\n api_key=os.environ.get("WRITER_API_KEY"), # This is the default and can be omitted\n)\ntranslation_response = client.translation.translate(\n formality=True,\n length_control=True,\n mask_profanity=True,\n model="palmyra-translate",\n source_language_code="en",\n target_language_code="es",\n text="Hello, world!",\n)\nprint(translation_response.data)',
- },
- go: {
- method: 'client.Translation.Translate',
- example:
- 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/stainless-sdks/writer-go"\n\t"github.com/stainless-sdks/writer-go/option"\n)\n\nfunc main() {\n\tclient := writersdk.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\ttranslationResponse, err := client.Translation.Translate(context.TODO(), writersdk.TranslationTranslateParams{\n\t\tTranslationRequest: writersdk.TranslationRequestParam{\n\t\t\tFormality: writersdk.F(true),\n\t\t\tLengthControl: writersdk.F(true),\n\t\t\tMaskProfanity: writersdk.F(true),\n\t\t\tModel: writersdk.F(writersdk.TranslationRequestModelPalmyraTranslate),\n\t\t\tSourceLanguageCode: writersdk.F("en"),\n\t\t\tTargetLanguageCode: writersdk.F("es"),\n\t\t\tText: writersdk.F("Hello, world!"),\n\t\t},\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", translationResponse.Data)\n}\n',
- },
- http: {
- example:
- 'curl https://api.writer.com/v1/translation \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $WRITER_API_KEY" \\\n -d \'{\n "formality": true,\n "length_control": true,\n "mask_profanity": true,\n "model": "palmyra-translate",\n "source_language_code": "en",\n "target_language_code": "es",\n "text": "Hello, world!"\n }\'',
- },
- },
- },
{
name: 'analyze',
endpoint: '/v1/vision',
diff --git a/packages/mcp-server/src/methods.ts b/packages/mcp-server/src/methods.ts
index c20ca99b..8f9f51ab 100644
--- a/packages/mcp-server/src/methods.ts
+++ b/packages/mcp-server/src/methods.ts
@@ -178,12 +178,6 @@ export const sdkMethods: SdkMethod[] = [
httpMethod: 'post',
httpPath: '/v1/tools/web-search',
},
- {
- clientCallName: 'client.translation.translate',
- fullyQualifiedName: 'translation.translate',
- httpMethod: 'post',
- httpPath: '/v1/translation',
- },
{
clientCallName: 'client.vision.analyze',
fullyQualifiedName: 'vision.analyze',
diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts
index c57801b0..7391cde6 100644
--- a/packages/mcp-server/src/server.ts
+++ b/packages/mcp-server/src/server.ts
@@ -28,7 +28,7 @@ export const newMcpServer = async ({
new McpServer(
{
name: 'writer_sdk_api',
- version: '3.0.0',
+ version: '3.1.0-rc.1',
},
{
instructions: await getInstructions({ stainlessApiKey, customInstructionsPath }),
diff --git a/src/client.ts b/src/client.ts
index eb4689c9..60430c34 100644
--- a/src/client.ts
+++ b/src/client.ts
@@ -83,12 +83,6 @@ import {
ToolWebSearchResponse,
Tools,
} from './resources/tools';
-import {
- Translation,
- TranslationRequest,
- TranslationResponse,
- TranslationTranslateParams,
-} from './resources/translation';
import { Vision, VisionAnalyzeParams, VisionRequest, VisionResponse } from './resources/vision';
import {
ApplicationGenerateContentChunk,
@@ -774,11 +768,19 @@ export class Writer {
return () => controller.abort();
}
- private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): {
+ private buildBody({ options }: { options: FinalRequestOptions }): {
bodyHeaders: HeadersLike;
body: BodyInit | undefined;
} {
+ const { body, headers: rawHeaders } = options;
if (!body) {
+ // A resource method always passes a `body` key when its operation defines a
+ // request body, even if the caller omitted an optional body param. Keep the
+ // content-type for those, and only elide it for operations with no body at
+ // all (e.g. GET/DELETE).
+ if (body == null && 'body' in options) {
+ return this.#encoder({ body, headers: buildHeaders([rawHeaders]) });
+ }
return { bodyHeaders: undefined, body: undefined };
}
const headers = buildHeaders([rawHeaders]);
@@ -845,7 +847,6 @@ export class Writer {
graphs: API.Graphs = new API.Graphs(this);
files: API.Files = new API.Files(this);
tools: API.Tools = new API.Tools(this);
- translation: API.Translation = new API.Translation(this);
vision: API.Vision = new API.Vision(this);
}
@@ -856,7 +857,6 @@ Writer.Models = Models;
Writer.Graphs = Graphs;
Writer.Files = Files;
Writer.Tools = Tools;
-Writer.Translation = Translation;
Writer.Vision = Vision;
export declare namespace Writer {
@@ -948,13 +948,6 @@ export declare namespace Writer {
type ToolWebSearchParams as ToolWebSearchParams,
};
- export {
- Translation as Translation,
- type TranslationRequest as TranslationRequest,
- type TranslationResponse as TranslationResponse,
- type TranslationTranslateParams as TranslationTranslateParams,
- };
-
export {
Vision as Vision,
type VisionRequest as VisionRequest,
diff --git a/src/resources/index.ts b/src/resources/index.ts
index 528a38ec..32fa63a3 100644
--- a/src/resources/index.ts
+++ b/src/resources/index.ts
@@ -71,10 +71,4 @@ export {
type ToolParsePdfParams,
type ToolWebSearchParams,
} from './tools';
-export {
- Translation,
- type TranslationRequest,
- type TranslationResponse,
- type TranslationTranslateParams,
-} from './translation';
export { Vision, type VisionRequest, type VisionResponse, type VisionAnalyzeParams } from './vision';
diff --git a/src/resources/translation.ts b/src/resources/translation.ts
deleted file mode 100644
index b5ce8c32..00000000
--- a/src/resources/translation.ts
+++ /dev/null
@@ -1,141 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { APIResource } from '../core/resource';
-import { APIPromise } from '../core/api-promise';
-import { RequestOptions } from '../internal/request-options';
-
-export class Translation extends APIResource {
- /**
- * Translate text from one language to another.
- *
- * @deprecated Will be removed in a future release. Migrate to `chat.chat` with the translate tool for translation capabilities. See documentation at dev.writer.com for more information.
- */
- translate(body: TranslationTranslateParams, options?: RequestOptions): APIPromise {
- return this._client.post('/v1/translation', { body, ...options });
- }
-}
-
-export interface TranslationRequest {
- /**
- * Whether to use formal or informal language in the translation. See the
- * [list of languages that support formality](https://dev.writer.com/api-reference/translation-api/language-support#formality).
- * If the language does not support formality, this parameter is ignored.
- */
- formality: boolean;
-
- /**
- * Whether to control the length of the translated text. See the
- * [list of languages that support length control](https://dev.writer.com/api-reference/translation-api/language-support#length-control).
- * If the language does not support length control, this parameter is ignored.
- */
- length_control: boolean;
-
- /**
- * Whether to mask profane words in the translated text. See the
- * [list of languages that do not support profanity masking](https://dev.writer.com/api-reference/translation-api/language-support#profanity-masking).
- * If the language does not support profanity masking, this parameter is ignored.
- */
- mask_profanity: boolean;
-
- /**
- * The model to use for translation.
- */
- model: 'palmyra-translate';
-
- /**
- * The [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes)
- * language code of the original text to translate. For example, `en` for English,
- * `zh` for Chinese, `fr` for French, `es` for Spanish. If the language has a
- * variant, the code appends the two-digit
- * [ISO-3166 country code](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes).
- * For example, Mexican Spanish is `es-MX`. See the
- * [list of supported languages and language codes](https://dev.writer.com/api-reference/translation-api/language-support).
- */
- source_language_code: string;
-
- /**
- * The [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes)
- * language code of the target language for the translation. For example, `en` for
- * English, `zh` for Chinese, `fr` for French, `es` for Spanish. If the language
- * has a variant, the code appends the two-digit
- * [ISO-3166 country code](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes).
- * For example, Mexican Spanish is `es-MX`. See the
- * [list of supported languages and language codes](https://dev.writer.com/api-reference/translation-api/language-support).
- */
- target_language_code: string;
-
- /**
- * The text to translate. Maximum of 100,000 words.
- */
- text: string;
-}
-
-export interface TranslationResponse {
- /**
- * The result of the translation.
- */
- data: string;
-}
-
-export interface TranslationTranslateParams {
- /**
- * Whether to use formal or informal language in the translation. See the
- * [list of languages that support formality](https://dev.writer.com/api-reference/translation-api/language-support#formality).
- * If the language does not support formality, this parameter is ignored.
- */
- formality: boolean;
-
- /**
- * Whether to control the length of the translated text. See the
- * [list of languages that support length control](https://dev.writer.com/api-reference/translation-api/language-support#length-control).
- * If the language does not support length control, this parameter is ignored.
- */
- length_control: boolean;
-
- /**
- * Whether to mask profane words in the translated text. See the
- * [list of languages that do not support profanity masking](https://dev.writer.com/api-reference/translation-api/language-support#profanity-masking).
- * If the language does not support profanity masking, this parameter is ignored.
- */
- mask_profanity: boolean;
-
- /**
- * The model to use for translation.
- */
- model: 'palmyra-translate';
-
- /**
- * The [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes)
- * language code of the original text to translate. For example, `en` for English,
- * `zh` for Chinese, `fr` for French, `es` for Spanish. If the language has a
- * variant, the code appends the two-digit
- * [ISO-3166 country code](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes).
- * For example, Mexican Spanish is `es-MX`. See the
- * [list of supported languages and language codes](https://dev.writer.com/api-reference/translation-api/language-support).
- */
- source_language_code: string;
-
- /**
- * The [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes)
- * language code of the target language for the translation. For example, `en` for
- * English, `zh` for Chinese, `fr` for French, `es` for Spanish. If the language
- * has a variant, the code appends the two-digit
- * [ISO-3166 country code](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes).
- * For example, Mexican Spanish is `es-MX`. See the
- * [list of supported languages and language codes](https://dev.writer.com/api-reference/translation-api/language-support).
- */
- target_language_code: string;
-
- /**
- * The text to translate. Maximum of 100,000 words.
- */
- text: string;
-}
-
-export declare namespace Translation {
- export {
- type TranslationRequest as TranslationRequest,
- type TranslationResponse as TranslationResponse,
- type TranslationTranslateParams as TranslationTranslateParams,
- };
-}
diff --git a/src/version.ts b/src/version.ts
index bccd5c23..4cd31ec7 100644
--- a/src/version.ts
+++ b/src/version.ts
@@ -1 +1 @@
-export const VERSION = '3.0.0'; // x-release-please-version
+export const VERSION = '3.1.0-rc.1'; // x-release-please-version
diff --git a/tests/api-resources/translation.test.ts b/tests/api-resources/translation.test.ts
deleted file mode 100644
index 9098b182..00000000
--- a/tests/api-resources/translation.test.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import Writer from 'writer-sdk';
-
-const client = new Writer({
- apiKey: 'My API Key',
- baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010',
-});
-
-describe('resource translation', () => {
- test('translate: only required params', async () => {
- const responsePromise = client.translation.translate({
- formality: true,
- length_control: true,
- mask_profanity: true,
- model: 'palmyra-translate',
- source_language_code: 'en',
- target_language_code: 'es',
- text: 'Hello, world!',
- });
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- test('translate: required and optional params', async () => {
- const response = await client.translation.translate({
- formality: true,
- length_control: true,
- mask_profanity: true,
- model: 'palmyra-translate',
- source_language_code: 'en',
- target_language_code: 'es',
- text: 'Hello, world!',
- });
- });
-});
diff --git a/yarn.lock b/yarn.lock
index d896de63..5b852591 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1269,9 +1269,9 @@ baseline-browser-mapping@^2.9.0:
integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==
brace-expansion@^2.0.2:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.1.tgz#c68b1c4111c76aae3a6fba55d496cee10c39dad8"
- integrity sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.2.tgz#0bba2271feb7d458b0d31ad13625aaa4754431e2"
+ integrity sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==
dependencies:
balanced-match "^1.0.0"