Create one token per integration
Descriptive names, independent expiration dates, and separate activity make rotation and incident response safer.
Runvello developer platform
Use a tenant-scoped JSON API to integrate CRM, scheduling, project, contract, campaign, and billing workflows without exposing data across workspaces.
Quickstart
Generate a least-privilege token from Admin → API access, store it on your server, and call the workspace host that issued it.
curl --request GET \
--url "https://your-workspace.runvello.com/api/v1/clients?page=1&per_page=25" \
--header "Accept: application/json" \
--header "Authorization: Bearer $RUNVELLO_API_TOKEN"
import os
import requests
response = requests.get(
"https://your-workspace.runvello.com/api/v1/clients",
params={"page": 1, "per_page": 25},
headers={
"Accept": "application/json",
"Authorization": f"Bearer {os.environ['RUNVELLO_API_TOKEN']}",
},
timeout=30,
)
response.raise_for_status()
clients = response.json()["data"]
require "json"
require "net/http"
uri = URI("https://your-workspace.runvello.com/api/v1/clients?page=1&per_page=25")
request = Net::HTTP::Get.new(uri)
request["Accept"] = "application/json"
request["Authorization"] = "Bearer #{ENV.fetch('RUNVELLO_API_TOKEN')}"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
raise "Runvello request failed: #{response.code}" unless response.is_a?(Net::HTTPSuccess)
clients = JSON.parse(response.body).fetch("data")
// Node.js 18+ — keep the token in the server process environment.
const response = await fetch(
"https://your-workspace.runvello.com/api/v1/clients?page=1&per_page=25",
{
headers: {
Accept: "application/json",
Authorization: `Bearer ${process.env.RUNVELLO_API_TOKEN}`
}
}
)
if (!response.ok) throw new Error(`Runvello request failed: ${response.status}`)
const { data: clients } = await response.json()
// React calls your own backend. Never expose RUNVELLO_API_TOKEN to the browser.
import { useEffect, useState } from "react"
export function ClientList() {
const [clients, setClients] = useState([])
useEffect(() => {
fetch("/api/runvello/clients")
.then((response) => {
if (!response.ok) throw new Error("Unable to load clients")
return response.json()
})
.then(({ data }) => setClients(data))
}, [])
return <ul>{clients.map((client) => <li key={client.id}>{client.name}</li>)}</ul>
}
// app/api/runvello/clients/route.js — this module runs only on your server.
export async function GET() {
const upstream = await fetch(
`${process.env.RUNVELLO_BASE_URL}/api/v1/clients?page=1&per_page=25`,
{
headers: {
Accept: "application/json",
Authorization: `Bearer ${process.env.RUNVELLO_API_TOKEN}`
},
cache: "no-store"
}
)
return Response.json(await upstream.json(), { status: upstream.status })
}
React security: the component calls an application-owned server route. The server—not the browser—adds the Runvello bearer token.
Authentication
Send the token in the Authorization header over HTTPS. Raw tokens are shown once and stored by Runvello only as SHA-256 digests.
Descriptive names, independent expiration dates, and separate activity make rotation and incident response safer.
Read and write scopes are separate. Contracts, invoices, campaigns, projects, and tasks remain read-only.
Never place a token in browser JavaScript, a mobile bundle, URL, log, screenshot, or source-control history.
Resources
All collection endpoints are paginated unless the reference explicitly documents a compatibility exception.
Read and safely create or update customer records. Preview and execute lead conversion with a dedicated scope.
Read, create, and update bookings while retaining plan limits and tenant-safe relationship checks.
Read project delivery state, project tasks, and standalone work without exposing cross-workspace records.
Read signed-work and billing context. Financial writes remain deliberately unavailable.
Read campaign configuration and delivery status without allowing remote campaign mutation.
Errors and reliability
Error bodies are JSON. Retry throttling and transient server errors with exponential backoff; do not retry validation failures without changing the request.
Ready to integrate?
Explore the browser reference, import one Postman collection, or download the canonical OpenAPI specification.