Back to Developers

Record Status API — developer documentation

Preliminary · version 0.9 · 14 October 2026 · My Content Tools LLC · mycontenttools.com

Preliminary. The Record Status API is not open yet. This is an early copy of the public documentation every API Consumer will receive, so your team can plan its work. Details may change before launch. No API keys are issued until the Public API Terms of Use are published at mycontenttools.com/developers.

Machine-readable companions: openapi.json (OpenAPI 3.1, every endpoint, header, field and error) and test-vectors.json (worked signing examples with the exact expected outputs). If you use an AI coding assistant, give it this file, openapi.json and test-vectors.json, and have it check its signing code against the test vectors before calling the API.

1. What the API tells you

Studios use Model Release Pro (phone) and My Content Tools (desktop) to record each scene: the performer's release and ID check. The Record Status API answers one question about one scene record:

Is the studio's record for this performer in this scene complete?

A record is complete when all four of these are on file: the performer's legal name, date of birth, a verified government ID, and the ID document itself.

  • You get a yes/no answer plus the time it was checked.
  • You never get personal data, documents, images or a reason why a record is incomplete.
  • You only get answers for studios that chose to connect your platform. The studio can disconnect at any time.
  • The answer is a status check. It does not by itself satisfy your platform's own record-keeping obligations.

2. How it works, start to finish

  1. Register at mycontenttools.com/developers: company name, website, contact email, and acceptance of the Terms of Use.
  2. Approval. Each account is reviewed and approved by hand. Until then, every request answers 403.
  3. Get your credentials: an API key and a signing secret, shown once. Store them server-side only. Test credentials are also available; they only ever see sample records, so you can build and test before any studio connects.
  4. A studio connects your platform. Your site shows the studio a one-time connection code. The studio enters it in Model Release Pro, sees your registered company name, and confirms (section 3).
  5. The studio gives you the Record IDs for each scene, one per performer, for example in your upload form (section 4).
  6. You ask for the status of that record, one at a time or in batches (section 6).

3. Connecting a studio

Your server requests a connection code with your key (signed as in section 5, with an empty body):

POST /v1/connection-codes
200 OK
{
  "code": "MCT-7Q4KX-R2PHM",
  "expiresAt": "2026-10-14T15:19:06Z"
}
  • Show the code to the studio. Each code works once and expires 15 minutes after it is created.
  • The studio enters it in Model Release Pro under Settings. The app shows the company name you registered and asks the studio to confirm.
  • Once confirmed, the studio's records answer to your key, including records made before the connection. If the studio disconnects, they answer 403 again.
  • Wrong codes are limited per studio, so a studio that enters too many will have to wait before trying again.

