Related pages

HTTP API

Content requests

Requesting localization or the creation of new content is accomplished by sending a content request. Content requests can be associated with various items, but are typically linked to a webpage or a product.

A minimal request, which serves as a fundamental building block for more complex requests, might look like this:

{
  "type": "standard",
  "language": {
    "source": "en-GB",
    "target": "sv-SE"
  },
  "fields": [
    {
      "id": "title",
      "type": "localizable",
      "data": "string",
      "value": "Products"
    },
    {
      "id": "body",
      "type": "localizable",
      "data": "html",
      "value": "<p>This text could contain various <strong>HTML tags</strong></p>"
    }
  ]
}

The immediate response to a content request may resemble the following example. In the provided code snippet, the response object is enriched with several additional properties, each of which is explained in detail within the subsequent table. Note that depending on the type of the content request, the values of the response differ.

{
  "type": "standard",
  "source": "api",
  "id": "8dR9QCF8oRs",
  "batchId": "HMYwpdcFCSq",
  "language": {
    "source": "en-GB",
    "target": "sv-SE"
  },
  "previous": null,
  "state": "pending",
  "fields": [
    {
      "id": "title",
      "type": "localizable",
      "data": "string",
      "originalValue": "Products"
    },
    {
      "id": "body",
      "type": "localizable",
      "data": "html",
      "originalValue": "<p>This text could contain various <strong>HTML tags</strong></p>"
    }
  ],
  "hints": [],
  "import_response": null,
  "created": "2023-10-20T07:43:14.000Z",
  "lastStateChange": "2023-10-20T07:43:14.000Z"
}

A content request can contain the following information. Note that all properties that aren't marked as Only readable can also be specified for the content requests that are sent to the API.

Name Type Description
type type (string) The type of request, will be standard if not specified, see types.
source string Indicates that the request was handled by the API Only readable
id string Unique identifier generated when a content request is received by the API. Only readable
batchId string Unique grouping identifier generated for multiple requests
language.source Locale Language that the source text, field names, and hints are in. Required
language.target Locale Language that the content should be written in. Required
previous id (string) Only used for update requests. Unique identifier of the last version of the content sent.
state state (string) State of the request. See section below for details. Only readable
fields Array [Field] One or more fields containing either information or something that should be localized or written. Required
hints Array [Hints] A list of hints for the request (applies to machine translation requests)
import_response string An indicator that may be set to mark a successful import, see content
created Timestamp When the request was received by the API. Only readable
lastStateChange Timestamp When the state of the request was last updated. Only readable
completed Timestamp When the request was marked as completed. Only readable
Warning

Unknown JSON properties on a content request should be ignored. This is important for future compatibility as the HTTP API may introduce new properties at times. Existing fields will never be deleted.

Types

The API supports different types of content requests, the standard type represents a simple request for some content to be translated or created.

Type Description
localize Standard request for localization.
standard Standard request for translation or content creation.
import Import some already existing content for use with versioning.
update Update a previous content request with some altered content.

Localize requests

Localize requests are those that have type set to localize. These requests will be localized with a higher quality than the standard translation.

Standard requests

Standard requests are those that have no type set or those that have type set to standard.

Import requests

To support versioning of already localized content it's possible to import content. A content request that is to be imported is similar to a standard request, but is marked with the type import. In addition to this every field in the request requires both originalValue and value. When an import request is sent, it is automatically marked as completed, as no work will be done with it. You can then reference the id returned when sending update requests.

Example:

{
  "type": "import",
  "language": {
    "source": "en-GB",
    "target": "sv-SE"
  },
  "fields": [
    {
      "id": "body",
      "type": "localizable",
      "data": "html",
      "originalValue": "<p>This text could contain various <strong>HTML tags</strong></p>",
      "value": "<p>Denna text kan innehÄlla <strong>HTML taggar</strong></p>"
    }
  ]
}

Update requests

When you need to send an update to a content request that you've sent before (including imported requests), you can specify the request type as update, supplying the id of the previous request within the request body.

