> ## Documentation Index
> Fetch the complete documentation index at: https://docs.virtuous.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Get an API key and make a useful request against Virtuous CRM+ in under 5 minutes.

This page takes you from zero to a working CRM+ API call. You will create an API key in the Virtuous UI, confirm the key is valid by reading your organization profile, and run a Contact query — the foundational read operation behind most partner integrations.

If you need more depth on any step, the [Authentication](/crm/authentication) and [Make Your First API Call](/crm/first-api-call) pages cover the same ground with additional detail.

## Prerequisites

* Access to a Virtuous CRM+ organization with administrator permissions (you cannot create API keys without them).
* A terminal with `curl` available, or a Node.js environment if you prefer to follow along in JavaScript.
* A secrets manager or environment-variable mechanism for storing the API key — never commit it to source control.

***

## 1. Create an API Key

<Steps>
  <Step title="Sign in to Virtuous">
    Open your organization's Virtuous instance and sign in with an account that has administrator permissions.
  </Step>

  <Step title="Open API Keys settings">
    Navigate to **Settings → Integrations → API Keys**.
  </Step>

  <Step title="Create a new key">
    Click **Create a Key**, give it a descriptive name (typically the name of the integration you are building), choose the appropriate permission group, and save.
  </Step>

  <Step title="Copy the key immediately">
    The key is displayed once. Copy it to a secrets manager or environment variable. If you lose it, you must create a new one — Virtuous cannot show it again.
  </Step>
</Steps>

<Warning>
  API Keys are static credentials with a 15-year lifetime. Treat them like passwords. Store them in a secrets manager or environment variable — never in source code, version control, or client-side JavaScript. If a key is compromised, revoke it from **Settings → Integrations → API Keys** and create a replacement.
</Warning>

For OAuth-based authentication (used when your integration acts on behalf of a specific Virtuous user rather than as a service account), see the [Authentication](/crm/authentication) page.

***

## 2. Verify the key works

Send a request to `GET /api/Organization/Current` — it requires only auth and returns the current organization profile. A successful response confirms your token is valid and your network path to the API is working.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.virtuoussoftware.com/api/Organization/Current \
    -H "Authorization: Bearer YOUR_API_TOKEN"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://api.virtuoussoftware.com/api/Organization/Current',
    {
      headers: {
        Authorization: `Bearer ${process.env.VIRTUOUS_API_TOKEN}`,
      },
    }
  );

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

  const org = await response.json();
  console.log('Connected to:', org.organizationName);
  ```
</CodeGroup>

A successful response looks like:

```json theme={null}
{
  "organizationUserId": 67890,
  "organizationName": "The Human Fund",
  "organizationTimeZone": "US/Arizona",
  "organizationCulture": "en-US",
  "currentUserTimeZone": "US/Arizona",
  "isAdministrator": true,
  "isEnabled": true
}
```

<Check>
  If you received a `200 OK` and the organization name matches the Virtuous account you generated the key in, your credentials are working. Move on to the next step.
</Check>

If you received a `401`, the `Authorization` header is missing, malformed, or the key has been revoked. Re-check the header format (`Bearer YOUR_API_TOKEN`, with the literal word `Bearer` followed by a single space) and confirm the key in the Virtuous UI is still active. See [Error Handling](/crm/error-handling) for full status code coverage.

***

## 3. Run your first Contact query

The Contact query endpoint is the workhorse read for most partner integrations — it powers incremental sync, donor lookups, and any workflow that retrieves Contact records by filter. The minimal call below returns the first ten Contacts sorted by last name.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.virtuoussoftware.com/api/Contact/Query \
    -H "Authorization: Bearer YOUR_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "groups": [],
      "sortBy": "lastName",
      "descending": false,
      "skip": 0,
      "take": 10
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://api.virtuoussoftware.com/api/Contact/Query',
    {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.VIRTUOUS_API_TOKEN}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        groups: [],
        sortBy: 'lastName',
        descending: false,
        skip: 0,
        take: 10,
      }),
    }
  );

  const page = await response.json();
  console.log(`Found ${page.total} contacts. Showing first ${page.list.length}:`);
  for (const contact of page.list) {
    console.log(`- ${contact.id}: ${contact.name}`);
  }
  ```
</CodeGroup>

The response uses the standard CRM+ pagination envelope:

```json theme={null}
{
  "list": [
    { "id": 4821, "name": "Wayne, Bruce" },
    { "id": 4822, "name": "Prince, Diana" }
  ],
  "total": 4823,
  "skip": 0,
  "take": 10
}
```

`list` holds the records returned on this page. `total` is the total count across all pages. To advance through the full result set, increment `skip` by `take` on each subsequent request — see [Pagination and Filtering](/crm/pagination) for the full loop pattern.

<Note>
  `POST /api/Contact/Query` accepts a structured filter object, not a free-text search string. The empty `groups: []` value above returns all Contacts. To filter by specific fields (modification date, tags, custom field values), populate `groups` with filter clauses. The available fields and operators are returned by `GET /api/Contact/QueryOptions`.
</Note>

***

## 4. Where to go from here

You now have a working API key, verified authentication, and a pagination-aware read against the Contact resource. The next pages cover the patterns every partner integration needs:

<CardGroup cols={2}>
  <Card title="Make Your First API Call" icon="terminal" href="/crm/first-api-call">
    A longer walkthrough that covers headers, response inspection, and common first-call failures.
  </Card>

  <Card title="Authentication" icon="key" href="/crm/authentication">
    Full coverage of API Keys and OAuth, including refresh, rotation, and two-factor flows.
  </Card>

  <Card title="Pagination and Filtering" icon="list" href="/crm/pagination">
    Iterate large result sets safely and use `Contact/Query` filters effectively.
  </Card>

  <Card title="Error Handling" icon="circle-exclamation" href="/crm/error-handling">
    The error response shape, status codes, and defensive patterns for production integrations.
  </Card>

  <Card title="Create a Contact" icon="user-plus" href="/crm/workflows/create-a-contact">
    The first write workflow — and why most partners should use the transaction endpoint.
  </Card>

  <Card title="Sync External Donations" icon="arrow-right-arrow-left" href="/crm/workflows/sync-external-donations">
    The canonical recipe for pushing Gifts from your platform into Virtuous.
  </Card>
</CardGroup>
