Skip to main content
The Volunteer API has a single documented base URL. This page covers the URL structure, the /v1/ versioning convention, the HTTPS requirements, and what’s known about test or sandbox environments.

The single documented base URL

https://api.vomo.org/v1
That’s the entire spec-documented surface. Every endpoint in the API is reached by appending the endpoint path to this base — GET /v1/users is GET https://api.vomo.org/v1/users.
ComponentValue
Protocolhttps only — plain HTTP is not supported
Hostapi.vomo.org
Version segment/v1 — present on every path
Resource paths/users, /projects, /groups, /campaigns, /organizations, /forms, /certificates
A few example requests showing the full URL structure:
GET  https://api.vomo.org/v1/users
GET  https://api.vomo.org/v1/users/12345
GET  https://api.vomo.org/v1/projects?page=2
POST https://api.vomo.org/v1/groups
GET  https://api.vomo.org/v1/forms/789/completions
The version segment (/v1) is part of the base URL — not part of individual endpoint paths. When the documentation refers to an endpoint as GET /users, the full URL is https://api.vomo.org/v1/users.

The /v1 versioning convention

Volunteer’s base URL includes an explicit /v1 segment. This is different from the other two Virtuous APIs:
APIBase URLVersion segment?
CRM+https://api.virtuoussoftware.com/apiNo
Raisehttps://prod-api.raisedonors.com/apiNo
Volunteerhttps://api.vomo.org/v1Yes

What this means for partner integrations

The presence of /v1 suggests the platform may introduce future versions (/v2, etc.) without breaking existing integrations. Integrations targeting /v1 should continue to work as long as the v1 contract is maintained, even after a v2 is released. This is purely speculative for now — no v2 exists. But the URL pattern is set up for a future migration to be possible. For practical integration code, hardcode the /v1 in your base URL constant:
const VOMO_BASE_URL = 'https://api.vomo.org/v1';

async function get(path, options = {}) {
  return fetch(`${VOMO_BASE_URL}${path}`, options);
}

// Usage
const users = await get('/users');
const oneUser = await get('/users/12345');
If a v2 is released someday, switching is a one-line change to the constant — assuming the path structure is preserved. See Versioning and Backward Compatibility for the broader discussion.

HTTPS is required

All Volunteer API requests must use HTTPS. The platform does not respond to plain HTTP requests, and any code that attempts http://api.vomo.org/v1/users will fail or be redirected.
Why HTTPS matters
The Bearer token in the Authorization header would be visible on the wire over plain HTTP
PII in responses (names, emails, addresses) would be visible over plain HTTP
Modern browsers and many HTTP clients block or warn on plain-HTTP API calls
Compliance frameworks (PCI, SOC 2, GDPR) require encryption in transit
In practice, this means every integration uses https:// in its URL constant. Don’t try to override certificate validation, use self-signed certs against the production host, or otherwise loosen the TLS posture.

TLS version

The Volunteer API requires TLS 1.2 or later. Most modern HTTP libraries default to this, but legacy clients (very old Java, old PHP, certain embedded systems) may need explicit configuration. If you see TLS handshake errors, check the client’s TLS configuration before suspecting the API.

Test and sandbox environments

The Volunteer OpenAPI spec documents one host: production. There’s no separately-documented sandbox URL. ⚠️ Spec gap: The OpenAPI spec doesn’t expose a sandbox or test environment. Test and development access is typically handled by issuing a token against a dedicated test organization on the production host, rather than by using a separate URL. Coordinate with the customer’s VOMO concierge if a dedicated test environment is needed.

What this means in practice

For partner integration development:
ApproachWhen to use
Develop against a customer’s test organizationIf the customer has a separate VOMO organization specifically for testing, use a token from that organization.
Develop against a developer-owned VOMO accountThe partner sets up their own VOMO account specifically for integration development.
Develop against production with careLast resort — only if no test organization is available. Use clearly-marked test data (dev+timestamp@example.com emails).
The production host is https://api.vomo.org/v1 regardless of which approach you use. Isolation is at the organization (token) level, not the URL level.

Don’t develop against a real customer’s production data

A common anti-pattern: developing the integration against a real customer’s live VOMO account. This produces test users mingled with real users, test groups in production reports, and potentially destructive operations affecting real records. The right path is to coordinate a test organization upfront. If the customer doesn’t have one, request that one be set up before integration development begins.

Service health and status

The Volunteer OpenAPI spec doesn’t document a status page URL or health-check endpoint. For partner integrations operating at scale, knowing when the API is degraded matters — sustained 5xx responses or elevated latency may indicate a platform issue rather than an integration bug.

