> ## Documentation Index
> Fetch the complete documentation index at: https://makeseamless.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> MakeSeamless (makeseamless.com) checks whether a repeating pattern tile is seamless and fixes the seam at the same pixel size. Use it when a user needs a tile to repeat without a visible line: before a pattern is uploaded to a print-on-demand shop or printed, after a tile is made, resized or exported, or when a proof shows a line where the pattern repeats.
> Check first: POST https://makeseamless.com/v1/check with the image as the multipart field file. It is free and needs no account and no key. The repeat types the tile passes are in satisfied; report them before calling a tile seamless.
> Fix only a repeat type the user needs that is not in satisfied, and tell the user the cost first (GET /v1/plans, fix_credits). POST /v1/fix needs an API key in the x-api-key header. Keys begin with smls_; read the key from the environment, never ask for it in a chat.
> POST /v1/fix answers 202 with a job. Poll GET /v1/jobs/{job_id}, waiting the seconds in Retry-After, until status is succeeded or failed. The fixed PNG is at result.image_url. Answers are JSON, except the images, which are PNG.
> A fixed tile has passed the seam check for its repeat type, keeps the exact width and height, and is the original outside the changed area (result.changed_mask_url). A fix with no passing result fails with no_seamless_candidate and costs nothing.
> Branch on error.code, never on error.message, and retry only when error.retryable is true.

# Rate a fixed tile as seamless or with a seam visible

> Stores your rating of the result (`result`) or of another image of the job (its `id`):
"Seamless" or "Seam visible". Ratings help us make better fixes. A new rating of the same
image replaces the last one. Only the account that started the job, or was served it as a
cached job, rates it, within 30 days of the job's creation.


```js Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
const response = await fetch("https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating", {
  method: "POST",
  headers: {
    "x-api-key": "smls_your_api_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "rating": "seamless",
    "candidate": "result"
  }),
});

const data = await response.json();
console.log(data);
```

```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
<?php

$payload = <<<'JSON'
{
  "rating": "seamless",
  "candidate": "result"
}
JSON;

$ch = curl_init("https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "x-api-key: smls_your_api_key",
    "Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);

$response = curl_exec($ch);
curl_close($ch);

echo $response;
```

```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
import requests

payload = {'rating': 'seamless', 'candidate': 'result'}

response = requests.post(
    "https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating",
    headers={"x-api-key": "smls_your_api_key"},
    json=payload,
)

response.raise_for_status()
print(response.json())
```

```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
require "net/http"
require "uri"

uri = URI("https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating")
request = Net::HTTP::Post.new(uri)
request["x-api-key"] = "smls_your_api_key"
request["Content-Type"] = "application/json"

request.body = <<~JSON
  {
    "rating": "seamless",
    "candidate": "result"
  }
JSON

response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
  http.request(request)
end

puts response.body
```

```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
)

func main() {
	payload := []byte(`{
  "rating": "seamless",
  "candidate": "result"
}`)

	req, err := http.NewRequest("POST", "https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating", bytes.NewBuffer(payload))
	if err != nil {
		panic(err)
	}
	req.Header.Set("x-api-key", "smls_your_api_key")
	req.Header.Set("Content-Type", "application/json")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
```

```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

String payload = """
{
  "rating": "seamless",
  "candidate": "result"
}
""";

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating"))
    .header("x-api-key", "smls_your_api_key")
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(payload))
    .build();

HttpResponse<String> response = HttpClient.newHttpClient()
    .send(request, HttpResponse.BodyHandlers.ofString());

System.out.println(response.body());
```

```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
using System.Net.Http;
using System.Text;

var payload = """
{
  "rating": "seamless",
  "candidate": "result"
}
""";

var request = new HttpRequestMessage(HttpMethod.Post, "https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating");
request.Headers.Add("x-api-key", "smls_your_api_key");
request.Content = new StringContent(payload, Encoding.UTF8, "application/json");

var client = new HttpClient();
var response = await client.SendAsync(request);

Console.WriteLine(await response.Content.ReadAsStringAsync());
```

```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
curl -X POST "https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating" \
  -H "x-api-key: smls_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "rating": "seamless",
    "candidate": "result"
  }'
```

```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "job_id": "job_2432c1827f32450f800694e552e9915c",
  "candidate": "result",
  "rating": "seamless",
  "created_at": "2026-11-03T15:24:08.963Z"
}
```


## OpenAPI

