thirds.ai Me API
The Me API from thirds.ai — 1 operation(s) for me.
The Me API from thirds.ai — 1 operation(s) for me.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/thirds-ai:thirds-ai-me-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: thirds.ai Me API
version: 1.0.0
description: Turn one design into content at scale. Create branded images and PDFs for your campaigns and clients. Automate each new version through our API or your AI tools. Render saved templates with new data, or send HTML directly. Every error uses one envelope, every response carries an x-request-id header, and every JSON request body rejects fields it does not expect.
servers:
- url: https://thirds.ai
tags:
- name: Me
paths:
/v1/me/identities/email:
post:
summary: Add an email to an account without one
description: Requires a signed-in browser session and its CSRF token. Sends a one-use verification link bound to that account and exact session. Open the link in the same browser while signed in, then press Complete sign in. POST /v1/auth/email/confirm proves the address and grants the current free monthly credits once. An account with an email cannot change it through this route.
operationId: requestAccountEmail
security:
- sessionCookie: []
parameters:
- name: x-csrf-token
in: header
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AccountEmailRequest'
responses:
'405':
$ref: '#/components/responses/MethodNotAllowed'
'431':
$ref: '#/components/responses/RequestHeadersTooLarge'
'401':
description: A live browser session is required. Expired, revoked, and suspended sessions are refused.
headers:
x-request-id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'403':
description: The CSRF token is missing or does not match this browser session.
headers:
x-request-id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'429':
description: The request limit was reached. Retry after the time in Retry-After.
headers:
x-request-id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'500':
description: The request failed internally.
headers:
x-request-id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'202':
description: The request was accepted. This does not confirm mail delivery or whether another account holds the address.
headers:
x-request-id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/AccountEmailAccepted'
'400':
description: The JSON request is invalid or has unknown fields.
headers:
x-request-id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'409':
description: This account already has an email address. The code is email_already_set.
headers:
x-request-id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'422':
description: The email address is invalid. The code is invalid_email.
headers:
x-request-id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'503':
description: Email delivery is not configured. The code is auth_unavailable.
headers:
x-request-id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
tags:
- Me
components:
schemas:
FieldDetail:
type: object
description: One request field that failed, its fixed safe reason, and an optional bounded source location. Details never carry template source, customer values, rendered output, or raw evaluator prose.
properties:
field:
type: string
maxLength: 260
description: The path to the field, such as "pdf.scale". Schema errors use data followed by a JSON Pointer, such as data/items/0/count. The pointer is cut at 256 UTF-8 bytes. Empty for a problem with the whole document.
reason:
type: string
enum:
- malformed JSON
- missing field
- unknown field
- wrong type
- invalid value
- A required value is missing.
- Use the expected value type.
- Declare this variable before using it.
- Choose an allowed value.
- Use the required format.
- Add a value.
- Use a shorter value.
- Use a number within the allowed range.
- Check this value against its data rule.
description: A fixed, safe reason. It never repeats the value the caller sent.
line:
type: integer
minimum: 1
maximum: 1000000
description: The one-based template source line when the evaluator provides one within the published bound.
column:
type: integer
minimum: 1
maximum: 1000000
description: The one-based template source column when the evaluator provides one within the published bound.
required:
- field
- reason
additionalProperties: false
AccountEmailAccepted:
type: object
additionalProperties: false
AccountEmailRequest:
type: object
properties:
email:
type: string
next:
type: string
description: A safe local path after proof; defaults to /account.
required:
- email
additionalProperties: false
ErrorEnvelope:
type: object
description: The one error shape every backend response uses.
properties:
error:
type: object
properties:
code:
type: string
enum:
- account_suspended
- account_concurrency_limited
- abuse_limited
- ai_failure_limit_reached
- ai_needs_paid_credits
- already_subscribed
- auth_unavailable
- batch_row_limit
- billing_unavailable
- brand_asset_account_limit_reached
- brand_asset_invalid
- brand_asset_kind_invalid
- brand_asset_kind_mismatch
- brand_asset_limit_reached
- brand_asset_too_large
- brand_asset_type_unsupported
- brand_data_conflict
- brand_font_glyphs_exceeded
- brand_font_tables_invalid
- brand_image_animated
- brand_image_dimensions_invalid
- brand_image_pixels_exceeded
- brand_kit_colours_invalid
- brand_kit_conflict
- brand_kit_limit
- brand_kit_name_invalid
- brand_kit_not_found
- brand_kit_patch_empty
- brand_kit_tone_invalid
- brand_kit_unavailable
- captcha_rejected
- checkout_superseded
- cross_origin_rejected
- csrf_rejected
- download_expired
- email_already_set
- gallery_template_not_found
- generated_template_invalid
- idempotency_conflict
- image_asset_header_unsupported
- image_asset_invalid
- image_asset_limit
- image_asset_not_found
- image_asset_reference_invalid
- image_asset_too_large
- image_asset_type_unsupported
- image_asset_unavailable
- image_url_invalid
- image_url_unavailable
- insufficient_credits
- internal_error
- invalid_cursor
- invalid_email
- invalid_event
- invalid_link
- invalid_profile
- invalid_request
- invalid_upload
- job_not_finished
- key_concurrency_limited
- key_limit_reached
- method_not_allowed
- no_billing_customer
- not_found
- operation_conflict
- operation_limit_exceeded
- operation_pending
- overage_limit_reached
- overage_unavailable
- overloaded
- playground_busy
- playground_request_invalid
- playground_selection_invalid
- playground_session_limited
- playground_unavailable
- policy_version_stale
- provider_unavailable
- rate_limited
- render_probe_busy
- render_probe_failed
- render_probe_not_configured
- render_probe_required
- render_probe_timeout
- request_headers_too_large
- request_too_large
- resize_timeout
- signed_out
- spend_cap_reached
- template_build_not_found
- template_data_collection_limit
- template_data_depth_limit
- template_data_invalid
- template_data_limit
- template_depth_limit
- template_draft_not_found
- template_evaluation_error
- template_invalid_filter_input
- template_missing_data
- template_output_limit
- template_not_found
- template_schema_complexity
- template_schema_draft_unsupported
- template_schema_invalid
- template_schema_too_large
- template_size_canvas_mismatch
- template_size_data_overrides_too_large
- template_size_duplicate_id
- template_size_invalid_dimensions
- template_size_invalid_id
- template_size_invalid_name
- template_sizes_too_large
- template_sizes_too_many
- template_source_limit
- template_syntax_error
- template_timeout
- template_version_changed
- template_work_limit
- testimonial_busy
- testimonial_invalid
- testimonial_rate_limited
- testimonial_unavailable
- unauthorized
- unsupported_media_type
- webhook_limit_reached
description: A fixed, machine-readable error code.
message:
type: string
description: A fixed, human-readable message.
request_id:
type: string
format: uuid
description: The identifier this answer also carries in its x-request-id header.
details:
type: array
description: Present on a validation failure. Schema failures return at most 16 entries with bounded data paths and fixed reasons. Values from the request are never repeated.
items:
$ref: '#/components/schemas/FieldDetail'
retry:
$ref: '#/components/schemas/RetryInfo'
plan_limit:
$ref: '#/components/schemas/PlanLimitInfo'
required:
- code
- message
- request_id
additionalProperties: false
required:
- error
additionalProperties: false
PlanLimitInfo:
type: object
description: 'Present when the account''s plan causes the refusal: brand_kit_limit and batch_row_limit. It names the limit and the plan that sets it, so a caller can act without a second request. The message text never names the number.'
properties:
plan:
type: string
enum:
- scale
- growth
- starter
- pack
- free
description: The account's plan at the time of the refusal.
limit:
type: integer
minimum: 1
description: 'What that plan allows: brand kits for brand_kit_limit, rows in one run for batch_row_limit.'
required:
- plan
- limit
additionalProperties: false
RetryInfo:
type: object
description: How long the caller must wait before it retries.
properties:
retry_after_seconds:
type: integer
minimum: 1
maximum: 60
required:
- retry_after_seconds
additionalProperties: false
responses:
MethodNotAllowed:
description: The method is not allowed on this route.
headers:
x-request-id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
RequestHeadersTooLarge:
description: The request has more than 64 headers or more than 32 KiB of header names and values.
headers:
x-request-id:
$ref: '#/components/headers/XRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
headers:
XRequestId:
description: The UUID that identifies this request and matches error.request_id on an error response.
required: true
schema:
type: string
format: uuid
securitySchemes:
sessionCookie:
type: apiKey
in: cookie
name: __Host-thirds_session
description: A browser session. Browser writes also require the matching x-csrf-token header from GET /v1/me.
bearerAuth:
type: http
scheme: bearer
description: 'An API key''s secret, sent as "Authorization: Bearer thirds_sk_v1_...".'
x-unmatched-v1-responses:
description: A request below /v1 that matches no operation receives the shared safe envelope. OpenAPI has no standard path item for an unmatched route, so this extension records the fallback contract without claiming that a catch-all operation exists.
'404':
$ref: '#/components/responses/NotFound'
'431':
$ref: '#/components/responses/RequestHeadersTooLarge'