fanvault-shop Media API
The Media API from fanvault-shop — 4 operation(s) for media.
The Media API from fanvault-shop — 4 operation(s) for media.
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/fanvault-shop:fanvault-shop-media-api"
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.
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: Fanvault Media API
version: 1.0.0
description: Programmatic control of a Fanvault creator storefront. Every path below is one tool from the shared registry, reachable over plain HTTP; the same registry is served as MCP over Streamable HTTP at the endpoint in the x-mcp block, and drives the `fanvault` CLI. All money values are integer cents.
servers:
- url: https://fanvault.shop
security:
- bearerAuth: []
tags:
- name: Media
paths:
/api/v1/tools/complete_upload:
post:
operationId: complete_upload
summary: Complete upload
description: Finishes an upload started with create_upload_url, after you have PUT the bytes to its upload_url. Checks the file the server actually received — its real size against the purpose's limit, its type from its bytes, images normalized to web format — then moves it to its real home and returns the storage_path / public_url to use (see `usage`). A file that fails a check is deleted. Call it once per upload, within 2 hours.
tags:
- Media
security:
- bearerAuth: []
parameters:
- name: Idempotency-Key
in: header
required: false
schema:
type: string
maxLength: 255
description: Replays the stored response for a repeat of the same call within 24h. Strongly recommended on every mutating call — agents retry on ambiguous network failures, and without a key a retry creates a second listing, post, or message.
- name: X-Fanvault-Dry-Run
in: header
required: false
schema:
type: string
enum:
- '1'
description: Run every precondition and return the change that would be made, writing nothing.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
creator:
type: string
maxLength: 64
description: 'Which creator to act on: a creator UUID or @handle. Required for admin/agency tokens that manage multiple creators and for tokens restricted to more than one creator (see list_managed_creators); omit it when the token is pinned to exactly one creator or you are the creator.'
storage_path:
type: string
minLength: 1
maxLength: 400
description: The storage_path create_upload_url returned (quarantine/…).
required:
- storage_path
additionalProperties: false
responses:
'200':
description: Tool result.
content:
application/json:
schema:
type: object
properties:
content:
type: array
items:
type: object
properties:
type:
type: string
text:
type: string
required:
- type
- text
structuredContent:
type: object
properties:
media:
type: object
properties:
storage_path:
type: string
bucket:
type: string
public_url:
type:
- string
- 'null'
content_type:
type: string
bytes:
type: number
usage:
type: string
required:
- storage_path
- bucket
- public_url
- content_type
- bytes
- usage
additionalProperties: true
creator:
type: object
properties:
id:
type: string
handle:
type:
- string
- 'null'
required:
- id
- handle
additionalProperties: true
required:
- media
additionalProperties: true
required:
- content
'400':
description: Invalid params, or the acting creator is ambiguous.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Token lacks the required scope, or targets a creator it may not act on.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Unknown tool, or the referenced resource does not exist.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: A precondition is unmet (payouts not connected, ship-from unset, ...).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
description: The action was understood but could not be completed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limited. Honor Retry-After.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/v1/tools/create_upload_url:
post:
operationId: create_upload_url
summary: Create upload URL
description: 'Returns a presigned PUT URL to upload one binary file directly to Fanvault storage. ONLY for clients that can make outbound HTTPS PUT requests to *.supabase.co — sandboxed or egress-restricted agents cannot complete this flow and should use upload_media (inline base64, ≤3MB) or import_media_from_url instead. Steps: (1) call this with the purpose + filename + content_type; (2) HTTP PUT the file bytes to upload_url; (3) call complete_upload with the returned storage_path, which checks the file (real size, type from its bytes, images normalized) and moves it to its real home; (4) pass complete_upload''s storage_path (for product/lesson files) or public_url (for posts/avatar/banner) into the relevant create/update tool — see its `usage`. The storage_path returned HERE is a holding area no other tool accepts.'
tags:
- Media
security:
- bearerAuth: []
parameters:
- name: Idempotency-Key
in: header
required: false
schema:
type: string
maxLength: 255
description: Replays the stored response for a repeat of the same call within 24h. Strongly recommended on every mutating call — agents retry on ambiguous network failures, and without a key a retry creates a second listing, post, or message.
- name: X-Fanvault-Dry-Run
in: header
required: false
schema:
type: string
enum:
- '1'
description: Run every precondition and return the change that would be made, writing nothing.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
creator:
type: string
maxLength: 64
description: 'Which creator to act on: a creator UUID or @handle. Required for admin/agency tokens that manage multiple creators and for tokens restricted to more than one creator (see list_managed_creators); omit it when the token is pinned to exactly one creator or you are the creator.'
purpose:
type: string
enum:
- post_media
- product_file
- lesson_video
- lesson_attachment
- preview_image
- avatar
- banner
description: What the file is for — determines bucket, path, size, and allowed types.
filename:
type: string
minLength: 1
maxLength: 200
description: Original filename (used for extension + display).
content_type:
type: string
minLength: 3
maxLength: 100
description: MIME type, e.g. image/jpeg or video/mp4.
required:
- purpose
- filename
- content_type
additionalProperties: false
responses:
'200':
description: Tool result.
content:
application/json:
schema:
type: object
properties:
content:
type: array
items:
type: object
properties:
type:
type: string
text:
type: string
required:
- type
- text
structuredContent:
type: object
properties:
upload:
type: object
properties:
method:
type: string
const: PUT
upload_url:
type: string
storage_path:
type: string
bucket:
type: string
public_url:
type:
- string
- 'null'
expires_at:
type: string
max_bytes:
type: number
allowed_mime:
type: string
usage:
type: string
required:
- method
- upload_url
- storage_path
- bucket
- public_url
- expires_at
- max_bytes
- allowed_mime
- usage
additionalProperties: true
creator:
type: object
properties:
id:
type: string
handle:
type:
- string
- 'null'
required:
- id
- handle
additionalProperties: true
required:
- upload
additionalProperties: true
required:
- content
'400':
description: Invalid params, or the acting creator is ambiguous.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Token lacks the required scope, or targets a creator it may not act on.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Unknown tool, or the referenced resource does not exist.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: A precondition is unmet (payouts not connected, ship-from unset, ...).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
description: The action was understood but could not be completed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limited. Honor Retry-After.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/v1/tools/import_media_from_url:
post:
operationId: import_media_from_url
summary: Import media from URL
description: Fetches a PUBLIC http(s) media URL server-side into Fanvault storage and returns the resulting storage_path / public_url (see `usage`). Works from any client — the server does the fetching, so the agent needs no network access. Preferred over create_upload_url when you already have a URL; for local files use upload_media. Images are normalized to web format. Private/internal addresses are blocked; max 50MB. Reaches the given URL.
tags:
- Media
security:
- bearerAuth: []
parameters:
- name: Idempotency-Key
in: header
required: false
schema:
type: string
maxLength: 255
description: Replays the stored response for a repeat of the same call within 24h. Strongly recommended on every mutating call — agents retry on ambiguous network failures, and without a key a retry creates a second listing, post, or message.
- name: X-Fanvault-Dry-Run
in: header
required: false
schema:
type: string
enum:
- '1'
description: Run every precondition and return the change that would be made, writing nothing.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
creator:
type: string
maxLength: 64
description: 'Which creator to act on: a creator UUID or @handle. Required for admin/agency tokens that manage multiple creators and for tokens restricted to more than one creator (see list_managed_creators); omit it when the token is pinned to exactly one creator or you are the creator.'
url:
type: string
format: uri
description: Public http(s) URL of the image/video to import.
purpose:
type: string
enum:
- post_media
- product_file
- lesson_video
- lesson_attachment
- preview_image
- avatar
- banner
description: What the file is for — determines destination and allowed types.
filename:
type: string
maxLength: 200
description: 'Override filename (default: from the URL).'
required:
- url
- purpose
additionalProperties: false
responses:
'200':
description: Tool result.
content:
application/json:
schema:
type: object
properties:
content:
type: array
items:
type: object
properties:
type:
type: string
text:
type: string
required:
- type
- text
structuredContent:
type: object
properties:
media:
type: object
properties:
storage_path:
type: string
bucket:
type: string
public_url:
type:
- string
- 'null'
content_type:
type: string
bytes:
type: number
usage:
type: string
required:
- storage_path
- bucket
- public_url
- content_type
- bytes
- usage
additionalProperties: true
creator:
type: object
properties:
id:
type: string
handle:
type:
- string
- 'null'
required:
- id
- handle
additionalProperties: true
required:
- media
additionalProperties: true
required:
- content
'400':
description: Invalid params, or the acting creator is ambiguous.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Token lacks the required scope, or targets a creator it may not act on.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Unknown tool, or the referenced resource does not exist.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: A precondition is unmet (payouts not connected, ship-from unset, ...).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
description: The action was understood but could not be completed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limited. Honor Retry-After.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/v1/tools/upload_media:
post:
operationId: upload_media
summary: Upload media (inline)
description: Uploads one small file passed inline as base64 — the server writes it straight to Fanvault storage, so this works from ANY client, including sandboxed agents with no outbound network access. Max ~3MB decoded; best for avatars, banners, and small images (content type is detected from the bytes). Then pass storage_path (product/lesson files) or public_url (posts/avatar/banner) into the relevant create/update tool — see the returned `usage`. For media already at a public URL prefer import_media_from_url; for larger files from clients with open networking use create_upload_url.
tags:
- Media
security:
- bearerAuth: []
parameters:
- name: Idempotency-Key
in: header
required: false
schema:
type: string
maxLength: 255
description: Replays the stored response for a repeat of the same call within 24h. Strongly recommended on every mutating call — agents retry on ambiguous network failures, and without a key a retry creates a second listing, post, or message.
- name: X-Fanvault-Dry-Run
in: header
required: false
schema:
type: string
enum:
- '1'
description: Run every precondition and return the change that would be made, writing nothing.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
creator:
type: string
maxLength: 64
description: 'Which creator to act on: a creator UUID or @handle. Required for admin/agency tokens that manage multiple creators and for tokens restricted to more than one creator (see list_managed_creators); omit it when the token is pinned to exactly one creator or you are the creator.'
purpose:
type: string
enum:
- post_media
- product_file
- lesson_video
- lesson_attachment
- preview_image
- avatar
- banner
description: What the file is for — determines bucket, path, size, and allowed types.
data_base64:
type: string
minLength: 8
maxLength: 4000000
description: 'The file bytes as raw base64 (a data: URI prefix is tolerated and stripped). Max ~3MB decoded.'
filename:
type: string
maxLength: 200
description: 'Filename for extension + display (default: upload).'
required:
- purpose
- data_base64
additionalProperties: false
responses:
'200':
description: Tool result.
content:
application/json:
schema:
type: object
properties:
content:
type: array
items:
type: object
properties:
type:
type: string
text:
type: string
required:
- type
- text
structuredContent:
type: object
properties:
media:
type: object
properties:
storage_path:
type: string
bucket:
type: string
public_url:
type:
- string
- 'null'
content_type:
type: string
bytes:
type: number
usage:
type: string
required:
- storage_path
- bucket
- public_url
- content_type
- bytes
- usage
additionalProperties: true
creator:
type: object
properties:
id:
type: string
handle:
type:
- string
- 'null'
required:
- id
- handle
additionalProperties: true
required:
- media
additionalProperties: true
required:
- content
'400':
description: Invalid params, or the acting creator is ambiguous.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Token lacks the required scope, or targets a creator it may not act on.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Unknown tool, or the referenced resource does not exist.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: A precondition is unmet (payouts not connected, ship-from unset, ...).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
description: The action was understood but could not be completed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limited. Honor Retry-After.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
Error:
type: object
properties:
error:
type: object
properties:
code:
type: string
message:
type: string
hint:
type: string
retryAfterSeconds:
type: integer
details: {}
required:
- code
- message
required:
- error
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: 'A Fanvault personal access token (fv_mcp_…), created at /settings/cli or /settings/mcp, or an OAuth 2.1 access token. Sent as `Authorization: Bearer <token>`.'
x-mcp:
endpoint: https://fanvault.shop/mcp
transport: streamable-http
spec_revision: '2025-11-25'
auth: Bearer PAT (fv_mcp_…) or OAuth 2.1
scopes:
- read
- write
- destructive
- payments
tool_count: 82
x-fanvault:
manifest: https://fanvault.shop/api/v1/manifest
manifest_version: 1
tools_hash: 385678b0326a5acd4c4ad0e412991ec0c9a510ea57eb743899b7c40ad0a5ecf4
min_cli_version: 0.1.0
cli:
install: npm i -g fanvault
docs: https://fanvault.shop/developers/cli