What partner integrations can do

PracticeDescription
Track 5xx response rateA spike across multiple customers usually means a platform issue, not a per-customer one.
Track API latency over timeSudden latency increases without your traffic changing typically indicate platform-side issues.
Maintain a status page for the integrationIndependent of VOMO — communicates to your customers when your integration is degraded for any reason.
Coordinate with VOMO during incidentsWhen sustained issues appear, reach out to VOMO support to confirm whether it’s a platform issue.
Don’t poll the API to detect health — that wastes rate-limit budget. Track the health of real workloads instead.

Latency and geographic considerations

The spec doesn’t document the API’s deployment geography or expected latency from different regions. In practice, partner integrations should expect:
Source regionExpected latency to API
North AmericaLow (typically <100ms for a simple GET)
EuropeModerate (typically <200ms)
Asia / PacificHigher (varies; can be >300ms)
These are typical web API characteristics, not specific guarantees. For latency-sensitive workloads, measure from your actual deployment environment.

Implications for sync architecture

For integrations doing bulk reads (backfills, daily reconciliation), latency adds up. A backfill of 100,000 users with 100ms round-trip per request takes ~3 hours even with no rate-limit throttling. Plan for this when scoping the backfill window. The patterns on Sync Architecture Patterns cover backfill design for large datasets.

URL construction patterns

A few practices that prevent common URL-construction bugs:

Don’t hand-concatenate query parameters

// ❌ Anti-pattern — breaks on special characters
const url = `https://api.vomo.org/v1/users?name_like=${searchTerm}`;

// ✅ Use URLSearchParams (or equivalent)
const params = new URLSearchParams({ name_like: searchTerm });
const url = `https://api.vomo.org/v1/users?${params}`;
Names with spaces, apostrophes, or other characters need URL encoding. Manual concatenation forgets this; URLSearchParams handles it correctly.

Don’t hand-construct paginated URLs

// ❌ Anti-pattern — breaks if pagination changes
const nextUrl = `${baseUrl}/users?page=${currentPage + 1}`;

// ✅ Follow links.next from the previous response
const nextUrl = previousResponse.links.next;
The API tells you the next page’s URL in links.next. Use it. Manual page-number construction works today but can break if the pagination scheme evolves.

Don’t strip /v1/ from URLs returned by the API

The links field in paginated responses includes the full URL with /v1/:
{
  "links": {
    "next": "https://api.vomo.org/v1/users?page=2"
  }
}
If your code strips the version segment (“I’ll add it myself when I make the call”), you’ll either double-prefix or miss it entirely. Use returned URLs as-is.

Be cautious with trailing slashes

The Volunteer paths don’t include trailing slashes in the spec:
✅ /users
✅ /users/12345
❌ /users/      (trailing slash — typically rejected or redirected)
Most HTTP clients handle this correctly, but if you’re constructing URLs by string template, double-check that you’re not appending a stray /.

A reference base URL setup

A minimal, well-organized base URL setup for a partner integration:
// config.js
export const VOMO_API_BASE_URL = 'https://api.vomo.org/v1';

// vomo-client.js
import { VOMO_API_BASE_URL } from './config.js';

export class VomoClient {
  constructor({ token }) {
    this.token = token;
  }

  async _request(path, options = {}) {
    const url = path.startsWith('http') ? path : `${VOMO_API_BASE_URL}${path}`;

    const response = await fetch(url, {
      ...options,
      headers: {
        Authorization: `Bearer ${this.token}`,
        Accept: 'application/json',
        ...options.headers,
      },
    });

    if (!response.ok) {
      throw await this._buildError(response);
    }

    return response.json();
  }

  async getUsers(params = {}) {
    const query = new URLSearchParams(params).toString();
    return this._request(`/users${query ? `?${query}` : ''}`);
  }

  async getUser(userId) {
    return this._request(`/users/${userId}`);
  }

  async followLink(url) {
    // For pagination — accept the full URL from a previous response
    return this._request(url);
  }
}
This pattern:
  • Defines the base URL in one place (easy to change for future v2).
  • Auto-detects whether a path or full URL is passed (so followLink works with links.next).
  • Centralizes auth headers (no per-call boilerplate).
  • Throws structured errors (caller doesn’t deal with raw Response objects).

Where to go next

Walk through a slightly richer call now that the URL structure is clear.The Bearer token pattern used with this base URL.How the links.next URLs returned by the API work.The longer discussion of /v1 and what a future /v2 might mean. The Volunteer API has a single documented base URL. This page covers the URL structure, the /v1/ versioning convention, the HTTPS requirements, and what’s known about test or sandbox environments.