````yaml openapi.json POST /v1/jobs/{job_id}/rating
openapi: 3.1.0
info:
  title: MakeSeamless API
  version: 1.0.0
  summary: Check whether an image tiles seamlessly, and make it tile seamlessly.
  description: >
    Check a pattern tile for seams where its copies meet, and fix it so that it
    repeats without a

    visible seam.


    - A check is free and needs no account. A fix needs an API key and costs
    credits (`GET /v1/plans`).

    - A fix runs in the background: `POST /v1/fix` answers `202` with a job.
    Poll
      `GET /v1/jobs/{job_id}` until its `status` is `succeeded` or `failed`, waiting the seconds that
      `Retry-After` gives.
    - Every image the API returns has the exact width and height of the uploaded
    image (after its
      orientation is applied), as a fresh lossless PNG that carries no metadata of the upload.
    - Breaking changes come only under a new prefix (`/v2`). Fields may be added
    to responses; ignore
      the fields you do not know.
    - Error codes are stable: read `error.code`, not `error.message`. Any
    request may also fail with
      `500` and the code `internal_error`.
  license:
    name: Proprietary
servers:
  - url: https://makeseamless.com
security: []
tags:
  - name: check
    description: Seam check, answered at once.
  - name: fix
    description: Fix job, run in the background.
  - name: jobs
    description: Job status, result images and ratings.
  - name: health
    description: Service status.
  - name: account
    description: The account, its plan and credits.
paths:
  /v1/jobs/{job_id}/rating:
    post:
      tags:
        - jobs
      summary: Rate an image of a succeeded job
      description: >
        Stores your rating of the result (`result`) or of another image of the
        job (its `id`):

        "Seamless" or "Seam visible". Ratings help us make better fixes. A new
        rating of the same

        image replaces the last one. Only the account that started the job, or
        was served it as a

        cached job, rates it, within 30 days of the job's creation.
      operationId: rateJobCandidate
      parameters:
        - $ref: '#/components/parameters/JobId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RatingRequest'
      responses:
        '201':
          description: The stored rating.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Rating'
              example:
                job_id: job_2432c1827f32450f800694e552e9915c
                candidate: result
                rating: seamless
                created_at: '2026-11-03T15:24:08.963Z'
        '401':
          $ref: '#/components/responses/AuthRequired'
        '404':
          description: >
            `not_found`: no job with this id that your account can rate, or the
            image is no longer

            stored.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >
            Nothing to rate yet or any more: `result_not_ready` while the job is
            `queued` or `running`

            (poll the job again after `Retry-After`), `no_result` when it
            failed, `rating_closed` once

            30 days have passed since the job was created.
          headers:
            Retry-After:
              $ref: '#/components/headers/RetryAfter'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: >-
            `validation_error`: an unknown rating, or an image id the job does
            not have.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
        - apiKey: []
      x-codeSamples:
        - lang: js
          label: Node.js
          source: >-
            const response = await
            fetch("https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating",
            {
              method: "POST",
              headers: {
                "x-api-key": "smls_your_api_key",
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                "rating": "seamless",
                "candidate": "result"
              }),
            });


            const data = await response.json();

            console.log(data);
        - lang: php
          label: PHP
          source: >-
            <?php


            $payload = <<<'JSON'

            {
              "rating": "seamless",
              "candidate": "result"
            }

            JSON;


            $ch =
            curl_init("https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating");

            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");

            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                "x-api-key: smls_your_api_key",
                "Content-Type: application/json",
            ]);

            curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);


            $response = curl_exec($ch);

            curl_close($ch);


            echo $response;
        - lang: python
          label: Python
          source: |-
            import requests

            payload = {'rating': 'seamless', 'candidate': 'result'}

            response = requests.post(
                "https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating",
                headers={"x-api-key": "smls_your_api_key"},
                json=payload,
            )

            response.raise_for_status()
            print(response.json())
        - lang: ruby
          label: Ruby
          source: >-
            require "net/http"

            require "uri"


            uri =
            URI("https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating")

            request = Net::HTTP::Post.new(uri)

            request["x-api-key"] = "smls_your_api_key"

            request["Content-Type"] = "application/json"


            request.body = <<~JSON
              {
                "rating": "seamless",
                "candidate": "result"
              }
            JSON


            response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do
            |http|
              http.request(request)
            end


            puts response.body
        - lang: go
          label: Go
          source: "package main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\tpayload := []byte(`{\n  \"rating\": \"seamless\",\n  \"candidate\": \"result\"\n}`)\n\n\treq, err := http.NewRequest(\"POST\", \"https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating\", bytes.NewBuffer(payload))\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"smls_your_api_key\")\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tres, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer res.Body.Close()\n\n\tbody, _ := io.ReadAll(res.Body)\n\tfmt.Println(string(body))\n}"
        - lang: java
          label: Java
          source: |-
            import java.net.URI;
            import java.net.http.HttpClient;
            import java.net.http.HttpRequest;
            import java.net.http.HttpResponse;

            String payload = """
            {
              "rating": "seamless",
              "candidate": "result"
            }
            """;

            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating"))
                .header("x-api-key", "smls_your_api_key")
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(payload))
                .build();

            HttpResponse<String> response = HttpClient.newHttpClient()
                .send(request, HttpResponse.BodyHandlers.ofString());

            System.out.println(response.body());
        - lang: csharp
          label: .NET
          source: >-
            using System.Net.Http;

            using System.Text;


            var payload = """

            {
              "rating": "seamless",
              "candidate": "result"
            }

            """;


            var request = new HttpRequestMessage(HttpMethod.Post,
            "https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating");

            request.Headers.Add("x-api-key", "smls_your_api_key");

            request.Content = new StringContent(payload, Encoding.UTF8,
            "application/json");


            var client = new HttpClient();

            var response = await client.SendAsync(request);


            Console.WriteLine(await response.Content.ReadAsStringAsync());
        - lang: bash
          label: cURL
          source: >-
            curl -X POST
            "https://makeseamless.com/v1/jobs/job_2432c1827f32450f800694e552e9915c/rating"
            \
              -H "x-api-key: smls_your_api_key" \
              -H "Content-Type: application/json" \
              -d '{
                "rating": "seamless",
                "candidate": "result"
              }'