4. Record IDs

  • A Record ID identifies one performer's record for one scene. A scene with two performers has two Record IDs. Ask for every performer's Record ID; the batch call takes up to 100 at once.
  • Studios copy Record IDs from the record in Model Release Pro or My Content Tools.
  • Record IDs are random strings. Treat them as opaque, case-sensitive text; do not parse them.
  • An ID that is not a Record ID (for example a performer's own ID) answers 404.

5. Authentication

Every request carries three headers:

HeaderValue
x-mct-platform-keyYour API key.
x-mct-timestampThe current time in UTC, RFC 3339, e.g. 2026-10-14T15:04:05Z. Must be within 5 minutes of our clock.
x-mct-signatureLowercase hex HMAC-SHA256 of the string below, keyed with your signing secret.

The string to sign is four lines joined by a single newline (\n), with no trailing newline:

METHOD
PATH
SHA256_HEX_OF_BODY
TIMESTAMP
  • METHOD: uppercase, e.g. GET or POST.
  • PATH: the request path without the host or query string, e.g. /v1/attestations/AbC123.
  • SHA256_HEX_OF_BODY: lowercase hex SHA-256 of the exact body bytes you send. For a request with no body, hash the empty string.
  • TIMESTAMP: exactly the value you sent in x-mct-timestamp.

Any failure (unknown key, account not approved, bad signature, stale timestamp) answers 403. The API never says which check failed, so check your signing code against test-vectors.json first.

Example: signing a request (Node.js 18+)

import { createHash, createHmac } from 'node:crypto';

const BASE_URL = process.env.MCT_API_BASE_URL;   // issued with your key
const API_KEY = process.env.MCT_API_KEY;
const SIGNING_SECRET = process.env.MCT_SIGNING_SECRET;

export function signedHeaders(method, path, body = '') {
  const timestamp = new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
  const bodyHash = createHash('sha256').update(body, 'utf8').digest('hex');
  const toSign = [method.toUpperCase(), path, bodyHash, timestamp].join('\n');
  const signature = createHmac('sha256', SIGNING_SECRET)
    .update(toSign, 'utf8').digest('hex');
  return {
    'x-mct-platform-key': API_KEY,
    'x-mct-timestamp': timestamp,
    'x-mct-signature': signature,
  };
}

export async function getRecordStatus(recordId) {
  const path = `/v1/attestations/${encodeURIComponent(recordId)}`;
  const res = await fetch(BASE_URL + path, { headers: signedHeaders('GET', path) });
  return { status: res.status, body: await res.json() };
}

export async function getRecordStatuses(recordIds) {
  const path = '/v1/attestations:batch';
  const body = JSON.stringify({ recordIds });
  const res = await fetch(BASE_URL + path, {
    method: 'POST',
    headers: { 'content-type': 'application/json', ...signedHeaders('POST', path, body) },
    body,
  });
  return { status: res.status, body: await res.json() };
}

Sign the exact body string you send. Re-serialising the JSON after signing will break the signature.

6. Endpoints

The base URL is issued with your key. All requests go over HTTPS, server to server. Browser calls are not supported.

Get one record's status

GET /v1/attestations/{recordId}
200 OK
{
  "recordId": "AbC123",
  "attestedAt": "2026-10-14T15:04:06Z",
  "fieldsComplete": true,
  "faceMatch": null,
  "schemaVersion": "1"
}

Get many records' statuses

POST /v1/attestations:batch
Content-Type: application/json

{ "recordIds": ["AbC123", "DeF456"] }
200 OK
{
  "attestations": [
    {
      "recordId": "AbC123",
      "attestedAt": "2026-10-14T15:04:06Z",
      "fieldsComplete": true,
      "faceMatch": null,
      "schemaVersion": "1"
    }
  ]
}
  • Up to 100 IDs per batch. More than 100 answers 400; the list is never cut short silently.
  • Records that do not exist, or that you are not authorised to see, are left out of the array. A missing ID means "no answer for you", never "incomplete". To tell the cases apart, ask for that ID on its own.

7. Response fields

Every successful answer has exactly these five fields, and never more. Treat any other field as an error.

FieldTypeMeaning
recordIdstringThe Record ID you asked about.
attestedAtstringWhen the record was checked, UTC, RFC 3339.
fieldsCompletebooleantrue when legal name, date of birth, verified government ID and the ID document are all on file. Otherwise false.
faceMatchnullReserved. Always null for API Consumers.
schemaVersionstringCurrently "1" (a string, not a number).

8. Status codes

CodeBodyMeaning
200the answerSuccess.
400{"error":"bad_request"}Malformed batch body, or more than 100 IDs.
403{"error":"forbidden"}Authentication failed, or the studio has not connected your platform for this record.
404{"error":"not_found"}No scene record with this ID, or an unknown path.
405{"error":"method_not_allowed"}Wrong method for the path.
429{"error":"rate_limited"}Over your rate limit. Wait for the seconds in the Retry-After header.
5xx{"error":"internal_error"}Our fault. Retry later with backoff.

9. Limits and caching

  • Rate limit: 30 requests per minute per key. In a batch, each ID counts as one request. Higher limits can be requested.
  • No caching: every response carries Cache-Control: no-store. A record's status can change (a studio adds a missing document, or disconnects). Ask again when you need a current answer.

10. Keys

  • Keep your API key and signing secret on your servers. Never put them in a web page or mobile app.
  • You can rotate your credentials yourself. The old and new credentials both work for 24 hours so you can switch without downtime.
  • Keys can be suspended for a breach of the Terms of Use, including sustained abuse of the rate limit.

11. Terms, cost and support

  • Terms of Use: published at mycontenttools.com/developers and accepted at sign-up, before any key is issued.
  • Cost: no charge at launch.
  • Support: this documentation, plus email to support@mycontenttools.com on a best-effort basis. There is no service-level agreement. We cannot provide custom development, integration calls or debugging of your code.

Record Status API · Developer documentation · Preliminary v0.9 · 14 October 2026 · © My Content Tools LLC. Subject to change before launch.