Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
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.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/easy2257-com:easy2257-com-hosted-attestation-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
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: Easy2257 Partner Hosted Attestation API
version: '2026-07-27'
description: 'The Easy2257 Partner API lets your platform outsource 18 U.S.C. § 2257 compliance in a single integration: performer ID verification, per-depiction content logging, and 7-year record retention, with Easy2257 named Custodian of Records. No endpoint in this API returns a performer''s legal name, date of birth, government ID image, or Easy2257 user id. A platform integrating it never touches a government ID, so it cannot leak one. There is no sandbox: only `ez_live_` keys are accepted, and every call writes a production record.'
contact:
name: Easy2257 Developer Support
email: api@easy2257.com
url: https://docs.easy2257.com
servers:
- url: https://easy2257.com
description: Production, and the only environment. There is no sandbox host.
tags:
- name: Hosted Attestation
description: Hand the attestation form to Easy2257 and build no compliance UI.
paths:
/api/v1/upload-sessions:
post:
summary: Start a hosted attestation session
description: Hands the whole attestation step to Easy2257. You post the content facts, redirect the uploader to `hostedUrl`, and Easy2257 renders the form, captures the producer attestation with IP, user agent and timestamp, and tells you when it is done. Your platform builds no compliance UI. `contentOrigin` and `detectedFaceCount` choose the path. For captured content (the default), 1 face records a solo attestation and fires `upload_session.solo_completed`; 2 or more opens a collab scene from the collaborators the uploader names, emails them, and fires `collab_scene.created` carrying `uploadSessionId` so you can correlate it back to the content row. AI-generated content (`synthetic`, or `mixed` with no other real person named) records a single attestation and fires `upload_session.synthetic_completed`; `contentSha256` is required for both. The uploader must already have an active solo account under your partner account. Sessions last 24 hours, and each call creates a new one.
tags:
- Hosted Attestation
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUploadSessionBody'
responses:
'201':
description: Session created. Redirect the uploader to `hostedUrl`.
content:
application/json:
schema:
$ref: '#/components/schemas/UploadSessionResponse'
'400':
description: Validation failure. `code` is `missing_field` or `invalid_field`, and `field` names the offender.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: 'No `Authorization: Bearer` header, or a key that is unknown, revoked, or expired. The body carries only `error`, never a `code`.'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: 'Rejected before the handler: a test-mode key (`TEST_MODE_UNAVAILABLE`) or a partner account that is not ACTIVE. Never used for cross-partner access, which returns 404.'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: The uploader has no active Easy2257 solo account under your partner account. `code` is `uploader_not_solo_active`. Run them through solo onboarding first.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: 'Rate limit exceeded: 300 requests per 60 seconds per API key, shared across all `/api/v1` endpoints (requests without a `Bearer` key fall back to 60 per 60 seconds per client IP, and a per-address flood ceiling of 1200 per 60 seconds also applies). Honor `Retry-After`.'
content:
application/json:
schema:
$ref: '#/components/schemas/RateLimitError'
'500':
description: Server error. Retry with exponential backoff.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
operationId: postApiV1UploadSessions
x-operation-id-source: derived
components:
schemas:
CreateUploadSessionBody:
type: object
properties:
contentId:
type: string
maxLength: 255
description: Your content id. Echoed back to you on the completion webhook so you can find the row again.
example: video_abc123
contentType:
type: string
enum:
- image
- video
- gallery
contentTitle:
type: string
maxLength: 500
example: April 2026 Scene
detectedFaceCount:
type: integer
minimum: 0
maximum: 50
description: 'How many faces your pipeline detected in the upload. For `captured` content this alone chooses the path: 1 collects a solo attestation, 2 or more opens a collab scene and emails every collaborator the uploader names. For `synthetic` content it is stored for the record and routes nothing, and 0 is allowed. Captured and mixed content need at least 1, since the uploader is in it.'
example: 2
contentOrigin:
type: string
enum:
- captured
- synthetic
- mixed
description: 'What the content is. `captured` (the default when omitted): real people were filmed or photographed. `synthetic`: generated entirely by AI, no real person depicted; the uploader attests to that, no collaborators are invited, and completion fires `upload_session.synthetic_completed`. `mixed`: the uploader with AI-generated figures; the uploader names any other real people, who go through the normal collab flow, and with none named completion fires `upload_session.synthetic_completed`. The uploader cannot change it on the form: if it is wrong, open a new session.'
example: captured
personaName:
type: string
maxLength: 100
description: The persona the content is posted under, such as an AI persona's display name. Shown on the form and kept with the attestation.
example: Lisa Mays
contentSha256:
type: string
pattern: ^[a-fA-F0-9]{64}$
description: SHA-256 (hex) of the file the uploader is attesting to. Required when `contentOrigin` is `synthetic` or `mixed`; optional for `captured`. Stored lowercased.
example: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
generationTool:
type: string
maxLength: 200
description: 'What generated the content, at whatever detail you have. `synthetic` and `mixed` only; sending it on `captured` is a `400`. Easy2257 does not take prompts, seeds or source files: the creator keeps those.'
example: Example Gen 3
uploaderExternalUserId:
type: string
maxLength: 450
description: Your user id for the uploader. Must already map to an active Easy2257 solo account under your partner account.
example: user_12345
uploaderEmail:
type: string
format: email
example: creator@example.com
uploaderFirstName:
type: string
uploaderLastName:
type: string
callbackUrl:
type: string
format: uri
description: Required, stored for your reference. Events go to your portal-registered endpoints.
example: https://your-platform.com/webhooks/ez2257
redirectUrl:
type: string
format: uri
description: Required. Where the hosted form returns the uploader when they are done.
example: https://your-platform.com/uploads/video_abc123
required:
- contentId
- contentType
- contentTitle
- detectedFaceCount
- uploaderExternalUserId
- uploaderEmail
- callbackUrl
- redirectUrl
RateLimitError:
type: object
properties:
error:
type: string
example: Too many requests. Please slow down.
retryAfter:
type: integer
description: Seconds until the window frees up. Mirrors the `Retry-After` header.
example: 14
limit:
type: integer
description: Requests allowed per window.
example: 60
remaining:
type: integer
example: 0
reset:
type: integer
description: Epoch milliseconds at which the sliding window releases the oldest request.
example: 1714000060000
required:
- error
- limit
- remaining
- reset
UploadSessionResponse:
type: object
properties:
sessionId:
type: string
example: cmd6t2p5x0001qz8h7f3d9k4w
token:
type: string
description: '64-character session token. Treat it as a secret: anyone holding it can complete the attestation.'
example: 3f9c1d...
hostedUrl:
type: string
format: uri
description: Send the uploader here in top-level navigation. Easy2257 hosts the attestation form, so you build no compliance UI at all.
example: https://easy2257.com/upload-attestation/3f9c1d...
status:
type: string
enum:
- created
contentOrigin:
type: string
enum:
- captured
- synthetic
- mixed
description: The origin the session was created with; `captured` when you omitted it.
example: captured
expiresAt:
type: string
format: date-time
description: 24 hours from creation. After that the uploader needs a new session.
example: '2026-04-25T18:00:00Z'
required:
- sessionId
- token
- hostedUrl
- status
- contentOrigin
- expiresAt
Error:
type: object
properties:
error:
type: string
description: 'Human-readable message. Switch on HTTP status and on `code`, never on this string: it is not part of the API contract.'
example: email, externalUserId, and callbackUrl are required
code:
type: string
description: Machine-readable error code. Present on the test-key rejection (`TEST_MODE_UNAVAILABLE`), consent conflicts, and most collab-scene and upload-session validation errors. Never present on `401` authentication rejections, and absent on the inactive-partner `403` and on some older solo-account validation errors, which is why status is the primary signal.
example: missing_parameter
field:
type: string
description: The offending request field. Present on collab-scene and upload-session validation errors.
example: contentType
required:
- error
securitySchemes:
BearerAuth:
type: http
scheme: bearer
description: 'Partner API key from partner.easy2257.com/api-keys. Only `ez_live_` keys are accepted. A key beginning with `ez_test_` is rejected with `403` and code `TEST_MODE_UNAVAILABLE` before any handler runs: there is no sandbox, and every handler writes production records, provisions real users, and sends real email. New partner accounts start with a test key, so create a live key before your first call.'