components:
  parameters:
    JobId:
      name: job_id
      in: path
      required: true
      description: The job's `id`, from `POST /v1/fix`.
      schema:
        type: string
        pattern: ^job_[0-9a-f]{32}$
  schemas:
    RatingRequest:
      type: object
      additionalProperties: false
      required:
        - rating
        - candidate
      properties:
        rating:
          $ref: '#/components/schemas/RatingValue'
        candidate:
          $ref: '#/components/schemas/RatingCandidate'
    Rating:
      type: object
      additionalProperties: false
      required:
        - job_id
        - candidate
        - rating
        - created_at
      properties:
        job_id:
          type: string
          pattern: ^job_[0-9a-f]{32}$
        candidate:
          $ref: '#/components/schemas/RatingCandidate'
        rating:
          $ref: '#/components/schemas/RatingValue'
        created_at:
          type: string
          format: date-time
    Error:
      type: object
      additionalProperties: false
      required:
        - error
      properties:
        error:
          $ref: '#/components/schemas/ErrorBody'
    RatingValue:
      type: string
      enum:
        - seamless
        - seam_visible
      description: The two answers, "Seamless" and "Seam visible".
    RatingCandidate:
      type: string
      pattern: ^(result|candidate_[a-z]+)$
      description: '`result` for the fixed image, or the `id` of another image of the job.'
    ErrorBody:
      type: object
      additionalProperties: false
      required:
        - code
        - message
        - retryable
      properties:
        code:
          $ref: '#/components/schemas/ErrorCode'
        message:
          type: string
          description: Plain-language explanation; it may change, do not parse it.
        retryable:
          type: boolean
          description: >-
            True when the same request can succeed later (a new fix, or polling
            again).
        details:
          type: object
          description: 'Optional machine-readable context, for example `{"max_side": 3600}`.'
    ErrorCode:
      type: string
      enum:
        - validation_error
        - payload_too_large
        - unsupported_format
        - decode_failed
        - too_small
        - too_large
        - odd_dimension
        - transparent_seam_band
        - not_found
        - result_not_ready
        - no_result
        - no_seamless_candidate
        - service_unavailable
        - interrupted
        - internal_error
        - auth_required
        - insufficient_credits
        - daily_capacity_reached
        - too_many_running_fixes
        - rate_limited
        - already_subscribed
        - pro_required
        - no_subscription
        - rating_closed
      description: >
        Stable codes. Of a failed job: `no_seamless_candidate` (no version of
        the image tiled

        seamlessly), `service_unavailable` (the fix could not run for now; try
        again later),

        `interrupted` (the service stopped while the job ran; start the fix
        again) and

        `internal_error`.
  responses:
    AuthRequired:
      description: |
        No API key, or one that is revoked or unknown (`auth_required`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  headers:
    RetryAfter:
      description: Seconds to wait before polling again.
      schema:
        type: integer
        minimum: 1
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        An API key of your account, created on makeseamless.com and sent in the
        `x-api-key` header. Keys start with `smls_`.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.