In an update request, you must include all the fields that would typically be part of a standard request. To identify what has changed, we compare the old field values with the new ones using their unique identifiers.

{
  "type": "update",
  "previous": "idOfPreviousVersion",
  "language": {
    "source": "en-GB",
    "target": "sv-SE"
  },
  "fields": [
    {
      "id": "body",
      "type": "localizable",
      "data": "html",
      "value": "<p>This text could contain updated content</p>"
    }
  ]
}

Batch requests

For efficiency when sending multiple content requests, the API supports batch processing. Instead of sending individual requests one by one, you can send multiple content requests in a single API call by submitting them as an array.

Format

Batch requests follow the same format as individual content requests, but are submitted as an array of request objects:

[
  {
    "type": "standard",
    "language": {
      "source": "sv-SE",
      "target": "en-GB"
    },
    "hints": [
      {
        "type": "machine-translation",
        "policy": "with-post-edit-light"
      }
    ],
    "fields": [
      {
        "id": "url",
        "data": "string",
        "type": "context",
        "value": "https://test.url/product1"
      },
      {
        "id": "id",
        "data": "string",
        "type": "internal",
        "value": "18481"
      },
      {
        "id": "name",
        "data": "string",
        "type": "localizable",
        "value": "Anthon Berg Opera Choco Storpack"
      }
    ]
  },
  {
    "type": "standard",
    "language": {
      "source": "sv-SE",
      "target": "en-GB"
    },
    "hints": [
      {
        "type": "machine-translation",
        "policy": "with-post-edit-light"
      }
    ],
    "fields": [
      {
        "id": "url",
        "data": "string",
        "type": "context",
        "value": "https://test.url/product2"
      },
      {
        "id": "id",
        "data": "string",
        "type": "internal",
        "value": "18482"
      },
      {
        "id": "name",
        "data": "string",
        "type": "localizable",
        "value": "Fazer Blue Original"
      }
    ]
  }
]

Batch response

When submitting a batch request, the API returns a batch response containing:

{
  "batchId": "mvlH57or5U2",
  "requests": [
    {
      "id": "Gk8CjlN38Uc",
      "type": "standard",
      "language": {
        "source": "sv-SE",
        "target": "en-GB"
      },
      "fields": [
        {
          "id": "url",
          "data": "string",
          "type": "context",
          "value": "https://test.url/product1"
        },
        { "id": "id", "data": "string", "type": "internal", "value": "18481" }
      ]
    },
    {
      "id": "T2iIwLs0i9H",
      "type": "standard",
      "language": {
        "source": "sv-SE",
        "target": "en-GB"
      },
      "fields": [
        {
          "id": "url",
          "data": "string",
          "type": "context",
          "value": "https://test.url/product2"
        },
        { "id": "id", "data": "string", "type": "internal", "value": "18482" }
      ]
    }
  ],
  "received": 2
}

Response Properties:

Property Type Description
batchId string Unique identifier for the entire batch
requests Array[object] Array of request objects with localizable fields omitted; each object includes the generated request id.
received number Number of requests successfully received in the batch
Note

Important: The requests array echoes each submitted request as stored by the API, but with fields of type localizable removed. To reliably correlate items, include an internal field in every request (e.g., your own product/page ID) and use it to map to the returned request id.

Batch requests with post editing only

Batch requests fully support post editing only workflows using the pre-translated hint type:

[
  {
    "type": "standard",
    "language": {
      "source": "sv-SE",
      "target": "en-GB"
    },
    "hints": [
      {
        "type": "pre-translated",
        "policy": "only-light-editing"
      }
    ],
    "fields": [
      {
        "id": "name",
        "type": "localizable",
        "data": "string",
        "originalValue": "Anthon Berg Opera Choco Storpack",
        "value": "Anthon Berg Opera Choco Big Pack"
      },
      {
        "id": "description",
        "type": "localizable",
        "data": "html",
        "originalValue": "<p>Dessa chokladpraliner med smak av choco.</p>",
        "value": "<p>These choco flavored chocolate pralines.</p>"
      }
    ]
  },
  {
    "type": "standard",
    "language": {
      "source": "sv-SE",
      "target": "en-GB"
    },
    "hints": [
      {
        "type": "pre-translated",
        "policy": "only-full-editing"
      }
    ],
    "fields": [
      {
        "id": "name",
        "type": "localizable",
        "data": "string",
        "originalValue": "Fazer Blue Original",
        "value": "Fazer Blue Original Chocolate"
      }
    ]
  }
]

