Skip to content
Scalekit Docs
Talk to an Engineer Dashboard

Connect AI agents to Close

Scalekit connector
Open markdown

The Close connector lets your AI agent act in each user's Close account. Each user signs in to Close once, and Scalekit stores and refreshes their tokens, so your agent never handles credentials. It comes with 103 tools.

Tools
103
What they doRead · write · destructive
46 · 39 · 1846 read39 write18 destructive
Users sign in with
OAuth app
Scalekit's or your own

What you can do

  • Manage leads: create, update, search, merge, and delete leads with their contacts, addresses, and custom fields
  • Track opportunities: create and update deals with status, value, and confidence, and manage pipelines
  • Log activities: record calls, emails, SMS, and notes on leads, and send emails and SMS
  • Manage tasks: create, assign, complete, and bulk-update tasks with due dates
  • Run sequences: build scheduled email and call sequences and enroll, pause, or remove contacts
  • Save searches and bulk edit: create Smart Views, export matching leads, and bulk edit or delete them

Setup

  1. Install the SDK

    Terminal window
    npm install @scalekit-sdk/node dotenv
  2. Set your credentials

    Add your Scalekit credentials to your .env file. Find values in app.scalekit.com > Developers > API Credentials.

    .env
    SCALEKIT_ENVIRONMENT_URL=<your-environment-url>
    SCALEKIT_CLIENT_ID=<your-client-id>
    SCALEKIT_CLIENT_SECRET=<your-client-secret>
  3. Create the Close connection

    In AgentKit > Connections, create a Close connection. The name you give it is the connection_name your code passes. See Configure connections.

    Scalekit credentials are available for Close, so you don't need to register an OAuth app. To show your own app on the consent screen, use your own credentials instead.

    Use your own OAuth app

    Register your Scalekit environment with the Close connector so Scalekit handles the OAuth flow and token lifecycle for you. The connection name you create will be used to identify and invoke the connection programmatically.

    1. Create a Close OAuth app

      • Sign in to Close and go to Settings → Developer → OAuth Apps.
      • Click Create New OAuth App.
      • Enter an app name and description.
      • In the Redirect URIs field, paste the redirect URI from Scalekit (see next step — you can come back to add it).

      • Copy your Client ID and Client Secret from the app detail page.
    2. Set up the connection in Scalekit

      • In Scalekit dashboard, go to AgentKit > Connections > Create Connection.
      • Find Close and click Create.
      • Copy the Redirect URI shown — it looks like: https://<SCALEKIT_ENVIRONMENT_URL>/sso/v1/oauth/<CONNECTION_ID>/callback
      • Note the Connection name (e.g., close) — use this as connection_name in your code.

      • Return to your Close OAuth app and add the redirect URI you copied.
      • Back in Scalekit, enter your Client ID and Client Secret. Scopes are granted automatically by Close — no additional scope configuration is needed.
      • Click Save.
    3. Add a connected account

      Via dashboard (for testing)

      • In the connection page, click the Connected Accounts tab → Add account.
      • Enter a User ID and click Save. You will be redirected to Close to authorize access.

      Via API (for production)

      const { link } = await scalekit.actions.getAuthorizationLink({
      connectionName: 'close',
      identifier: 'user_123',
      });
      // Redirect your user to `link` to authorize access
      console.log('Authorize at:', link);
  4. Authorize a user and make your first call

    quickstart.mts
    import { ScalekitClient } from '@scalekit-sdk/node'
    import 'dotenv/config'
    import { createInterface } from 'node:readline/promises'
    const scalekit = new ScalekitClient(
    process.env.SCALEKIT_ENVIRONMENT_URL,
    process.env.SCALEKIT_CLIENT_ID,
    process.env.SCALEKIT_CLIENT_SECRET,
    )
    const actions = scalekit.actions
    const connector = 'close'
    const identifier = 'user_123'
    // Generate an authorization link for the user
    const { link } = await actions.getAuthorizationLink({ connectionName: connector, identifier })
    console.log('Authorize Close:', link)
    const rl = createInterface({ input: process.stdin, output: process.stdout })
    await rl.question('Press Enter after authorizing...')
    rl.close()
    // Make your first call
    const result = await actions.executeTool({
    connector,
    identifier,
    toolName: 'close_activities_list',
    toolInput: {},
    })
    console.log(result)
    Terminal window
    npx tsx quickstart.mts

    Each user signs in once. See Authorize a user for the full flow and statuses.

Tools

