Skip to main content
The CRM+ API exposes a single production base URL. There is no separate sandbox environment, no staging URL, and no version prefix in the path. This page explains the implications for partner integrations and the patterns that work in production.

Base URL

PropertyValue
Base URLhttps://api.virtuoussoftware.com
ProtocolHTTPS only — plain HTTP requests fail
Version prefixNone — endpoints are versioned individually as they evolve
Every endpoint in this documentation is reached by appending its path to the base URL. For example, the endpoint listed in the reference as GET /api/Contact/{contactId} is called as:
GET https://api.virtuoussoftware.com/api/Contact/4821
A small number of endpoints use a /v2/ segment in the path (for example, GET /api/v2/Pledge/{pledgeId}). These are versioned in place rather than at the host level — the base URL is the same, and only the specific resource path includes the version segment.

Environments and sandbox access

There is one CRM+ API host. Every API Key — whether it belongs to a production nonprofit organization or to a Seeded Sandbox — connects to https://api.virtuoussoftware.com. The isolation between environments lives at the organization level, not the API host level: a given API Key resolves to exactly one Virtuous organization, and Virtuous organizations are independent of one another.
Calls made with a valid API Key affect that organization’s live data. A POST /api/Gift made against a production nonprofit’s organization creates a real Gift in that nonprofit’s database. There is no automatic rollback. Partner integrations must verify their write paths against a Seeded Sandbox before pointing them at customer data.

Seeded Sandbox

Virtuous provisions a Seeded Sandbox for partner integrations: a dedicated Virtuous organization pre-loaded with representative Contact, Gift, Campaign, and Designation data so partners can build and test against realistic records without touching customer data. The sandbox name typically ends with (Sandbox) to make it visually distinct in the UI and in GET /api/Organization/Current responses. To request a Seeded Sandbox, contact your Virtuous partner manager. The provisioning is handled by the Virtuous team — see Sandbox Access for the full request process, what data is seeded, and how the sandbox is refreshed. Practical guidance for using the sandbox effectively:
  • Use a separate API Key for the sandbox. Generate the sandbox’s API Key inside the sandbox organization itself. Treat it as a fully independent credential from any production customer’s key.
  • Verify which organization a credential belongs to. Call GET /api/Organization/Current after switching credentials — the organizationName should include (Sandbox) and isEnabled should be true. This prevents accidentally pointing a sandbox-targeted test run at a production customer.
  • Sandbox data is seeded but mutable. Writes made by your integration persist in the sandbox until the sandbox is refreshed. Each partner organization is provisioned a single shared sandbox, so coordinate test data among developers on your team — for example, prefix Contact names or external reference IDs with a developer initial — to avoid conflicting writes during parallel development.
  • Restrict early read-only testing to the sandbox. Even before your write paths are validated, exercise GET /api/Organization/Current, POST /api/Contact/Query, and similar read endpoints against the sandbox rather than a customer organization to avoid surfacing your in-progress integration in customer audit logs.

Credential scoping

An API Key is generated inside a specific Virtuous organization and grants access only to that organization’s data. The API Key is the unit of scoping — there is no header or query parameter that switches the target organization at request time when authenticating with an API Key. This has three implications for partner integrations:
  • One API Key per nonprofit customer. A partner integration that serves multiple nonprofit customers stores one API Key per customer and uses the correct key when calling the API on that customer’s behalf. You cannot use a single global API Key to access multiple customers’ data.
  • API Keys cannot be reused across products. A CRM+ API Key does not authenticate against the Raise API or the Volunteer API. If your integration spans products, store a separate credential for each.
  • Permission groups apply to the key. Each API Key is assigned a permission group at creation time. Two keys generated in the same organization can have different permission groups and therefore different access levels.

Verify which organization a credential belongs to

When onboarding a new nonprofit customer’s API Key into your integration, call GET /api/Organization/Current to confirm which Virtuous organization the credential resolves to. This is the fastest way to detect a misconfigured credential before it writes data to the wrong organization.
curl https://api.virtuoussoftware.com/api/Organization/Current \
  -H "Authorization: Bearer CUSTOMER_API_TOKEN"
