Authentication
The base URL is https://api.vdclip.com and the REST surface lives under /v1/*. There are two ways to authenticate:
API key
Authorization: Bearer vdck_... on every /v1 request. Server-to-server only.
OAuth 2.1
Authorization: Bearer <JWT> for MCP servers, AI agents, and integrations acting for a user.
API keys
Send your API key in the Authorization header as a Bearer token on every /v1 request. Keys are prefixed with vdck_.
curl https://api.vdclip.com/v1/account \
-H "Authorization: Bearer vdck_your_key_here"A successful response returns the resource directly:
{
"id": "acc_...",
"plan": "pro",
"credits": 120
}The API is server-to-server only. It has no CORS, so browser requests are rejected with ORIGIN_REJECTED. Treat vdck_... keys like a password: keep them in server environment variables or a secret manager, never in front-end code, mobile apps, or anything a user can inspect. If a key is exposed, rotate it immediately.
Pagination
List endpoints use cursor pagination. Pass a limit, then pass the returned cursor to fetch the next page. Defaults and maximums vary per endpoint and live in the OpenAPI spec.
curl "https://api.vdclip.com/v1/projects?limit=20" \
-H "Authorization: Bearer vdck_your_key_here"Scopes
Each scope follows the pattern vdclip:<resource>:<action>. A request without the scope its endpoint needs is rejected with MISSING_SCOPE. OAuth clients request the same scopes. The full catalog is in MCP Servers, and each endpoint page lists the scope it requires.
vdclip:render:execute and vdclip:social:publish are plan-gated: they only work on plans that include them, even when the key carries the scope. Render endpoints also consume credits, returning INSUFFICIENT_CREDITS when you run out. See the pricing page for what each plan includes.
Error responses
All /v1 errors use an errors array, with a machine-readable code and a human-readable description:
{
"errors": [
{
"code": "MISSING_SCOPE",
"description": "This credential is not authorized for vdclip:render:execute."
}
]
}| Code | Meaning |
|---|---|
INVALID_API_KEY | The Authorization header is missing, malformed, or unknown |
MISSING_SCOPE | The key lacks the scope required by this endpoint |
INSUFFICIENT_CREDITS | Not enough credits to complete the operation |
RATE_LIMITED | Too many requests (see rate limiting below) |
UPSTREAM_ERROR | A downstream service failed |
VALIDATION_ERROR | The request body or query failed validation |
INVALID_JSON | The request body is not valid JSON |
NOT_FOUND | The requested resource does not exist |
ORIGIN_REJECTED | The request came from a disallowed origin (browser) |
Include the X-Request-ID response header from a failing response when you contact contact@vdclip.com.
Rate limiting
When you exceed the rate limit, the API responds with HTTP 429 and a Retry-After header (in seconds). Wait at least that long, and use exponential backoff for repeated 429 responses.
HTTP/1.1 429 Too Many Requests
Retry-After: 30OAuth 2.1 for user-delegated clients
For MCP servers, AI agents, and third-party integrations that act on behalf of a user, VDClip runs an OAuth 2.1 Authorization Server. These clients send Authorization: Bearer <JWT> instead of an API key.
- The issuer is
https://api.vdclip.com. OAuth endpoints live under/oauth2/*, discovery under/.well-known/*. - Access tokens are JWTs (
at+jwt, ES256). - These endpoints use RFC-standard bodies, not the
/v1envelope. - They use the same
vdclip:<resource>:<action>scopes, with the same plan-gating.
Clients start at discovery (RFC 8414), which advertises the issuer, the authorize/token/revoke endpoints, the supported scopes, and the JWKS URI for verifying token signatures:
curl https://api.vdclip.com/.well-known/oauth-authorization-serverWith an access token, a client calls the same /v1 endpoints with the same Bearer header:
curl https://api.vdclip.com/v1/projects \
-H "Authorization: Bearer <JWT>"See OAuth 2.1 for the full flow.
Tips & Best Practices
Store vdck_ keys in environment variables or a secret manager. A key in browser code cannot work and only risks exposure.
Grant only the scopes an integration needs. A read-only integration should never hold write or render:execute scopes.
Respect the Retry-After header and use exponential backoff so a burst of requests does not keep tripping the rate limiter.
Store X-Request-ID and X-Trace-ID from responses so you can reference exact requests when you reach out to support.
Use the OAuth 2.1 Bearer flow when a client acts for a user. For your own backend, an API key is simpler.