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/johnsessentials-com:johnsessentials-com-webhooks-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:
contact:
email: support@johnsessentials.com
name: John's Essentials Support
url: https://johnsessentials.com
description: 'Programmatic access to every tool on John''s Essentials. Compress PDFs,
convert images, OCR documents, run AI agents that orchestrate any of
the above — all behind a single bearer-token API key. ## Authentication
All endpoints under `/api/v1/public/*` require a bearer token whose
value is an API key starting with `je_live_sk_`. Generate keys in
the dashboard at `/integrations?tab=api-keys`. ## Rate limits
Tier-based limits are enforced per key on a 1-hour sliding window. Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining`,
and `X-RateLimit-Reset`. 429 responses include the standard
`Retry-After` header. ## Credits
Every tool call spends the tool''s published credit price from your
account''s monthly allowance — the same credits and the same prices
the website charges (Starter 1,500 / Business 40,000 a month). The
price of each tool is the `credits` field on `GET /tools`. Tool
responses carry `X-Credits-Cost` (what this call cost) and
`X-Credits-Remaining` (credits left this month, or `unlimited`). `GET /usage` is the meter: credits used and left this month, when
the allowance resets and what each API key spent; it spends
nothing. When
the allowance is spent the call fails with 402 `file_limit_reached`;
the body names the call''s cost (`credits`) and carries
`add_credits_url`. Credit packs (500 for $7, 5,000 for $25, 25,000
for $59) are bought on the billing page, top up the website and the
API alike, and stay spendable for twelve months. Free accounts also
have a daily cap of 100 credits (402 `daily_limit_reached`, with
`resets_at_utc`); a pack does not lift that cap, a paid plan does. Agent runs additionally draw on the key''s monthly USD budget for
model tokens (`cost_cap_exceeded`). ## Idempotency
Send `Idempotency-Key: ` on any unsafe request
(POST/PUT/PATCH) to make retries safe. Identical key + body within
24h replays the cached response and adds `Idempotency-Replayed: true`. Reusing a key with a different body returns 409 `idempotency_key_in_use`. ## Errors
All error responses share the same shape:
```json
{ "error": { "code": "auth_invalid_key",
"message": "Invalid API key",
"doc_url": "https://docs.johnsessentials.com/api/errors#auth_invalid_key",
"request_id": "uuid" } }
```
The full error catalogue is at `/api/errors`. ## Schema extensions (keys beginning `x-`)
A tool''s `parameters_schema` is the JSON Schema describing its inputs. Some properties in it also carry keys beginning `x-` — today `x-ui` and
`x-show-when`. These are presentation hints: instructions to our own web
interface about labelling, units, and which controls to hide. They are not
part of the API contract, so they may be added, changed, or removed at any
time, without a new API version and without a deprecation notice. An `x-` key never changes the value a parameter accepts or returns. `type`, `enum`, `minimum`, `maximum`, `default` and `required` are
authoritative. `x-ui.wire_scale` is the unit our form displays, not the
unit the API accepts. `x-ui.unit_from` names another parameter whose
value decides the unit and range our form shows for this one — a corner
radius read as pixels up to 5000, or as a percentage up to 50 — and it
only ever narrows the declared `minimum` and `maximum`, which remain
what the API accepts. `x-show-when` says when our interface hides a
control, never whether the API accepts it — a parameter our interface
never shows is still accepted. `x-ui.draw` says which part of a drawing
a parameter is (see `x-draw` below): our interface sets it by drawing on
the file instead of typing it, and writes the same value the parameter
accepts. Three `x-` keys sit on the schema itself, beside `properties` and
`required`, and describe the tool rather than one parameter. They are
advisory in the same way: our own interface and plan checks read them,
and the tool''s endpoint remains what decides.'
license:
name: Proprietary
url: https://johnsessentials.com/license
summary: Deterministic file-processing tools, AI agent orchestration, and a public REST surface for both.
title: John's Essentials Webhooks API
version: 1.0.0
servers:
- description: Production
url: https://api.johnsessentials.com/api/v1
- description: Local development
url: http://localhost:3000/api/v1
security:
- BearerAuth: []
tags:
- description: 'Server-to-server event notifications. We POST a JSON payload to
your registered URL when a long-running job completes, when a cost
threshold is reached, or when org/file/subscription state changes.
Signed with HMAC-SHA256 over `.` (Stripe
pattern). 3 retries with exponential backoff. See the catalog
below in `webhooks:`.'
name: Webhooks
paths: {}
webhooks:
agent.approval_pending:
post:
description: 'Fires when a run reaches an approval step and checkpoints — the run
resumes automatically once approved (in-app or via the emailed
approval link). `data.step` is the 1-indexed paused step.'
operationId: webhookAgentApprovalPending
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
data:
properties:
job_id:
format: uuid
type: string
message:
type: string
step:
type: integer
type: object
type:
const: agent.approval_pending
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: An agent run paused at an approval gate
tags:
- Webhooks
agent.finished:
post:
description: 'Fires when an agent run terminates — whether it completed
normally, hit max iterations, was cancelled, or errored. Check
`data.success` to discriminate.'
operationId: webhookAgentFinished
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
data:
$ref: '#/components/schemas/WebhookAgentFinishedData'
type:
const: agent.finished
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: An agent run completed (success or failure)
tags:
- Webhooks
agent.trigger_skipped:
post:
description: 'Fires when a cron/webhook/watch trigger was due but the account''s
monthly agent-run entitlement is exhausted — the run did NOT execute
and the trigger''s fire count is unchanged. Resumes firing when the
quota resets or the plan is upgraded.'
operationId: webhookAgentTriggerSkipped
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
data:
properties:
message:
type: string
reason:
type: string
trigger_id:
format: uuid
type: string
type: object
type:
const: agent.trigger_skipped
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A scheduled/triggered run was skipped (quota exhausted)
tags:
- Webhooks
cost.threshold_reached:
post:
description: 'Fires once per billing month per key, when `spent_this_month_usd`
crosses `alert_threshold_pct * monthly_cost_cap_usd / 100`
(default 80% × cap). Dedupe-safe — `threshold_alerted_at` is set
after fire and cleared on the next monthly reset. Use this to
proactively bump the cap, rotate the key, or page the on-call
engineer BEFORE the 402 wall.'
operationId: webhookCostThresholdReached
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
data:
$ref: '#/components/schemas/WebhookCostThresholdData'
type:
const: cost.threshold_reached
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: An API key's monthly spend crossed the alert threshold
tags:
- Webhooks
export.ready:
post:
operationId: webhookExportReady
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: export.ready
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A user-requested data export finished and is downloadable
tags:
- Webhooks
file.deleted:
post:
operationId: webhookFileDeleted
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: file.deleted
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A file was permanently deleted
tags:
- Webhooks
file.imported:
post:
operationId: webhookFileImported
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: file.imported
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A file was imported from a connected integration (Drive / Gmail / Slack)
tags:
- Webhooks
file.processed:
post:
description: 'Fires when any tool-run job finishes successfully. The `data`
block carries the output file ID + download URL. Retries: 3
attempts with exponential backoff (1m, 5m, 25m). Treat 2xx as
success; any other status triggers retry.'
operationId: webhookFileProcessed
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
data:
$ref: '#/components/schemas/WebhookFileProcessedData'
type:
const: file.processed
type: object
required: true
responses:
'200':
description: Acknowledged. We will not retry.
4XX:
description: Permanent failure on your side. We will not retry.
5XX:
description: Transient failure. We will retry per the backoff schedule.
summary: A tool run completed and the result file is ready
tags:
- Webhooks
file.restored:
post:
operationId: webhookFileRestored
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: file.restored
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A file was restored from trash
tags:
- Webhooks
file.share_revoked:
post:
operationId: webhookFileShareRevoked
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: file.share_revoked
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A file's share link was revoked
tags:
- Webhooks
file.shared:
post:
operationId: webhookFileShared
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: file.shared
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A public share link was created for a file
tags:
- Webhooks
file.trashed:
post:
operationId: webhookFileTrashed
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: file.trashed
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A file was moved to trash (soft delete)
tags:
- Webhooks
file.updated:
post:
operationId: webhookFileUpdated
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: file.updated
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A file's metadata changed (rename, move, tag, or star)
tags:
- Webhooks
file.uploaded:
post:
operationId: webhookFileUploaded
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: file.uploaded
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A file was uploaded to the user's storage
tags:
- Webhooks
files.bulk_op:
post:
operationId: webhookFilesBulkOp
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: files.bulk_op
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A bulk operation was applied to multiple files (trash, restore, move, tag, or…
tags:
- Webhooks
folder.created:
post:
operationId: webhookFolderCreated
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: folder.created
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A folder was created
tags:
- Webhooks
folder.deleted:
post:
operationId: webhookFolderDeleted
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: folder.deleted
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A folder was deleted
tags:
- Webhooks
folder.moved:
post:
operationId: webhookFolderMoved
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: folder.moved
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A folder was moved or renamed
tags:
- Webhooks
member.invited:
post:
operationId: webhookMemberInvited
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: member.invited
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A member was invited to an organization you administer
tags:
- Webhooks
member.joined:
post:
operationId: webhookMemberJoined
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: member.joined
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A user joined an organization you administer
tags:
- Webhooks
member.removed:
post:
operationId: webhookMemberRemoved
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: member.removed
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A member was removed from an organization you administer
tags:
- Webhooks
role.changed:
post:
operationId: webhookRoleChanged
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: role.changed
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A member's role changed in an organization you administer
tags:
- Webhooks
subscription.changed:
post:
operationId: webhookSubscriptionChanged
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: subscription.changed
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A subscription (plan / status / seats) changed
tags:
- Webhooks
trash.emptied:
post:
operationId: webhookTrashEmptied
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: trash.emptied
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: The user emptied their trash
tags:
- Webhooks
workflow.completed:
post:
operationId: webhookWorkflowCompleted
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
data:
$ref: '#/components/schemas/WebhookWorkflowCompletedData'
type:
const: workflow.completed
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A saved workflow finished running successfully
tags:
- Webhooks
workflow.failed:
post:
operationId: webhookWorkflowFailed
requestBody:
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WebhookEnvelope'
- properties:
type:
const: workflow.failed
type: object
required: true
responses:
'200':
description: Acknowledged.
summary: A saved workflow run failed
tags:
- Webhooks
components:
schemas:
WebhookFileProcessedData:
properties:
duration_ms:
type: integer
file_id:
type: string
result_url:
format: uri
type: string
size_bytes:
type: integer
tool:
example: pdf_compress
type: string
type: object
WebhookWorkflowCompletedData:
properties:
outputs:
type: object
run_id:
format: uuid
type: string
steps:
type: integer
success:
type: boolean
workflow_id:
format: uuid
type: string
type: object
WebhookEnvelope:
description: 'Common envelope every webhook delivery uses. `data` is the
per-event payload — branch on `type` to know its shape.
Signature header: `X-JE-Signature: t=<unix>,v1=<hex>` computed
as HMAC-SHA256 over `t + "." + raw_body`. Reject deliveries
whose `t` is more than 5 minutes from your server clock.
'
properties:
api_version:
example: '1.0'
type: string
created:
description: Unix seconds.
format: int64
type: integer
data:
description: Event-specific payload (see schemas below).
type: object
id:
example: evt_a1b2c3...
format: uuid
type: string
type:
enum:
- workflow.completed
- workflow.failed
- file.processed
- file.uploaded
- agent.finished
- agent.approval_pending
- agent.trigger_skipped
- export.ready
- member.joined
- member.invited
- member.removed
- role.changed
- subscription.changed
- cost.threshold_reached
type: string
required:
- id
- type
- created
- data
type: object
WebhookAgentFinishedData:
properties:
cost_usd:
format: double
type: number
duration_ms:
type: integer
job_id:
format: uuid
type: string
session_id:
type: string
steps:
type: integer
success:
type: boolean
type: object
WebhookCostThresholdData:
description: 'Fires once per billing month per key when spend crosses the alert
threshold (default 80%). Dedupe-safe: `threshold_alerted_at` is
set after fire and cleared on month rollover.
'
properties:
api_key_id:
format: uuid
type: string
api_key_name:
type: string
cap_usd:
example: 12
format: double
type: number
resets_at_utc:
format: date-time
type: string
spent_usd:
example: 9.8
format: double
type: number
threshold_pct:
example: 80
type: integer
type: object
securitySchemes:
BearerAuth:
bearerFormat: API Key
description: 'Bearer token = your API key, prefixed `je_live_sk_`.
Example: `Authorization: Bearer je_live_sk_abc123...`
'
scheme: bearer
type: http