Get startedQuickstart

Quickstart

Create an API key and make your first MCP call in a few minutes.

This guide walks you through getting an API key and sending your first two requests to the Zoop MCP server — a tools/list to confirm the connection works, then a customers.search call to fetch real data.

What you need: a Zoop account with owner-level access and a terminal with curl.

Base URL: every example uses https://app.zoop.example as a placeholder. Replace it with your actual Zoop URL. If you are unsure what that is, fetch GET /.well-known/oauth-protected-resource — the resource field is the canonical base URL for your environment.


Background: what the MCP server is

Zoop exposes a Model Context Protocol (MCP) server at POST /api/mcp. MCP is an open standard for letting AI agents and tools talk to services like Zoop. Under the hood it uses JSON-RPC 2.0 — a convention where every request is a JSON object with four fields (jsonrpc, id, method, params) and every response is a JSON object with either a result or an error.

You do not need to know the full spec to follow this guide — the examples below are complete, copy-paste calls.


Step 1: create an API key

Open settings

In Zoop, go to Settings → API & MCP. You need owner role to reach this page.

Settings API & MCP page showing an existing user key with scopes and the New API key button
Settings API & MCP page showing an existing user key with scopes and the New API key button

Create a user key

Click New API key. When prompted for the key type, choose User key — these have the prefix zoop_uk_. A user key carries your identity, which Zoop uses to record who created or updated a record (the created_by / updated_by fields). A tenant key (zoop_tk_) works for read-only tools and some write tools, but cannot call any tool that stamps a user actor on the record.

Next, select scopes — scopes are permissions that control which tools your key can call. For this guide, enable at least read:customers.

Copy the key immediately

The key is shown once in plain text. Zoop only stores a hashed version — if you close the dialog without copying the key, you will need to revoke it and create a new one.

Store it in an environment variable rather than pasting it directly into source code:

export ZOOP_API_KEY="zoop_uk_<the rest of your key>"

Step 2: confirm the connection with tools/list

tools/list is a built-in MCP method that returns every tool your key has permission to call. It is a safe first call because it does not read or write any of your data — it just proves your key is valid and the server is reachable.

Send the request with curl:

curl -X POST https://app.zoop.example/api/mcp \
  -H "Authorization: Bearer $ZOOP_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

What the headers do:

  • Authorization: Bearer $ZOOP_API_KEY — sends your API key as the credential. There is no separate login step; Zoop reads the key directly from this header.
  • Content-Type: application/json — tells the server the request body is JSON.
  • Accept: application/json, text/event-stream — the MCP server uses a streamable HTTP transport; this header is required or the server will reject the request.

A successful response looks like this (truncated):

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "customers.search",
        "description": "Search customers by name, phone, tag, or status."
      }
    ]
  }
}

If you see a 401 error, the key is invalid, expired, or revoked. The most common cause is a missing prefix — make sure you copied the full key including zoop_uk_. Also confirm the environment variable is set in the same shell session where you are running curl. See errors for the full error shape.


Step 3: search for a customer

Now call an actual Zoop tool. customers.search lets you look up customers by name, phone, tag, or status. It requires the read:customers scope you enabled in step 1.

To call any tool, set method to tools/call and put the tool name and its arguments in params:

curl -X POST https://app.zoop.example/api/mcp \
  -H "Authorization: Bearer $ZOOP_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "customers.search",
      "arguments": {
        "q": "Henderson"
      }
    }
  }'

A successful response returns a list of matching customers plus a pagination cursor:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{"rows":[{"id":"<uuid>","display_name":"Henderson, Sarah","customer_type":"individual","status":"active"}],"hasMore":false}"
      }
    ]
  }
}

The content[0].text field is a JSON string — you need to parse it to get the structured data. Inside it, rows holds the matching customers. If hasMore is true, there are more results on the next page; pass the value of nextCursor as cursor in your next call to continue paging.

If you get an insufficient_scope error, the key was created without the read:customers scope. You cannot add scopes to an existing key — revoke it, create a new one, and make sure to check read:customers during setup.


What's next