A successful response:
{
  "organizationUserId": 67890,
  "organizationName": "The Human Fund",
  "organizationTimeZone": "US/Arizona",
  "organizationCulture": "en-US",
  "currentUserTimeZone": "US/Arizona",
  "isAdministrator": true,
  "isEnabled": true
}
Store the organizationUserId and organizationName alongside the API Key in your integration’s tenant configuration. Compare them on each onboarding refresh to detect when a customer rotates a key into a different organization.
isEnabled: false on the response indicates the organization is disabled in Virtuous (typically for billing or administrative reasons). Treat a disabled organization as a soft failure in your integration — surface a clear error to the customer rather than retrying.

Users with access to multiple organizations

OAuth-authenticated users may belong to more than one Virtuous organization — for example, a consultant working across several nonprofits. The CRM+ API provides three endpoints for working with the available organizations:
EndpointPurpose
GET /api/OrganizationList every organization the current user belongs to.
GET /api/Organization/CurrentRead the current active organization for this session.
PUT /api/Organization/SwitchChange the active organization for this session by organizationUserId.
PUT /api/Organization/Switch applies to the current session and is most relevant to OAuth-token integrations where a user interactively chooses a context. Server-to-server integrations using API Keys do not switch organizations — the API Key itself is bound to a single organization.

Example: list and select an organization

# List organizations the user belongs to
curl https://api.virtuoussoftware.com/api/Organization \
  -H "Authorization: Bearer OAUTH_ACCESS_TOKEN"

# Switch to a specific organization
curl -X PUT https://api.virtuoussoftware.com/api/Organization/Switch \
  -H "Authorization: Bearer OAUTH_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "organizationUserId": "12345" }'
A sample GET /api/Organization response:
[
  {
    "organizationUserId": 12345,
    "organizationName": "The Human Fund (Sandbox)",
    "organizationTimeZone": "US/Arizona",
    "organizationCulture": "en-US",
    "isAdministrator": true,
    "isEnabled": true
  },
  {
    "organizationUserId": 67890,
    "organizationName": "The Human Fund",
    "organizationTimeZone": "US/Arizona",
    "organizationCulture": "en-US",
    "isAdministrator": true,
    "isEnabled": true
  }
]

Multi-tenant integration pattern

A typical partner integration that serves many nonprofit customers stores credentials and metadata per tenant. A reasonable shape:
FieldSourcePurpose
Customer identifierYour systemInternal tenant ID.
API KeyGenerated in the customer’s Virtuous instanceCredential used for all CRM+ calls on that customer’s behalf.
organizationUserIdGET /api/Organization/Current at onboardingVerifies the credential resolves to the expected Virtuous organization.
organizationNameGET /api/Organization/Current at onboardingUsed in your UI to confirm the connection to the customer.
organizationTimeZoneGET /api/Organization/CurrentRequired to interpret date and time fields correctly — Virtuous dates are stored in the organization’s timezone, not UTC.
Permission group noteCaptured at onboardingUseful for diagnosing 403 responses later.
On every API call, look up the customer’s API Key from your secrets manager, attach it as the Bearer token, and route the response back to the originating tenant context.
Never log API Keys, even in test environments. Configure your logging library to redact the Authorization header on every outbound HTTP call. A single API Key leaked to a log aggregator counts as a credential compromise and requires rotation.

Cross-API base URLs

If your integration spans multiple Virtuous products, each product has its own base URL and its own credentials:
ProductBase URL
CRM+https://api.virtuoussoftware.com
Raisehttps://prod-api.raisedonors.com
Volunteer (VOMO)https://api.vomo.org/v1
Tokens are not interchangeable. A CRM+ API Key authenticates only against the CRM+ API. See Raise Authentication and Volunteer Authentication for details on those products.

Next steps

Make Your First API Call

Walk through the anatomy of a request and response, and learn to debug common first-call failures.

Authentication

Full coverage of API Keys, OAuth, refresh tokens, and the two-factor flow.

Error Handling

Status codes, error envelope shape, and defensive client patterns.

Rate Limits

The 5,000-requests-per-hour limit and how it interacts with multi-tenant integrations.
Last modified on June 4, 2026