The single documented base URL

https://api.vomo.org/v1
That’s the entire spec-documented surface. Every endpoint in the API is reached by appending the endpoint path to this base — GET /v1/users is GET https://api.vomo.org/v1/users.
ComponentValue
Protocolhttps only — plain HTTP is not supported
Hostapi.vomo.org
Version segment/v1 — present on every path
Resource paths/users, /projects, /groups, /campaigns, /organizations, /forms, /certificates
A few example requests showing the full URL structure:
GET  https://api.vomo.org/v1/users
GET  https://api.vomo.org/v1/users/12345
GET  https://api.vomo.org/v1/projects?page=2
POST https://api.vomo.org/v1/groups
GET  https://api.vomo.org/v1/forms/789/completions
The version segment (/v1) is part of the base URL — not part of individual endpoint paths. When the documentation refers to an endpoint as GET /users, the full URL is https://api.vomo.org/v1/users.

The /v1 versioning convention

Volunteer’s base URL includes an explicit /v1 segment. This is different from the other two Virtuous APIs:
APIBase URLVersion segment?
CRM+https://api.virtuoussoftware.com/apiNo
Raisehttps://prod-api.raisedonors.com/apiNo
Volunteerhttps://api.vomo.org/v1Yes

What this means for partner integrations

The presence of /v1 suggests the platform may introduce future versions (/v2, etc.) without breaking existing integrations. Integrations targeting /v1 should continue to work as long as the v1 contract is maintained, even after a v2 is released. This is purely speculative for now — no v2 exists. But the URL pattern is set up for a future migration to be possible. For practical integration code, hardcode the /v1 in your base URL constant:
const VOMO_BASE_URL = 'https://api.vomo.org/v1';

async function get(path, options = {}) {
  return fetch(`${VOMO_BASE_URL}${path}`, options);
}

// Usage
const users = await get('/users');
const oneUser = await get('/users/12345');
If a v2 is released someday, switching is a one-line change to the constant — assuming the path structure is preserved. See Versioning and Backward Compatibility for the broader discussion.

HTTPS is required

All Volunteer API requests must use HTTPS. The platform does not respond to plain HTTP requests, and any code that attempts http://api.vomo.org/v1/users will fail or be redirected.
Why HTTPS matters
The Bearer token in the Authorization header would be visible on the wire over plain HTTP
PII in responses (names, emails, addresses) would be visible over plain HTTP
Modern browsers and many HTTP clients block or warn on plain-HTTP API calls
Compliance frameworks (PCI, SOC 2, GDPR) require encryption in transit
In practice, this means every integration uses https:// in its URL constant. Don’t try to override certificate validation, use self-signed certs against the production host, or otherwise loosen the TLS posture.

TLS version

The Volunteer API requires TLS 1.2 or later. Most modern HTTP libraries default to this, but legacy clients (very old Java, old PHP, certain embedded systems) may need explicit configuration. If you see TLS handshake errors, check the client’s TLS configuration before suspecting the API.

Test and sandbox environments

The Volunteer OpenAPI spec documents one host: production. There’s no separately-documented sandbox URL. ⚠️ Spec gap: The OpenAPI spec doesn’t expose a sandbox or test environment. Test and development access is typically handled by issuing a token against a dedicated test organization on the production host, rather than by using a separate URL. Coordinate with the customer’s VOMO concierge if a dedicated test environment is needed.

What this means in practice

For partner integration development:
ApproachWhen to use
Develop against a customer’s test organizationIf the customer has a separate VOMO organization specifically for testing, use a token from that organization.
Develop against a developer-owned VOMO accountThe partner sets up their own VOMO account specifically for integration development.
Develop against production with careLast resort — only if no test organization is available. Use clearly-marked test data (dev+timestamp@example.com emails).
The production host is https://api.vomo.org/v1 regardless of which approach you use. Isolation is at the organization (token) level, not the URL level.

Don’t develop against a real customer’s production data

A common anti-pattern: developing the integration against a real customer’s live VOMO account. This produces test users mingled with real users, test groups in production reports, and potentially destructive operations affecting real records. The right path is to coordinate a test organization upfront. If the customer doesn’t have one, request that one be set up before integration development begins.

Service health and status

The Volunteer OpenAPI spec doesn’t document a status page URL or health-check endpoint. For partner integrations operating at scale, knowing when the API is degraded matters — sustained 5xx responses or elevated latency may indicate a platform issue rather than an integration bug.

