Inkbox

> # Documentation index
> Fetch the complete documentation index at: https://inkbox.ai/sitemap.xml
> Use this file to discover all available pages before exploring further.

---

# Contacts
description: Maintain a shared contact directory for your organization using the Inkbox SDK and CLI

---


# Contacts

Contacts are an organization-wide address book shared across every agent. Each contact aggregates a person or company — names, emails, phones, domains, addresses — and is visible to every agent in your org by default. Narrow that visibility per agent when you need to, or keep the wildcard and let every agent see every contact.

## Creating a contact

The minimum is one non-empty name field: `given_name`, `family_name`, `company_name`, or `preferred_name`. Emails and phones are validated client-side before the request leaves the SDK.

**Python**

```python
from inkbox.contacts.types import ContactEmail, ContactPhone

contact = inkbox.contacts.create(
    given_name="Jane",
    family_name="Doe",
    company_name="Acme Inc.",
    emails=[ContactEmail(value="jane@acme.example", label="work", is_primary=True)],
    phones=[ContactPhone(value="+15551234567", label="mobile")],
)
print(contact.id, contact.preferred_name)
```

**TypeScript**

```typescript
const contact = await inkbox.contacts.create({
    givenName: "Jane",
    familyName: "Doe",
    companyName: "Acme Inc.",
    emails: [{ value: "jane@acme.example", label: "work", isPrimary: true }],
    phones: [{ value: "+15551234567", label: "mobile" }],
});
console.log(contact.id, contact.preferredName);
```

**CLI**

```bash
inkbox contacts create --json '{"givenName":"Jane","familyName":"Doe","companyName":"Acme Inc.","emails":[{"value":"jane@acme.example","label":"work","isPrimary":true}],"phones":[{"value":"+15551234567","label":"mobile"}]}'
```

## Looking up by channel

When an email or call comes in, you usually want to know _who_ it's from before deciding how your agent should respond. `contacts.lookup` runs a reverse search by exact email, email substring, email domain, exact phone, or phone substring. Exactly one filter is required per call.

**Python**

```python
# Exact email
matches = inkbox.contacts.lookup(email="jane@acme.example")

# Substring on the email's local part
matches = inkbox.contacts.lookup(email_contains="jane")

# Everyone from this company domain
matches = inkbox.contacts.lookup(email_domain="acme.example")

# Exact phone (E.164)
matches = inkbox.contacts.lookup(phone="+15551234567")
```

**TypeScript**

```typescript
// Exact email
let matches = await inkbox.contacts.lookup({ email: "jane@acme.example" });

// Substring on the email's local part
matches = await inkbox.contacts.lookup({ emailContains: "jane" });

// Everyone from this company domain
matches = await inkbox.contacts.lookup({ emailDomain: "acme.example" });

// Exact phone (E.164)
matches = await inkbox.contacts.lookup({ phone: "+15551234567" });
```

**CLI**

```bash
inkbox contacts lookup --email jane@acme.example
inkbox contacts lookup --email-contains jane
inkbox contacts lookup --email-domain acme.example
inkbox contacts lookup --phone +15551234567
```

## Controlling visibility

Contacts created through the SDK default to the **wildcard** rule: every active agent in your org can see them. This matches how a shared address book usually works.

To narrow the visibility of a contact to a specific set of agents — for example, to keep customer contacts separate from vendor contacts — create the contact with an explicit `access_identity_ids` list, or revoke agents from an existing contact. Note that revoking an identity from a wildcard contact automatically fans the wildcard out into per-identity rows for every other active agent before dropping the revoked one, so the narrowing is atomic.

**Python**

```python
# Create a contact that only two agents can see
contact = inkbox.contacts.create(
    given_name="Alex",
    company_name="Secret Vendor Co.",
    access_identity_ids=[sales_agent.id, legal_agent.id],
)

# Grant another agent access to an existing contact
inkbox.contacts.access.grant(contact.id, identity_id=finance_agent.id)

# Revoke an agent (narrows a wildcard contact to explicit rows under the hood)
inkbox.contacts.access.revoke(contact.id, identity_id=sales_agent.id)

# Reset to wildcard (every active agent sees the contact again)
inkbox.contacts.access.grant(contact.id, wildcard=True)
```

**TypeScript**

```typescript
// Create a contact that only two agents can see
const contact = await inkbox.contacts.create({
    givenName: "Alex",
    companyName: "Secret Vendor Co.",
    accessIdentityIds: [salesAgent.id, legalAgent.id],
});

// Grant another agent access to an existing contact
await inkbox.contacts.access.grant(contact.id, { identityId: financeAgent.id });

// Revoke an agent (narrows a wildcard contact to explicit rows under the hood)
await inkbox.contacts.access.revoke(contact.id, salesAgent.id);

// Reset to wildcard (every active agent sees the contact again)
await inkbox.contacts.access.grant(contact.id, { wildcard: true });
```

**CLI**

```bash
# Grant an agent access
inkbox contacts access grant <contact-id> --identity <identity-id>

# Revoke an agent
inkbox contacts access revoke <contact-id> <identity-id>

# Reset to wildcard (all agents)
inkbox contacts access grant <contact-id> --wildcard
```

## Importing and exporting vCards

Round-trip contacts through the RFC 6350 vCard format to migrate from Apple Contacts, Google Contacts, LinkedIn exports, or any other address book. Bulk import handles up to 1000 cards per request with per-card isolation: one bad card doesn't poison the rest, and the response breaks down `created_count` / `error_count` plus per-card errors.

**Python**

```python
# Export a single contact as vCard text
vcf = inkbox.contacts.vcards.export_vcard(contact.id)
print(vcf)

# Bulk-import from a .vcf file
with open("contacts.vcf", "rb") as fh:
    result = inkbox.contacts.vcards.import_vcards(fh.read())
print(f"Created {result.created_count}, errors {result.error_count}")
for item in result.results:
    if item.status == "error":
        print(f"  card {item.index}: {item.error}")
```

**TypeScript**

```typescript
import { readFile } from "node:fs/promises";

// Export a single contact as vCard text
const vcf = await inkbox.contacts.vcards.export(contact.id);
console.log(vcf);

// Bulk-import from a .vcf file
const body = await readFile("contacts.vcf", "utf-8");
const result = await inkbox.contacts.vcards.import(body);
console.log(`Created ${result.createdCount}, errors ${result.errorCount}`);
for (const item of result.results) {
    if (item.status === "error") {
        console.log(`  card ${item.index}: ${item.error}`);
    }
}
```

**CLI**

```bash
# Export a single contact
inkbox contacts export <contact-id> > jane-doe.vcf

# Bulk-import from a .vcf file
inkbox contacts import contacts.vcf
```

## Related

- [Contacts API reference](/docs/api/contacts)
- [Access control reference](/docs/api/contacts/access)
- [vCard import/export reference](/docs/api/contacts/vcards)
