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/crevio-co:crevio-co-forms-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: Crevio API V1 Forms API
version: 1.0.0
description: 'API for the Crevio creator platform — a multi-tenant SaaS for digital product sales.
Uses snake_case keys following Stripe conventions. All resource IDs are string IDs (e.g., "prod_abc123").
Authentication is a bearer token: `Authorization: Bearer $CREVIO_API_KEY`.
List endpoints are cursor-paginated with `limit` and `starting_after`.
Writes accept an `Idempotency-Key` header and are safe to retry.
Every response carries IETF RateLimit headers (`RateLimit`, `RateLimit-Policy`) so a client can
self-throttle, and `Retry-After` on a 429. The quota is 600 requests per minute per credential.
The API is versioned in the URL path (`/v1`). Nothing is removed without in-band warning: a
deprecated operation is marked `"deprecated": true` here and serves `Deprecation` (RFC 9745),
`Sunset` (RFC 8594) and `Link; rel="deprecation"` headers for at least six months before it
stops answering. See https://crevio.co/docs/developer/guides/versioning.'
contact:
email: support@crevio.co
name: Crevio Support
url: https://crevio.co/docs
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
termsOfService: https://crevio.co/legal/terms-of-service
servers:
- url: https://api.crevio.co/v1
description: Production
security:
- ApiKey: []
tags:
- name: Forms
description: Hosted forms that capture leads and submissions
paths:
/forms:
get:
summary: List forms
description: Returns all forms for the current account.
operationId: listForms
x-crevio-sdk-method: list
tags:
- Forms
security:
- ApiKey: []
parameters:
- name: starting_after
in: query
description: Cursor for pagination — the ID of the last item in the previous page
schema:
type: string
- name: limit
in: query
description: Items per page
schema:
type: integer
minimum: 1
maximum: 100
default: 20
responses:
'200':
description: List of forms
content:
application/json:
schema:
$ref: '#/components/schemas/ListResponse_Form'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
x-crevio-approval: allow
x-codeSamples:
- lang: typescript
label: Typescript (SDK)
source: "import { Crevio } from \"@crevio/sdk\";\n\nconst crevio = new Crevio({\n apiKey: process.env[\"CREVIO_API_KEY\"] ?? \"\",\n});\n\nasync function run() {\n const result = await crevio.forms.list({});\n\n console.log(result);\n}\n\nrun();"
post:
summary: Create form
description: Creates a new Form, optionally with fields nested via form_fields_attributes. Set `delivery_type` (with `delivery_file_id`, `delivery_url` or `experience_id`) to email a file, link or experience to everyone who submits, and `tag_ids` to tag them. With `confirmation_required` (double opt-in), tags and delivery wait until the person confirms. Submissions come in through `POST /forms/{form_id}/submissions`.
operationId: createForm
x-crevio-sdk-method: create
tags:
- Forms
security:
- ApiKey: []
parameters:
- name: Idempotency-Key
in: header
required: false
description: 'Makes this write safe to retry: a repeat with the same key replays the first response instead of creating a second resource. Scoped to the account, remembered for 24 hours; reusing a key with a different payload is an error.'
schema:
type: string
maxLength: 255
example: 1f7a4c2e-3b19-4a6d-9f0c-2ac81b5d7e33
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/FormRequest'
responses:
'201':
description: Form created
content:
application/json:
schema:
$ref: '#/components/schemas/Form'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
x-crevio-approval: allow
x-codeSamples:
- lang: typescript
label: Typescript (SDK)
source: "import { Crevio } from \"@crevio/sdk\";\n\nconst crevio = new Crevio({\n apiKey: process.env[\"CREVIO_API_KEY\"] ?? \"\",\n});\n\nasync function run() {\n const result = await crevio.forms.create({});\n\n console.log(result);\n}\n\nrun();"
/forms/{form_id}/submissions:
parameters:
- name: form_id
description: The form's ID.
in: path
required: true
schema:
type: string
post:
summary: Create form submission
description: Submits an answer set to a specific Form. Customer is upserted by email; lead-magnet purpose forms also trigger delivery.
operationId: createFormSubmissionForForm
x-crevio-sdk-method: submit
tags:
- Forms
security:
- ApiKey: []
parameters:
- name: Idempotency-Key
in: header
required: false
description: 'Makes this write safe to retry: a repeat with the same key replays the first response instead of creating a second resource. Scoped to the account, remembered for 24 hours; reusing a key with a different payload is an error.'
schema:
type: string
maxLength: 255
example: 1f7a4c2e-3b19-4a6d-9f0c-2ac81b5d7e33
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
email:
type: string
name:
type:
- string
- 'null'
answers:
type: object
additionalProperties: true
description: Map of form_field id → answer value. A `consent` field takes `true` when the person agreed.
ip_address:
type:
- string
- 'null'
description: The submitter's IP address, kept with the submission as a record of consent.
required:
- email
- answers
responses:
'201':
description: Submission created
content:
application/json:
schema:
$ref: '#/components/schemas/FormSubmission'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
x-crevio-approval: allow
x-codeSamples:
- lang: typescript
label: Typescript (SDK)
source: "import { Crevio } from \"@crevio/sdk\";\n\nconst crevio = new Crevio({\n apiKey: process.env[\"CREVIO_API_KEY\"] ?? \"\",\n});\n\nasync function run() {\n const result = await crevio.forms.submit({\n formId: \"<id>\",\n requestBody: {\n email: \"jane@example.com\",\n answers: {\n key: \"<value>\",\n },\n },\n });\n\n console.log(result);\n}\n\nrun();"
/forms/{id}:
parameters:
- name: id
description: The form's ID.
in: path
required: true
schema:
type: string
get:
summary: Get form
description: Retrieves a single form with its fields, in the order they are presented, along with the settings that govern how submissions are collected.
operationId: getForm
x-crevio-sdk-method: get
tags:
- Forms
security:
- ApiKey: []
responses:
'200':
description: Form
content:
application/json:
schema:
$ref: '#/components/schemas/Form'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
x-crevio-approval: allow
x-codeSamples:
- lang: typescript
label: Typescript (SDK)
source: "import { Crevio } from \"@crevio/sdk\";\n\nconst crevio = new Crevio({\n apiKey: process.env[\"CREVIO_API_KEY\"] ?? \"\",\n});\n\nasync function run() {\n const result = await crevio.forms.get({\n id: \"<id>\",\n });\n\n console.log(result);\n}\n\nrun();"
patch:
summary: Update form
description: Update a Form's name, settings, confirmation behavior, or auto-tag list.
operationId: updateForm
x-crevio-sdk-method: update
tags:
- Forms
security:
- ApiKey: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/FormRequest'
responses:
'200':
description: Updated form
content:
application/json:
schema:
$ref: '#/components/schemas/Form'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
x-crevio-approval: allow
x-codeSamples:
- lang: typescript
label: Typescript (SDK)
source: "import { Crevio } from \"@crevio/sdk\";\n\nconst crevio = new Crevio({\n apiKey: process.env[\"CREVIO_API_KEY\"] ?? \"\",\n});\n\nasync function run() {\n const result = await crevio.forms.update({\n id: \"<id>\",\n formRequest: {},\n });\n\n console.log(result);\n}\n\nrun();"
delete:
summary: Delete form
description: Permanently deletes a Form. Refuses with a 422 if the form has submissions — archive it instead via PATCH /forms/{id}/archive to preserve them.
operationId: deleteForm
x-crevio-sdk-method: delete
tags:
- Forms
security:
- ApiKey: []
responses:
'200':
description: Deleted form
content:
application/json:
schema:
$ref: '#/components/schemas/Form'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
x-crevio-approval: ask
x-codeSamples:
- lang: typescript
label: Typescript (SDK)
source: "import { Crevio } from \"@crevio/sdk\";\n\nconst crevio = new Crevio({\n apiKey: process.env[\"CREVIO_API_KEY\"] ?? \"\",\n});\n\nasync function run() {\n const result = await crevio.forms.delete({\n id: \"<id>\",\n });\n\n console.log(result);\n}\n\nrun();"
/forms/{id}/archive:
parameters:
- name: id
description: The form's ID.
in: path
required: true
schema:
type: string
patch:
summary: Archive form
description: Soft-deletes a Form by setting archived_at. The form stops appearing in the active list but its fields and submissions are preserved. Idempotent.
operationId: archiveForm
x-crevio-sdk-method: archive
tags:
- Forms
security:
- ApiKey: []
responses:
'200':
description: Archived form
content:
application/json:
schema:
$ref: '#/components/schemas/Form'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
x-crevio-approval: allow
x-codeSamples:
- lang: typescript
label: Typescript (SDK)
source: "import { Crevio } from \"@crevio/sdk\";\n\nconst crevio = new Crevio({\n apiKey: process.env[\"CREVIO_API_KEY\"] ?? \"\",\n});\n\nasync function run() {\n const result = await crevio.forms.archive({\n id: \"<id>\",\n });\n\n console.log(result);\n}\n\nrun();"
/forms/{id}/restore:
parameters:
- name: id
description: The form's ID.
in: path
required: true
schema:
type: string
patch:
summary: Restore form
description: Unarchives a previously archived Form so it appears in the active list again. Idempotent.
operationId: restoreForm
x-crevio-sdk-method: restore
tags:
- Forms
security:
- ApiKey: []
responses:
'200':
description: Restored form
content:
application/json:
schema:
$ref: '#/components/schemas/Form'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
x-crevio-approval: allow
x-codeSamples:
- lang: typescript
label: Typescript (SDK)
source: "import { Crevio } from \"@crevio/sdk\";\n\nconst crevio = new Crevio({\n apiKey: process.env[\"CREVIO_API_KEY\"] ?? \"\",\n});\n\nasync function run() {\n const result = await crevio.forms.restore({\n id: \"<id>\",\n });\n\n console.log(result);\n}\n\nrun();"
components:
responses:
Forbidden:
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
type: invalid_request_error
code: forbidden
message: You do not have permission to perform this action
headers:
RateLimit:
$ref: '#/components/headers/RateLimit'
RateLimit-Policy:
$ref: '#/components/headers/RateLimitPolicy'
Request-Id:
$ref: '#/components/headers/RequestId'
Deprecation:
$ref: '#/components/headers/Deprecation'
Sunset:
$ref: '#/components/headers/Sunset'
Link:
$ref: '#/components/headers/DeprecationLink'
BadRequest:
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
type: invalid_request_error
code: bad_request
message: The request was malformed or contained invalid parameters
headers:
RateLimit:
$ref: '#/components/headers/RateLimit'
RateLimit-Policy:
$ref: '#/components/headers/RateLimitPolicy'
Request-Id:
$ref: '#/components/headers/RequestId'
Deprecation:
$ref: '#/components/headers/Deprecation'
Sunset:
$ref: '#/components/headers/Sunset'
Link:
$ref: '#/components/headers/DeprecationLink'
Unauthorized:
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
type: invalid_request_error
code: authentication_required
message: You did not provide an API key.
headers:
RateLimit:
$ref: '#/components/headers/RateLimit'
RateLimit-Policy:
$ref: '#/components/headers/RateLimitPolicy'
Request-Id:
$ref: '#/components/headers/RequestId'
Deprecation:
$ref: '#/components/headers/Deprecation'
Sunset:
$ref: '#/components/headers/Sunset'
Link:
$ref: '#/components/headers/DeprecationLink'
NotFound:
description: Resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
type: invalid_request_error
code: resource_missing
message: The requested resource was not found
headers:
RateLimit:
$ref: '#/components/headers/RateLimit'
RateLimit-Policy:
$ref: '#/components/headers/RateLimitPolicy'
Request-Id:
$ref: '#/components/headers/RequestId'
Deprecation:
$ref: '#/components/headers/Deprecation'
Sunset:
$ref: '#/components/headers/Sunset'
Link:
$ref: '#/components/headers/DeprecationLink'
TooManyRequests:
description: 'Rate limit exceeded — 600 requests per minute per owner on the free tier: every API key and OAuth token one person holds on an account shares one budget, and the account''s team keys share another. Retry after the number of seconds in `Retry-After`.'
headers:
Retry-After:
$ref: '#/components/headers/RetryAfter'
RateLimit:
$ref: '#/components/headers/RateLimit'
RateLimit-Policy:
$ref: '#/components/headers/RateLimitPolicy'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
type: invalid_request_error
code: rate_limit_exceeded
message: Too many requests. Please retry later.
InternalServerError:
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
type: api_error
code: internal_error
message: An unexpected error occurred
headers:
RateLimit:
$ref: '#/components/headers/RateLimit'
RateLimit-Policy:
$ref: '#/components/headers/RateLimitPolicy'
Request-Id:
$ref: '#/components/headers/RequestId'
Deprecation:
$ref: '#/components/headers/Deprecation'
Sunset:
$ref: '#/components/headers/Sunset'
Link:
$ref: '#/components/headers/DeprecationLink'
UnprocessableEntity:
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
type: validation_error
code: validation_failed
message: Email is required
errors:
email:
- can't be blank
headers:
RateLimit:
$ref: '#/components/headers/RateLimit'
RateLimit-Policy:
$ref: '#/components/headers/RateLimitPolicy'
Request-Id:
$ref: '#/components/headers/RequestId'
Deprecation:
$ref: '#/components/headers/Deprecation'
Sunset:
$ref: '#/components/headers/Sunset'
Link:
$ref: '#/components/headers/DeprecationLink'
schemas:
FormField:
type: object
properties:
id:
type: string
object:
type: string
name:
type: string
field_type:
type: string
enum:
- email
- text
- phone
- textarea
- radio
- select
- checkbox
- consent
required:
type:
- boolean
- 'null'
position:
type:
- integer
- 'null'
options:
type: array
items:
type: string
required:
- id
- object
- name
- field_type
- required
- position
- options
Form:
type: object
properties:
id:
type: string
object:
type: string
name:
type: string
redirect_url:
type:
- string
- 'null'
settings:
type: object
archived_at:
type:
- string
- 'null'
format: date-time
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
confirmation_required:
type: boolean
tag_ids:
type: array
items:
type: string
delivery_url:
type:
- string
- 'null'
delivery_subject:
type:
- string
- 'null'
delivery_message:
type:
- string
- 'null'
delivery_type:
type: string
enum:
- none
- file
- link
- experience
delivery_file:
type:
- object
- 'null'
experience_id:
type:
- string
- 'null'
submissions_count:
type: number
form_fields:
type: array
items:
$ref: '#/components/schemas/FormField'
required:
- id
- object
- name
- redirect_url
- settings
- archived_at
- created_at
- updated_at
- confirmation_required
- tag_ids
- delivery_url
- delivery_subject
- delivery_message
- delivery_type
- delivery_file
- experience_id
- submissions_count
- form_fields
FormRequest:
type: object
properties:
name:
type: string
redirect_url:
type:
- string
- 'null'
description: Full https:// URL people land on after they click the confirmation link, with `confirmation_required` on.
delivery_type:
type: string
enum:
- none
- file
- link
- experience
description: What everyone who submits gets by email, on every submission. `none` turns delivery off; `file` needs `delivery_file_id`, `link` needs `delivery_url`, `experience` needs `experience_id`.
delivery_url:
type:
- string
- 'null'
description: 'Full https:// URL to send: a page, video or download elsewhere.'
experience_id:
type:
- string
- 'null'
description: Experience ID to grant access to; the email carries a sign-in link.
delivery_subject:
type:
- string
- 'null'
description: Subject of the delivery email. Defaults to "Your freebie from <business> is here!".
delivery_message:
type:
- string
- 'null'
description: Plain-text body of the delivery email; the download button is added below it.
archived_at:
type:
- string
- 'null'
format: date-time
tag_ids:
type: array
items:
type: string
description: Tag IDs added to everyone who submits (never replacing their other tags). With `confirmation_required`, once they confirm.
form_fields_attributes:
type: array
description: 'Nested-attributes payload for creating, updating, or destroying fields in one round-trip. Pass `id` to update an existing field; pass `_destroy: true` to remove one.'
items:
type: object
properties:
id:
type:
- integer
- 'null'
description: FormField id (omit when creating)
name:
type: string
description: User-facing label
field_type:
type: string
enum:
- email
- text
- phone
- textarea
- radio
- select
- checkbox
- consent
required:
type: boolean
position:
type: integer
description: Zero-based ordinal
options:
type: array
items:
type: string
description: Required when field_type is radio/select/checkbox
_destroy:
type: boolean
description: Set true to remove this field
required:
- name
- field_type
settings:
type: object
confirmation_required:
type: boolean
description: 'Double opt-in: tags and the lead magnet wait until the person clicks the confirmation link.'
delivery_file_id:
type: string
description: File ID (`file_...`, from the Files API) to send as a download.
Error:
type: object
properties:
error:
type: object
properties:
type:
type: string
enum:
- api_error
- invalid_request_error
- validation_error
code:
type: string
message:
type: string
param:
type: string
errors:
type: object
doc_url:
type: string
required:
- type
- message
required:
- error
ListResponse_Form:
type: object
properties:
object:
type: string
enum:
- list
data:
type: array
items:
$ref: '#/components/schemas/Form'
has_more:
type: boolean
url:
type: string
required:
- object
- data
- has_more
- url
FormSubmission:
type: object
properties:
id:
type: string
object:
type: string
answers:
type: array
items:
type: object
properties:
field_type:
type: string
label:
type: string
required:
type: boolean
value:
oneOf:
- type: string
- type: array
items:
type: string
- type: boolean
- type: 'null'
description: A `consent` answer is `true` when the person ticked it.
options:
type: array
items:
type: string
required:
- field_type
- label
- required
- value
respondent_type:
type: string
confirmation_requested_at:
type:
- string
- 'null'
format: date-time
confirmed_at:
type:
- string
- 'null'
format: date-time
delivered_at:
type:
- string
- 'null'
format: date-time
created_at:
type: string
format: date-time
respondent_id:
type: string
form_id:
type: string
required:
- id
- object
- answers
- respondent_type
- confirmation_requested_at
- confirmed_at
- delivered_at
- created_at
- respondent_id
- form_id
headers:
Sunset:
description: Present only on a deprecated operation. HTTP-date (RFC 8594) after which the operation stops responding. Always at least six months after `Deprecation`.
schema:
type: string
examples:
- Thu, 01 Oct 2026 00:00:00 GMT
RequestId:
description: Unique id for this request. Quote it when reporting a problem.
schema:
type: string
examples:
- 8fe045fe-cb8a-4407-a44d-5df60385e522
DeprecationLink:
description: Present only on a deprecated operation. `<url>; rel="deprecation"` pointing at the migration notes.
schema:
type: string
examples:
- <https://crevio.co/docs/developer/guides/versioning>; rel="deprecation"
RetryAfter:
description: Seconds to wait before retrying.
schema:
type: integer
examples:
- 11
Deprecation:
description: Present only on a deprecated operation. Structured-field date (RFC 9745) — `@` followed by the Unix timestamp at which the operation became deprecated.
schema:
type: string
examples:
- '@1775001600'
RateLimit:
description: 'Remaining quota for the current window, as an IETF structured field: `"default";r=<remaining>;t=<seconds until reset>`.'
schema:
type: string
examples:
- '"default";r=596;t=11'
RateLimitPolicy:
description: 'The quota this credential is subject to: `"default";q=<requests>;w=<window seconds>`.'
schema:
type: string
examples:
- '"default";q=600;w=60'
securitySchemes:
ApiKey:
type: apiKey
in: header
name: Authorization
description: 'API key in the format: Bearer {api_token}'
externalDocs:
description: Crevio developer documentation
url: https://crevio.co/docs/developer
x-mint:
mcp:
enabled: true
x-api-lifecycle:
current_major_version: v1
versioning_scheme: URL path
deprecation_policy_url: https://crevio.co/docs/developer/guides/versioning
minimum_notice_days: 183
deprecation_headers:
- Deprecation
- Sunset
- Link