Skip to main content
An Organization in the Volunteer API represents a customer entity — typically a nonprofit, a corporation’s CSR program, or a similar group running a volunteer initiative. Organizations can be arranged in parent-child hierarchies — a national umbrella organization with regional chapter children, a corporation with departmental sub-orgs, an interfaith network with member organizations. This is the organization family concept that determines what data an API token can access: a token issued for a parent organization typically grants access to that organization and its children.

The two endpoints

EndpointMethodWhat it returns
/organizationsGETThe Organization (or family) accessible to the token
/organizations/{id}GETA single Organization with its parent/child relationships
Both are read-only. Organization records are managed in the VOMO admin UI; there’s no API path for creating, updating, or deleting Organizations.
⚠️ Spec gap (audit #25, #26, #27): The Organization endpoints have empty schema: {} in the OpenAPI spec — the response shape is documented only through inline examples. There is no OrganizationResource component schema.The fields documented on this page come from the spec’s inline examples and live API observations. Treat them as the working contract, but confirm against actual responses for production-critical workflows.

The Organization resource

Based on the spec’s inline example, an Organization has these fields:

Core identity

FieldTypeDescription
idintegerThe Organization’s stable ID
namestringDisplay name
slugstringURL-safe identifier (used in some filter parameters like org_slug)
typestringOrganization type (e.g., "NPO" for nonprofit)
descriptionstringFree-text description (may be null)
created_atstringISO 8601 datetime
updated_atstringISO 8601 datetime
deleted_atstring or nullIf deleted, the deletion timestamp

Contact information

FieldTypeDescription
emailstringPrimary contact email
phonestringContact phone number
websitestringThe Organization’s website URL

Organizational metadata

FieldTypeDescription
tax_numberstring or nullTax ID (EIN, etc.)
org_sizeintegerApproximate size (number of people in the org)
background_check_expirationstringHow long background checks remain valid (e.g., "1_YEAR")
hub_experiencestringHub experience tier (e.g., "FULL")
invitation_tokenstringToken for inviting new users to the org
user_submitted_projectsintegerFlag indicating whether users can submit their own Projects (0 or 1)
show_categoriesintegerFlag for displaying categories (0 or 1)

Custom monikers

VOMO Organizations support custom display labels that override the default UI vocabulary:
FieldDefaultExample custom values
groups_moniker"Group""Team", "Chapter", "Cohort"
project_moniker"Project""Opportunity", "Event", "Activity"
campaign_moniker"Campaign""Initiative", "Drive", "Mission"
For partner integrations building user-facing displays, honor these monikers when displaying Organization-specific content. A customer that calls Projects “Events” appreciates seeing “Events” in your UI rather than “Projects.”

Address

The address field is an object with detailed location info:
{
  "address": {
    "lat": 32.7767,
    "lng": -96.7970,
    "country": "United States",
    "country_short": "US",
    "locality": "Dallas",
    "locality_short": "Dallas",
    "administrative_area_level_1": "Texas",
    "administrative_area_level_1_short": "TX",
    "timezone": "America/Chicago",
    "formatted_address": "Dallas, TX, USA"
  }
}
The format follows the Google Places API convention. The formatted_address field is the human-readable string suitable for display. The logo field is a media object:
{
  "logo": {
    "id": 99908,
    "type": "LOGO",
    "urls": {
      "s": "https://web-assets.vomo.org/.../logo-small.jpg",
      "o": "https://web-assets.vomo.org/.../logo-original.jpg",
      "l": "https://web-assets.vomo.org/.../logo-large.jpg"
    },
    "mediable_id": 12345,
    "mediable_type": "organization",
    "created_at": "...",
    "updated_at": "...",
    "deleted_at": null
  }
}
The urls object provides multiple sizes (s = small, o = original, l = large) for different display contexts.

Parent and child relationships

The defining fields for the organization family:
FieldTypeDescription
parent_organizationsarrayOrganizations this org is a child of
child_organizationsarrayOrganizations this org is a parent of
Each entry in these arrays is itself an Organization-shaped object (potentially abbreviated), allowing the partner integration to navigate the hierarchy from any starting point.

The organization family pattern

The parent-child relationships form a tree (or in some cases, a more complex DAG):

What this enables

CapabilityDescription
Single token, multiple organizationsA token issued at the parent level grants access to descendant organizations
Aggregated reportingReports can span the full family or filter to specific child orgs
Per-org branding and configurationEach org has its own monikers, logos, contact info
Resource attributionProjects, Campaigns, Groups are owned by specific organizations within the family

Resource attribution

Most resources in the API include organization attribution:
ResourceOrg attribution fields
Projectorganization, organization_id, organization_slug
Campaignorganization, organization_slug
Group(parent organization is implied; not directly exposed)
Usermembership_* fields scoped to the current org
For partner integrations doing per-org reporting or routing:
JavaScript
async function projectsForChildOrg(orgSlug) {
  const params = new URLSearchParams({ org_slug: orgSlug });
  return paginate(`https://api.vomo.org/v1/projects?${params}`);
}

async function campaignsForChildOrg(orgSlug) {
  const params = new URLSearchParams({ org_slug: orgSlug });
  return paginate(`https://api.vomo.org/v1/campaigns?${params}`);
}
The org_slug query parameter on Project and Campaign endpoints accepts comma-separated values for multi-org queries.

Listing organizations

cURL
curl https://api.vomo.org/v1/organizations \
  -H "Authorization: Bearer $VOMO_API_TOKEN"
⚠️ Spec gap (audit #25): The GET /organizations endpoint’s summary describes returning “organizations in your organizations family,” but the spec’s example shows a single Organization object — not an array of Organizations. The pagination semantics aren’t clearly documented.Confirm against the live API whether this endpoint returns a single Organization (the parent), a paginated list of the family, or something else. The patterns below assume it returns the family hierarchy in some form.
For partner integrations that need to know the full organization family their token can access, this is the entry point.
JavaScript
async function getOrganizationFamily() {
  const response = await fetch(
    'https://api.vomo.org/v1/organizations',
    { headers: { Authorization: `Bearer ${token}` } }
  );

  if (!response.ok) throw new Error(`Failed: ${response.status}`);

  const result = await response.json();
  return result.data;
}
If the response shape is “the parent Organization with its children listed,” walk the child_organizations array. If it’s “a list of organizations the token can access,” paginate the result.

Fetching a single organization

cURL
curl https://api.vomo.org/v1/organizations/12345 \
  -H "Authorization: Bearer $VOMO_API_TOKEN"
Returns the Organization with full detail, including its parent and child organization arrays.
JavaScript
async function getOrganization(orgId) {
  const response = await fetch(
    `https://api.vomo.org/v1/organizations/${orgId}`,
    { headers: { Authorization: `Bearer ${token}` } }
  );

  if (response.status === 404) return null;
  if (!response.ok) throw new Error(`Failed: ${response.status}`);

  const result = await response.json();
  return parseOrganization(result.data);
}
Useful when you have a specific Organization ID (from a Project’s organization_id, from a previous family fetch, etc.) and need the full record.

Common workflows

Map child organizations for routing

For partner integrations that route data based on which org within the family it belongs to:
JavaScript
async function buildOrgRoutingMap() {
  const family = await getOrganizationFamily();
  const routingMap = new Map();

  // Map by slug for easy lookup
  function mapOrg(org) {
    routingMap.set(org.slug, {
      id: org.id,
      name: org.name,
      slug: org.slug,
      monikers: {
        groups: org.groups_moniker,
        project: org.project_moniker,
        campaign: org.campaign_moniker,
      },
    });

    for (const child of org.child_organizations ?? []) {
      mapOrg(child);
    }
  }

  mapOrg(family);
  return routingMap;
}

// Usage
const routingMap = await buildOrgRoutingMap();
const orgInfo = routingMap.get('gotham-food-bank');
The slug-based lookup makes routing on project.organization_slug straightforward.

Display Organization monikers consistently

For UIs that display Organization-specific content:
JavaScript
function getOrgLabel(org, kind) {
  switch (kind) {
    case 'group':
      return org.groups_moniker ?? 'Group';
    case 'project':
      return org.project_moniker ?? 'Project';
    case 'campaign':
      return org.campaign_moniker ?? 'Campaign';
    default:
      return capitalize(kind);
  }
}

// Usage
const projectLabel = getOrgLabel(currentOrg, 'project');
// e.g., "Event" for orgs that customize
A customer that calls their Projects “Events” gets to see “Events” everywhere in your integration.

Aggregate across the family vs. filter to one org

For reporting integrations:
JavaScript
// Aggregate across the entire family (default token scope)
async function totalActiveProjectsAcrossFamily() {
  const params = new URLSearchParams({ active: 'true', published: 'true' });
  const all = await paginate(`https://api.vomo.org/v1/projects?${params}`);
  return all.length;
}

// Filter to one specific org
async function activeProjectsForOrg(orgSlug) {
  const params = new URLSearchParams({
    active: 'true',
    published: 'true',
    org_slug: orgSlug,
  });
  return paginate(`https://api.vomo.org/v1/projects?${params}`);
}

// Filter to multiple specific orgs
async function activeProjectsForOrgs(orgSlugs) {
  const params = new URLSearchParams({
    active: 'true',
    published: 'true',
    org_slug: orgSlugs.join(','),
  });
  return paginate(`https://api.vomo.org/v1/projects?${params}`);
}
The org_slug parameter on Project and Campaign endpoints is the canonical way to filter — comma-separated lists are supported.

Detect the token’s “home” organization

The Organization the API token was issued for is typically the parent. To detect it programmatically:
JavaScript
async function getHomeOrganization() {
  const family = await getOrganizationFamily();
  // If the family response returns a single Organization, that's the home
  // If it returns a hierarchy, the root (no parent_organizations) is the home
  if (Array.isArray(family.parent_organizations) && family.parent_organizations.length === 0) {
    return family;
  }
  // ...otherwise navigate up to the topmost org
  return family;
}
Useful for displaying “you’re integrated with [Home Org Name]” in your partner UI.

ID, slug, and the family

A few practical points about Organization identifiers:
IdentifierWhen to use
id (integer)Direct API references — GET /organizations/{id}
slug (string)Filter parameters — ?org_slug=wayne-foundation
name (string)Display only — never used as a key
The slug is human-readable and stable across the Organization’s lifetime; the ID is the numeric primary key. Both are stable, but slugs are easier for humans to work with (and easier to communicate via documentation or settings UIs).

Filtering across multiple orgs

The org_slug query parameter on Project and Campaign endpoints accepts comma-separated values:
GET /projects?org_slug=gotham-outreach,wayne-manor-programs
This returns Projects belonging to either of the two child organizations. Useful for partner integrations whose customer wants a subset of their family included in a specific workflow.

What this means for multi-org customers

Partner integrations serving customers with parent-child organization structures should:
PracticeDescription
Surface the family structure in your UILet the customer see what organizations the integration has access to
Allow per-org configuration where it makes senseDifferent child orgs may have different sync destinations, templates, or rules
Use slug-based filtering for routingEasier to read in code and configuration than numeric IDs
Honor monikers in user-facing displaysThe customer customized the labels for a reason
Don’t assume one-token-equals-one-orgMulti-org customers’ single token can span many organizations
The integration’s design should accommodate single-org customers (most common) without making things complex, while also being able to handle multi-org families when they appear.

A reference Organizations client

Given the spec gaps around the Organization shape, the reference client treats fields defensively:
JavaScript
class VomoOrganizations {
  constructor({ token }) {
    this.token = token;
    this.baseUrl = 'https://api.vomo.org/v1';
  }

  async getFamily() {
    const response = await this._fetch(`${this.baseUrl}/organizations`);
    if (!response.ok) throw new Error(`Failed: ${response.status}`);
    const result = await response.json();
    return this._parseOrg(result.data);
  }

  async getById(orgId) {
    const response = await this._fetch(`${this.baseUrl}/organizations/${orgId}`);
    if (response.status === 404) return null;
    if (!response.ok) throw new Error(`Failed: ${response.status}`);
    const result = await response.json();
    return this._parseOrg(result.data);
  }

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

  _parseOrg(raw) {
    return {
      id: raw.id,
      name: raw.name,
      slug: raw.slug,
      type: raw.type,
      description: raw.description ?? null,
      email: raw.email,
      phone: raw.phone,
      website: raw.website,
      taxNumber: raw.tax_number ?? null,
      orgSize: raw.org_size,
      backgroundCheckExpiration: raw.background_check_expiration,
      hubExperience: raw.hub_experience,
      invitationToken: raw.invitation_token,
      address: raw.address ?? null,
      logo: raw.logo ? this._parseLogo(raw.logo) : null,
      monikers: {
        groups: raw.groups_moniker ?? 'Group',
        project: raw.project_moniker ?? 'Project',
        campaign: raw.campaign_moniker ?? 'Campaign',
      },
      createdAt: raw.created_at ? new Date(raw.created_at) : null,
      updatedAt: raw.updated_at ? new Date(raw.updated_at) : null,
      deletedAt: raw.deleted_at ? new Date(raw.deleted_at) : null,
      childOrganizations: (raw.child_organizations ?? []).map(this._parseOrg.bind(this)),
      parentOrganizations: (raw.parent_organizations ?? []).map(this._parseOrg.bind(this)),
    };
  }

  _parseLogo(raw) {
    return {
      id: raw.id,
      type: raw.type,
      urls: raw.urls ?? {},
      mediableId: raw.mediable_id,
      mediableType: raw.mediable_type,
    };
  }
}
The ?? null and ?? defaults throughout reflect the spec gap reality — fields may be missing or have unexpected shapes, and the parser handles both gracefully.

Where to go next

Campaigns

The Campaign resource — Campaigns are owned by specific organizations within the family.

Groups

Groups belong to specific organizations within the family.

Projects and Project Dates

Projects are attributed to organizations via organization_slug.

The Volunteer Data Model

The full data model context for organizations.
Last modified on May 22, 2026