What partner integrations can do

PracticeDescription
Track 5xx response rateA spike across multiple customers usually means a platform issue, not a per-customer one.
Track API latency over timeSudden latency increases without your traffic changing typically indicate platform-side issues.
Maintain a status page for the integrationIndependent of VOMO — communicates to your customers when your integration is degraded for any reason.
Coordinate with VOMO during incidentsWhen sustained issues appear, reach out to VOMO support to confirm whether it’s a platform issue.
Don’t poll the API to detect health — that wastes rate-limit budget. Track the health of real workloads instead.

Latency and geographic considerations

The spec doesn’t document the API’s deployment geography or expected latency from different regions. In practice, partner integrations should expect:
Source regionExpected latency to API
North AmericaLow (typically <100ms for a simple GET)
EuropeModerate (typically <200ms)
Asia / PacificHigher (varies; can be >300ms)
These are typical web API characteristics, not specific guarantees. For latency-sensitive workloads, measure from your actual deployment environment.

Implications for sync architecture

For integrations doing bulk reads (backfills, daily reconciliation), latency adds up. A backfill of 100,000 users with 100ms round-trip per request takes ~3 hours even with no rate-limit throttling. Plan for this when scoping the backfill window. The patterns on Sync Architecture Patterns cover backfill design for large datasets.

URL construction patterns

A few practices that prevent common URL-construction bugs:

Don’t hand-concatenate query parameters

// ❌ Anti-pattern — breaks on special characters
const url = `https://api.vomo.org/v1/users?name_like=${searchTerm}`;

// ✅ Use URLSearchParams (or equivalent)
const params = new URLSearchParams({ name_like: searchTerm });
const url = `https://api.vomo.org/v1/users?${params}`;
Names with spaces, apostrophes, or other characters need URL encoding. Manual concatenation forgets this; URLSearchParams handles it correctly.

Don’t hand-construct paginated URLs

// ❌ Anti-pattern — breaks if pagination changes
const nextUrl = `${baseUrl}/users?page=${currentPage + 1}`;

// ✅ Follow links.next from the previous response
const nextUrl = previousResponse.links.next;
The API tells you the next page’s URL in links.next. Use it. Manual page-number construction works today but can break if the pagination scheme evolves.

Don’t strip /v1/ from URLs returned by the API

The links field in paginated responses includes the full URL with /v1/:
{
  "links": {
    "next": "https://api.vomo.org/v1/users?page=2"
  }
}
If your code strips the version segment (“I’ll add it myself when I make the call”), you’ll either double-prefix or miss it entirely. Use returned URLs as-is.

Be cautious with trailing slashes

The Volunteer paths don’t include trailing slashes in the spec:
✅ /users
✅ /users/12345
❌ /users/      (trailing slash — typically rejected or redirected)
Most HTTP clients handle this correctly, but if you’re constructing URLs by string template, double-check that you’re not appending a stray /.

A reference base URL setup

A minimal, well-organized base URL setup for a partner integration:
// config.js
export const VOMO_API_BASE_URL = 'https://api.vomo.org/v1';

// vomo-client.js
import { VOMO_API_BASE_URL } from './config.js';

export class VomoClient {
  constructor({ token }) {
    this.token = token;
  }

  async _request(path, options = {}) {
    const url = path.startsWith('http') ? path : `${VOMO_API_BASE_URL}${path}`;

    const response = await fetch(url, {
      ...options,
      headers: {
        Authorization: `Bearer ${this.token}`,
        Accept: 'application/json',
        ...options.headers,
      },
    });

    if (!response.ok) {
      throw await this._buildError(response);
    }

    return response.json();
  }

  async getUsers(params = {}) {
    const query = new URLSearchParams(params).toString();
    return this._request(`/users${query ? `?${query}` : ''}`);
  }

  async getUser(userId) {
    return this._request(`/users/${userId}`);
  }

  async followLink(url) {
    // For pagination — accept the full URL from a previous response
    return this._request(url);
  }
}
This pattern:
  • Defines the base URL in one place (easy to change for future v2).
  • Auto-detects whether a path or full URL is passed (so followLink works with links.next).
  • Centralizes auth headers (no per-call boilerplate).
  • Throws structured errors (caller doesn’t deal with raw Response objects).

Where to go next

Walk through a slightly richer call now that the URL structure is clear.The Bearer token pattern used with this base URL.How the links.next URLs returned by the API work.The longer discussion of /v1 and what a future /v2 might mean.
Last modified on May 22, 2026