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/fabricatedemail-com:fabricatedemail-com-subscriptions-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
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: fabricatedemail HTTP Subscriptions API
version: 1.0.0
description: '## General contract
- Every error response has body `{"error": ""}`. The message is
human-facing and may change; branch on the status code, never on the
string.
- Checks run in the order authentication (`401`) → account state (`403`) →
rate limit (`429`) → request validation (`400`) → existence and
ownership (`404`) → cross-key conflict (`409`) → address cap (`429`).
A request that is wrong in two ways gets the earlier status.
- Unknown routes and methods are `404 {"error": "Not found"}`, including
after successful authentication.
- Every timestamp is exactly the format of JavaScript
`Date.prototype.toISOString()`: millisecond precision, trailing `Z`.
- Request bodies must be JSON objects. A malformed body, a JSON array or a
bare JSON string is `400`. Unknown fields are ignored.
- Register first, then trigger the mail. A `201` from `POST /subscriptions`
means the mailbox is committed and visible to the mail handler, and a
stored message is visible to your very next poll.'
servers:
- url: https://api.fabricatedemail.com
description: Production.
security:
- apiKey: []
tags:
- name: Subscriptions
paths:
/subscriptions:
post:
operationId: createSubscription
tags:
- Subscriptions
summary: Register an address
description: 'A `201` means the mailbox is live now: mail sent after this response
returns is guaranteed to be visible to the next poll.
The failure checks run in this order, and the first failure wins:
1. `401` — no key, an unknown or revoked key, or a key whose account is
missing.
2. `403` — the account is suspended.
3. `429` with `Retry-After` — the rate limit.
4. `400` — a malformed address, a reserved local part, or an invalid
`ttlSeconds`.
5. `409` — another key holds a live subscription for the address.
6. `429` without `Retry-After` — the account''s live address cap.
Registering an address you already hold succeeds even at the cap: the
address being registered is excluded from the count.'
x-mcp-tool:
name: create_address
summary: Register a disposable address and return its subscription.
arguments:
- name: localPart
required: false
description: 'The local part of the address. The tool sends
`<localPart>@fabricatedemail.com` as `address`. Omitted, the tool
generates a random local part of at least 64 bits of entropy.
'
schema:
type: string
pattern: ^[a-z0-9._+-]{1,64}$
- name: ttlSeconds
required: false
description: Sent verbatim as `ttlSeconds`.
schema:
type:
- integer
- 'null'
minimum: 60
maximum: 86400
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SubscriptionCreate'
examples:
withTtl:
summary: A 15-minute mailbox.
value:
address: myapp-4f2a9c81d3e6b7a0@fabricatedemail.com
ttlSeconds: 900
defaultTtl:
summary: The default TTL of one hour.
value:
address: myapp-4f2a9c81d3e6b7a0@fabricatedemail.com
permanent:
summary: A permanent mailbox — only `DELETE` ends it.
value:
address: qa-shared-inbox@fabricatedemail.com
ttlSeconds: null
responses:
'201':
description: The mailbox is live.
content:
application/json:
schema:
$ref: '#/components/schemas/Subscription'
examples:
created:
$ref: '#/components/examples/subscription'
permanent:
$ref: '#/components/examples/permanentSubscription'
'400':
description: 'The address is outside the grammar or off the service domain,
`address` is missing or not a string, the local part is reserved,
`ttlSeconds` is invalid, or the body is not a JSON object.
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
wrongDomain:
value:
error: address must be on the service domain fabricatedemail.com
badLocalPart:
value:
error: address local part must be 1-64 characters of [a-z0-9._+-]
reservedLocalPart:
$ref: '#/components/examples/errorReservedLocalPart'
badTtl:
value:
error: ttlSeconds must be between 60 and 86400
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/AccountSuspended'
'409':
description: 'Another key holds a live subscription for this address, including a
permanent one, which stays live until its owner deletes it. An
expired foreign subscription never causes this: the registration
clears expired rows for the address as part of the write.
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
foreignHolder:
value:
error: address is registered by another key
'429':
description: 'Either the rate limit, which carries `Retry-After`, or the
account''s live address cap, which does not. The cap is the tier''s
`liveAddresses`, or the technical bound of 10 000 for an account
with no limit; it is approximate under concurrent registrations,
because it is checked before the write rather than atomically with
it.
'
headers:
Retry-After:
$ref: '#/components/headers/RetryAfter'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
rateLimited:
$ref: '#/components/examples/errorRateLimited'
addressCapReached:
$ref: '#/components/examples/errorAddressCapReached'
'500':
$ref: '#/components/responses/ServerError'
get:
operationId: listSubscriptions
tags:
- Subscriptions
summary: List the calling key's live subscriptions, oldest first
description: 'Expired subscriptions never appear, whether or not the hourly cleanup
has collected them yet. A key sees only the subscriptions it created,
not the rest of its account''s.
Unpaginated: the account''s live address cap bounds it, and the
technical bound of 10 000 bounds it absolutely.'
x-mcp-tool:
name: list_addresses
summary: List the live addresses this key holds.
arguments: []
responses:
'200':
description: The live subscriptions.
content:
application/json:
schema:
type: object
required:
- subscriptions
properties:
subscriptions:
type: array
items:
$ref: '#/components/schemas/Subscription'
examples:
one:
value:
subscriptions:
- id: 3f7c1c0e-1e5b-4b3f-9a2a-2f6f6d4b1c77
address: myapp-4f2a9c81d3e6b7a0@fabricatedemail.com
createdAt: '2026-08-10T12:00:00.000Z'
expiresAt: '2026-08-10T12:15:00.000Z'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/AccountSuspended'
'429':
$ref: '#/components/responses/RateLimited'
'500':
$ref: '#/components/responses/ServerError'
/subscriptions/{sid}:
parameters:
- $ref: '#/components/parameters/sid'
delete:
operationId: deleteSubscription
tags:
- Subscriptions
summary: End a subscription early and delete its stored messages
description: 'Both happen in one transaction. Deleting is optional hygiene — a TTL''d
subscription disappears on its own — but it frees the address for
immediate reuse by another key. It is the only way a permanent
subscription ever ends.'
x-mcp-tool:
name: delete_address
summary: Delete an address and its stored mail.
arguments:
- name: subscriptionId
required: true
description: Sent as the `sid` path parameter.
schema:
type: string
format: uuid
responses:
'204':
description: Deleted. No body.
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/AccountSuspended'
'404':
$ref: '#/components/responses/SubscriptionNotFound'
'429':
$ref: '#/components/responses/RateLimited'
'500':
$ref: '#/components/responses/ServerError'
components:
examples:
errorReservedLocalPart:
value:
error: address local part is reserved
errorInternal:
value:
error: internal error
errorRateLimited:
summary: 'The rate limit — sent with `Retry-After: 60`.'
value:
error: rate limited
errorAccountSuspended:
value:
error: account suspended
errorNotFound:
value:
error: Not found
errorAddressCapReached:
summary: The account's live address cap — sent without `Retry-After`.
value:
error: address cap reached
subscription:
summary: A 15-minute mailbox.
value:
id: 3f7c1c0e-1e5b-4b3f-9a2a-2f6f6d4b1c77
address: myapp-4f2a9c81d3e6b7a0@fabricatedemail.com
createdAt: '2026-08-10T12:00:00.000Z'
expiresAt: '2026-08-10T12:15:00.000Z'
errorUnauthorized:
value:
error: unauthorized
permanentSubscription:
summary: A permanent mailbox — `expiresAt` is null.
value:
id: 5a1b2c3d-4e5f-4061-8273-8495a6b7c8d9
address: qa-shared-inbox@fabricatedemail.com
createdAt: '2026-08-10T12:00:00.000Z'
expiresAt: null
schemas:
Subscription:
type: object
required:
- id
- address
- createdAt
- expiresAt
properties:
id:
type: string
format: uuid
description: The handle for every later call. A replaced subscription's id is dead for good.
address:
type: string
description: The registered address, lowercased.
createdAt:
type: string
format: date-time
expiresAt:
type:
- string
- 'null'
format: date-time
description: When the subscription expires, or `null` when it is permanent.
Error:
type: object
required:
- error
properties:
error:
type: string
description: Human-facing, and free to change. Branch on the status code.
SubscriptionCreate:
type: object
required:
- address
properties:
address:
type: string
pattern: ^[a-z0-9._+-]{1,64}@fabricatedemail\.com$
description: '`local-part@fabricatedemail.com`, where the local part is 1–64
characters of `[a-z0-9._+-]` and the domain is the service mail
domain exactly — a subdomain is rejected. Compared and stored
lowercased, so `Foo@…` is registered and returned as `foo@…`.
The local part must not be one of the reserved parts listed in
`x-reserved-local-parts` at the root of this document; those are
forwarded to a real inbox and cannot be claimed.
Use at least 64 bits of entropy for anything that can run twice
concurrently.
'
ttlSeconds:
type:
- integer
- 'null'
minimum: 60
maximum: 86400
default: 3600
description: 'Seconds until the subscription expires: 60 to 86 400. Omitted, the
default is one hour. Explicit `null` makes the subscription
permanent — `expiresAt` is `null`, it is never garbage-collected,
and `DELETE` is the only thing that ends it. Anything else — a
non-integer, a numeric string, a boolean, an out-of-range integer —
is `400`.
A permanent mailbox still counts towards the account''s live address
cap, and its messages still expire on the normal 24-hour retention.
'
responses:
SubscriptionNotFound:
description: 'The subscription is unknown, expired, deleted, replaced or owned by
another key. These are indistinguishable, and the handle is dead for
good: get a new one by registering again.
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
notFound:
$ref: '#/components/examples/errorNotFound'
AccountSuspended:
description: 'The key''s account is suspended. Every key of the account sees this, on
every key route, from the next request on; a long poll already in
flight is not interrupted, and the request after it gets this within
30 seconds. Mail addressed to the account''s
addresses is dropped meanwhile. Reinstatement makes the account work
again; mail that arrived during the suspension is gone, and addresses
and mail that expired meanwhile were deleted as usual.
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
suspended:
$ref: '#/components/examples/errorAccountSuspended'
Unauthorized:
description: 'The key or token is missing, malformed, unknown or revoked, or the key
has no account. All of these are indistinguishable from outside.
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
unauthorized:
$ref: '#/components/examples/errorUnauthorized'
RateLimited:
description: 'The key passed 600 requests in a minute. `Retry-After` says when to
come back. A well-behaved 30-second poll loop costs about two requests
a minute and never sees this.
'
headers:
Retry-After:
$ref: '#/components/headers/RetryAfter'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
rateLimited:
$ref: '#/components/examples/errorRateLimited'
ServerError:
description: A server-side failure, logged by the service with the real cause. Retry.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
internal:
$ref: '#/components/examples/errorInternal'
headers:
RetryAfter:
description: 'Seconds to wait before retrying. Present on the rate-limit `429` and
absent on the address-cap `429`, which is what tells the two apart
without reading the message.
'
required: false
schema:
type: integer
minimum: 0
parameters:
sid:
name: sid
in: path
required: true
description: The subscription id from `POST /subscriptions`.
schema:
type: string
format: uuid
securitySchemes:
apiKey:
type: http
scheme: bearer
description: 'The 64-hex-character API key, created in the customer dashboard and
shown once. The scheme is matched case-insensitively. A missing header,
a malformed credential, an unknown key and a revoked key are all `401`
and indistinguishable from outside.
'
x-reserved-local-parts:
- abuse
- postmaster
- security
- support
- admin
- noreply
- no-reply
- hostmaster
- webmaster
- info
- billing
- legal
- dmarc