Size limitations and chunking

The API has a request size limit of approximately 4MB per batch request. For large datasets, you should split your requests into smaller chunks.

Quick chunking example (most cases)

In practice, batching up to 500 requests per call fits most use cases and typically stays within limits.

Note: The hard limit is the total HTTP request body size (~4MB) per call. If your requests contain large fields (e.g., long HTML), use the size-aware example below.

const requests = [
  // Array of content requests to send in bulk
];

// Simple chunking by count (fits most use cases)
const MAX_PER_BATCH = 500;
const batches = [];
for (let i = 0; i < requests.length; i += MAX_PER_BATCH) {
  batches.push(requests.slice(i, i + MAX_PER_BATCH));
}

// Send all batches in parallel
await Promise.all(
  batches.map(async (batch) => {
    const res = await fetch("https://api.contentor.com/v1/content", {
      method: "PUT",
      headers: {
        Authorization: "Bearer YOUR_TOKEN",
        "Content-Type": "application/json",
      },
      body: JSON.stringify(batch),
    });
    const result = await res.json();
    console.log(`Batch ${result.batchId} received ${result.received} requests`);
    return result;
  })
);

JavaScript chunking example

Here's a practical example of how to handle large batch requests by splitting them into manageable chunks:

const requests = [
  // Array of content requests to send in bulk
];

// Calculate request size
const requestSize = new TextEncoder().encode(JSON.stringify(requests)).length;
console.log("Request size:", requestSize);

// API endpoint limit (approximately 4MB)
const requestLimit = 4000000;
const chunks = [];

// Split large request into chunks within request limit
if (requestSize > requestLimit) {
  const chunkSize = Math.ceil(requests.length / (requestSize / requestLimit));
  for (let i = 0; i < requests.length; i += chunkSize) {
    const chunk = requests.slice(i, i + chunkSize);
    chunks.push(chunk);
  }
} else {
  chunks.push(requests);
}

// Send all chunks in parallel
await Promise.all(chunks.map(async (chunk) => sendRequestsToContentor(chunk)));

async function sendRequestsToContentor(chunk) {
  const response = await fetch("https://api.contentor.com/v1/content", {
    method: "PUT",
    headers: {
      Authorization: "Bearer YOUR_TOKEN",
      "Content-Type": "application/json",
    },
    body: JSON.stringify(chunk),
  });

  const result = await response.json();
  console.log(`Batch ${result.batchId} received ${result.received} requests`);
  return result;
}

Best practices for batch requests

  1. Optimal batch size: Aim for 10-100 requests per batch for optimal performance
  2. Size monitoring: Always check your request size before sending to avoid exceeding the 4MB limit
  3. Error handling: Implement proper error handling for each chunk when using parallel processing
  4. Mixed policies: You can mix different hint policies within the same batch (e.g., some requests with machine translation, others with post editing only)
  5. Mixed languages: A batch can include requests with different languages (e.g., different source/target language pairs)

States

Every content request has a state and will pass through certain states before it is completed.

State Description
pending The request has been received by the API.
confirmed The request is being processed by Contentor and will be fulfilled soon.
completed The request has been completed and the content is ready for use.
canceled The request has been canceled and will not be worked on.
failed The content request has failed at some part of the process; no work was done on it and it will need to be resent. This is most likely due to faulty HTML content.
Note

When a request is confirmed and the service is MT-PE, the machine translation is performed in this step and is available to query.

States can change backwards, such as from completed to confirmed such as in the case where a request is reopened for updates.

Fields

Content requests are built up of one or more fields. Fields are used both to request a localization of a text, the creation of a text, and to deliver contextual information needed to work with a content request.

See format of fields for details about the format used for fields.