Pass the exact name to execute_tool
Try in PlaygroundRequest a tool
  • close_activities_listList all activity types for a lead in Close (calls, emails, notes, SMS, etc.).Read-only

    List Activities

    List all activity types for a lead in Close (calls, emails, notes, SMS, etc.).

    Inputs

    _fieldsstring
    Comma-separated list of fields to return.
    _limitinteger
    Maximum number of results to return.
    _order_bystring
    Sort field. Default: date_created.
    _skipinteger
    Number of results to skip (offset).
    _typestring
    Activity type: Note, Call, Email, Sms, etc.
    contact_idstring
    Filter by contact ID.
    lead_idstring
    Filter by lead ID.
    user_idstring
    Filter by user ID.
  • close_call_getRetrieve a single call activity by ID.Read-only

    Get Call

    Retrieve a single call activity by ID.

    Inputs

    call_idstringrequired
    ID of the call activity.
  • close_calls_listList call activities in Close, optionally filtered by lead, contact, or user.Read-only

    List Calls

    List call activities in Close, optionally filtered by lead, contact, or user.

    Inputs

    _fieldsstring
    Comma-separated list of fields to return.
    _limitinteger
    Maximum number of results to return.
    _skipinteger
    Number of results to skip (offset).
    contact_idstring
    Filter by contact ID.
    lead_idstring
    Filter by lead ID.
    user_idstring
    Filter by user ID.
  • close_comment_getRetrieve a single comment by ID.Read-only

    Get Comment

    Retrieve a single comment by ID.

    Inputs

    comment_idstringrequired
    ID of the comment.
  • close_comment_threads_listList comment threads in Close, optionally filtered by thread ID or the object the thread is attached to.Read-only

    List Comment Threads

    List comment threads in Close, optionally filtered by thread ID or the object the thread is attached to.

    Inputs

    _limitinteger
    Maximum number of results to return. Defaults to 100.
    _skipinteger
    Number of results to skip (offset). Defaults to 0.
    idsstring
    Only return threads with these IDs (comma-separated).
    object_idsstring
    Only return threads attached to these object IDs (comma-separated), e.g. activity or note IDs.
  • close_comments_listList comments on an object.Read-only

    List Comments

    List comments on an object. Provide either object_id or thread_id to filter results.

    Inputs

    _fieldsstring
    Comma-separated list of fields to return.
    _limitinteger
    Maximum number of results to return.
    _skipinteger
    Number of results to skip (offset).
    object_idstring
    ID of the object to fetch comments for.
    thread_idstring
    ID of the comment thread.
  • close_contact_getRetrieve a single contact by ID from Close.Read-only

    Get Contact

    Retrieve a single contact by ID from Close.

    Inputs

    contact_idstringrequired
    ID of the contact.
    _fieldsstring
    Comma-separated list of fields to return.
  • close_contacts_listList contacts in Close, optionally filtered by lead.Read-only

    List Contacts

    List contacts in Close, optionally filtered by lead.

    Inputs

    _fieldsstring
    Comma-separated list of fields to return.
    _limitinteger
    Maximum number of results to return.
    _skipinteger
    Number of results to skip (offset).
    lead_idstring
    Filter contacts by lead ID.

Workflows

Proxy API call
// Fetch the authenticated user's profile
const me = await actions.request({
connectionName: 'close',
identifier: 'user_123',
path: '/api/v1/me/',
method: 'GET',
});
console.log(me);
Basic example — get the current user
const me = await actions.executeTool({
toolName: 'close_me_get',
connector: 'close',
identifier: 'user_123',
toolInput: {},
});
console.log(me);
Advanced enrichment workflow

This example shows a complete lead enrichment pipeline: find a lead, attach activities, enroll in a sequence, and track progress — all in one automated flow.

const opts = { connector: 'close', identifier: 'user_123' };
async function enrichAndEnrollLead(companyName: string, contactEmail: string) {
// 1. Find or create the lead
const searchResult = await actions.executeTool({
toolName: 'close_leads_list',
...opts,
toolInput: { query: companyName, _limit: 1 },
});
let leadId: string;
if (searchResult.data.length > 0) {
leadId = searchResult.data[0].id;
console.log(`Found existing lead: ${leadId}`);
} else {
const newLead = await actions.executeTool({
toolName: 'close_lead_create',
...opts,
toolInput: { name: companyName },
});
leadId = newLead.id;
console.log(`Created lead: ${leadId}`);
}
// 2. Create a contact on the lead
const contact = await actions.executeTool({
toolName: 'close_contact_create',
...opts,
toolInput: {
lead_id: leadId,
name: contactEmail.split('@')[0],
emails: JSON.stringify([{ email: contactEmail, type: 'office' }]),
},
});
console.log(`Created contact: ${contact.id}`);
// 3. Create an opportunity on the lead
const pipelines = await actions.executeTool({
toolName: 'close_pipelines_list',
...opts,
toolInput: {},
});
const pipeline = pipelines.data[0];
const activeStatus = pipeline.statuses.find((s: any) => s.type === 'active');
if (!activeStatus) throw new Error('No active status found in pipeline');
const opportunity = await actions.executeTool({
toolName: 'close_opportunity_create',
...opts,
toolInput: {
lead_id: leadId,
status_id: activeStatus.id,
value: 500000, // $5,000.00 in cents
value_currency: 'USD',
value_period: 'one_time',
confidence: 30,
},
});
console.log(`Created opportunity: ${opportunity.id} — $${opportunity.value / 100}`);
// 4. Log a note summarizing the enrichment
await actions.executeTool({
toolName: 'close_note_create',
...opts,
toolInput: {
lead_id: leadId,
note: `Lead enriched automatically. Contact ${contactEmail} created. Opportunity ${opportunity.id} opened.`,
},
});
// 5. Create a follow-up task
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
await actions.executeTool({
toolName: 'close_task_create',
...opts,
toolInput: {
lead_id: leadId,
text: `Follow up with ${contactEmail}`,
date: tomorrow.toISOString().split('T')[0],
},
});
// 6. Enroll the contact in a sequence (if sequences exist)
const sequences = await actions.executeTool({
toolName: 'close_sequences_list',
...opts,
toolInput: { _limit: 1 },
});
if (sequences.data.length > 0) {
const subscription = await actions.executeTool({
toolName: 'close_sequence_subscription_create',
...opts,
toolInput: {
contact_id: contact.id,
sequence_id: sequences.data[0].id,
},
});
console.log(`Enrolled contact in sequence. Subscription: ${subscription.id}`);
}
return { leadId, contactId: contact.id, opportunityId: opportunity.id };
}
// Run the enrichment
enrichAndEnrollLead('Acme Corp', 'jane@acme.com').then(console.log);
Required scopes

Close OAuth apps automatically include both required scopes — no manual scope selection is needed.

ScopeRequired for
all.full_accessEvery tool in this connector (leads, contacts, opportunities, tasks, notes, calls, emails, SMS, pipelines, sequences, webhooks, users, custom fields)
offline_accessAll tools — enables the refresh token so sessions persist beyond 1 hour