# Contacts

> Keep each project's phonebook in step with your own systems, by number.

Each project has a phonebook: the people it calls, one entry per number, with the details an agent
may say about them. It is the phonebook the console shows, and what it holds reaches two places — a
campaign started from it in the console, and an inbound call whose agent
[fills its fields from the phonebook](/guides/inbound-calls#fill-fields-from-the-phonebook).

Reading it needs `contacts:read`; changing it needs `contacts:write` and a **live key**, because these
are real people. A test key reads nobody. A phonebook belongs to its whole project, so a key limited
to some agents cannot reach it.

## Add someone

**curl**

```sh
#!/bin/sh
# Add someone to the phonebook. With a live key: the phonebook holds real people.
curl -sS --fail-with-body -X POST "https://api.aigently.ai/v1/contacts" \
  -H "Authorization: Bearer $AIGENTLY_API_KEY" \
  --json '{
  "project_id": "0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5e",
  "phone": "+12025550131",
  "name": "Sara Haddad",
  "attributes": {
    "first_name": "Sara",
    "member_since": "2023"
  },
  "timezone": "America/New_York"
}'
```

**JavaScript**

```js
// Add someone to the phonebook. With a live key: the phonebook holds real people.
const response = await fetch("https://api.aigently.ai/v1/contacts", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.AIGENTLY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "project_id": "0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5e",
    "phone": "+12025550131",
    "name": "Sara Haddad",
    "attributes": {
      "first_name": "Sara",
      "member_since": "2023"
    },
    "timezone": "America/New_York"
  }),
});
const answer = await response.json();
if (!response.ok) throw new Error(`${answer.code}: ${answer.detail}`);
console.log(answer);
```

**Python**

```python
# Add someone to the phonebook. With a live key: the phonebook holds real people.
# pip install httpx
import os

import httpx

response = httpx.post(
    "https://api.aigently.ai/v1/contacts",
    headers={
        "Authorization": f"Bearer {os.environ['AIGENTLY_API_KEY']}",
    },
    json={
        "project_id": "0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5e",
        "phone": "+12025550131",
        "name": "Sara Haddad",
        "attributes": {
            "first_name": "Sara",
            "member_since": "2023",
        },
        "timezone": "America/New_York",
    },
)
if response.is_error:
    raise SystemExit(response.text)
print(response.json())
```

**Go**

```go
// Add someone to the phonebook. With a live key: the phonebook holds real people.
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	payload := []byte(`{
  "project_id": "0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5e",
  "phone": "+12025550131",
  "name": "Sara Haddad",
  "attributes": {
    "first_name": "Sara",
    "member_since": "2023"
  },
  "timezone": "America/New_York"
}`)
	request, err := http.NewRequest("POST", "https://api.aigently.ai/v1/contacts", bytes.NewReader(payload))
	if err != nil {
		panic(err)
	}
	request.Header.Set("Authorization", "Bearer "+os.Getenv("AIGENTLY_API_KEY"))
	request.Header.Set("Content-Type", "application/json")
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		panic(err)
	}
	defer response.Body.Close()
	body, _ := io.ReadAll(response.Body)
	if response.StatusCode >= 400 {
		fmt.Fprintln(os.Stderr, string(body))
		os.Exit(1)
	}
	fmt.Println(string(body))
}
```

**Java**

```java
// Add someone to the phonebook. With a live key: the phonebook holds real people.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Main {
    public static void main(String[] args) throws Exception {
        String body = """
            {
              "project_id": "0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5e",
              "phone": "+12025550131",
              "name": "Sara Haddad",
              "attributes": {
                "first_name": "Sara",
                "member_since": "2023"
              },
              "timezone": "America/New_York"
            }
            """;
        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.aigently.ai/v1/contacts"))
            .header("Authorization", "Bearer " + System.getenv("AIGENTLY_API_KEY"))
            .header("Content-Type", "application/json")
            .method("POST", HttpRequest.BodyPublishers.ofString(body))
            .build();
        // HTTP/1.1: on a plain-http address Java's default asks to upgrade, which not every
        // server allows.
        HttpClient client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build();
        HttpResponse<String> response =
            client.send(request, HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() >= 400) {
            System.err.println(response.body());
            System.exit(1);
        }
        System.out.println(response.body());
    }
}
```

**C#**

```csharp
// Add someone to the phonebook. With a live key: the phonebook holds real people.
using System.Net.Http.Headers;
using System.Text;

using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("AIGENTLY_API_KEY"));
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.aigently.ai/v1/contacts")
{
    Content = new StringContent(
        """
        {
          "project_id": "0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5e",
          "phone": "+12025550131",
          "name": "Sara Haddad",
          "attributes": {
            "first_name": "Sara",
            "member_since": "2023"
          },
          "timezone": "America/New_York"
        }
        """,
        Encoding.UTF8,
        "application/json"),
};
var response = await client.SendAsync(request);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
    Console.Error.WriteLine(body);
    return 1;
}
Console.WriteLine(body);
return 0;
```

**PHP**

```php
<?php
// Add someone to the phonebook. With a live key: the phonebook holds real people.
$curl = curl_init("https://api.aigently.ai/v1/contacts");
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("AIGENTLY_API_KEY"),
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "project_id" => "0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5e",
        "phone" => "+12025550131",
        "name" => "Sara Haddad",
        "attributes" => [
            "first_name" => "Sara",
            "member_since" => "2023",
        ],
        "timezone" => "America/New_York",
    ]),
]);
$body = curl_exec($curl);
if (curl_getinfo($curl, CURLINFO_RESPONSE_CODE) >= 400) {
    fwrite(STDERR, $body . "\n");
    exit(1);
}
echo $body, "\n";
```

| Field | What it is |
|---|---|
| `phone` | Their number, in international format. One entry per number in a project. |
| `name` | What the console calls them. The agent never says it — it says what its placeholders take. |
| `attributes` | What an agent may say about them. Its `{{placeholders}}` take these by name: `first_name` fills `{{first_name}}`. Kept as text — `3` as `"3"`, `true` as `"yes"`. |
| `timezone` | Where they are, like `Asia/Riyadh`: a campaign's calling hours are read there. |

A number already in the project's phonebook is `409 contact_exists`. To add or update many people
at once, [import them](#import-a-list).

## Find someone, and change them

**curl**

```sh
#!/bin/sh
# Find someone in the phonebook by their number
curl -sS --fail-with-body -X GET "https://api.aigently.ai/v1/contacts?phone=+12025550131" \
  -H "Authorization: Bearer $AIGENTLY_API_KEY"
```

**JavaScript**

```js
// Find someone in the phonebook by their number
const response = await fetch("https://api.aigently.ai/v1/contacts?phone=+12025550131", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.AIGENTLY_API_KEY}`,
  },
});
const answer = await response.json();
if (!response.ok) throw new Error(`${answer.code}: ${answer.detail}`);
console.log(answer);
```

**Python**

```python
# Find someone in the phonebook by their number
# pip install httpx
import os

import httpx

response = httpx.get(
    "https://api.aigently.ai/v1/contacts",
    headers={
        "Authorization": f"Bearer {os.environ['AIGENTLY_API_KEY']}",
    },
    params={
        "phone": "+12025550131",
    },
)
if response.is_error:
    raise SystemExit(response.text)
print(response.json())
```

**Go**

```go
// Find someone in the phonebook by their number
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	request, err := http.NewRequest("GET", "https://api.aigently.ai/v1/contacts?phone=+12025550131", nil)
	if err != nil {
		panic(err)
	}
	request.Header.Set("Authorization", "Bearer "+os.Getenv("AIGENTLY_API_KEY"))
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		panic(err)
	}
	defer response.Body.Close()
	body, _ := io.ReadAll(response.Body)
	if response.StatusCode >= 400 {
		fmt.Fprintln(os.Stderr, string(body))
		os.Exit(1)
	}
	fmt.Println(string(body))
}
```

**Java**

```java
// Find someone in the phonebook by their number
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Main {
    public static void main(String[] args) throws Exception {
        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.aigently.ai/v1/contacts?phone=+12025550131"))
            .header("Authorization", "Bearer " + System.getenv("AIGENTLY_API_KEY"))
            .method("GET", HttpRequest.BodyPublishers.noBody())
            .build();
        // HTTP/1.1: on a plain-http address Java's default asks to upgrade, which not every
        // server allows.
        HttpClient client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build();
        HttpResponse<String> response =
            client.send(request, HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() >= 400) {
            System.err.println(response.body());
            System.exit(1);
        }
        System.out.println(response.body());
    }
}
```

**C#**

```csharp
// Find someone in the phonebook by their number
using System.Net.Http.Headers;
using System.Text;

using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("AIGENTLY_API_KEY"));
var request = new HttpRequestMessage(HttpMethod.Get, "https://api.aigently.ai/v1/contacts?phone=+12025550131")
{
};
var response = await client.SendAsync(request);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
    Console.Error.WriteLine(body);
    return 1;
}
Console.WriteLine(body);
return 0;
```

**PHP**

```php
<?php
// Find someone in the phonebook by their number
$curl = curl_init("https://api.aigently.ai/v1/contacts?phone=+12025550131");
curl_setopt_array($curl, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("AIGENTLY_API_KEY"),
    ],
]);
$body = curl_exec($curl);
if (curl_getinfo($curl, CURLINFO_RESPONSE_CODE) >= 400) {
    fwrite(STDERR, $body . "\n");
    exit(1);
}
echo $body, "\n";
```

**curl**

```sh
#!/bin/sh
# Read a contact
curl -sS --fail-with-body -X GET "https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d" \
  -H "Authorization: Bearer $AIGENTLY_API_KEY"
```

**JavaScript**

```js
// Read a contact
const response = await fetch("https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.AIGENTLY_API_KEY}`,
  },
});
const answer = await response.json();
if (!response.ok) throw new Error(`${answer.code}: ${answer.detail}`);
console.log(answer);
```

**Python**

```python
# Read a contact
# pip install httpx
import os

import httpx

response = httpx.get(
    "https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d",
    headers={
        "Authorization": f"Bearer {os.environ['AIGENTLY_API_KEY']}",
    },
)
if response.is_error:
    raise SystemExit(response.text)
print(response.json())
```

**Go**

```go
// Read a contact
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	request, err := http.NewRequest("GET", "https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d", nil)
	if err != nil {
		panic(err)
	}
	request.Header.Set("Authorization", "Bearer "+os.Getenv("AIGENTLY_API_KEY"))
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		panic(err)
	}
	defer response.Body.Close()
	body, _ := io.ReadAll(response.Body)
	if response.StatusCode >= 400 {
		fmt.Fprintln(os.Stderr, string(body))
		os.Exit(1)
	}
	fmt.Println(string(body))
}
```

**Java**

```java
// Read a contact
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Main {
    public static void main(String[] args) throws Exception {
        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d"))
            .header("Authorization", "Bearer " + System.getenv("AIGENTLY_API_KEY"))
            .method("GET", HttpRequest.BodyPublishers.noBody())
            .build();
        // HTTP/1.1: on a plain-http address Java's default asks to upgrade, which not every
        // server allows.
        HttpClient client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build();
        HttpResponse<String> response =
            client.send(request, HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() >= 400) {
            System.err.println(response.body());
            System.exit(1);
        }
        System.out.println(response.body());
    }
}
```

**C#**

```csharp
// Read a contact
using System.Net.Http.Headers;
using System.Text;

using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("AIGENTLY_API_KEY"));
var request = new HttpRequestMessage(HttpMethod.Get, "https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d")
{
};
var response = await client.SendAsync(request);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
    Console.Error.WriteLine(body);
    return 1;
}
Console.WriteLine(body);
return 0;
```

**PHP**

```php
<?php
// Read a contact
$curl = curl_init("https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d");
curl_setopt_array($curl, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("AIGENTLY_API_KEY"),
    ],
]);
$body = curl_exec($curl);
if (curl_getinfo($curl, CURLINFO_RESPONSE_CODE) >= 400) {
    fwrite(STDERR, $body . "\n");
    exit(1);
}
echo $body, "\n";
```

**curl**

```sh
#!/bin/sh
# Change a contact. attributes is replaced whole: send every one they should have.
curl -sS --fail-with-body -X PATCH "https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d" \
  -H "Authorization: Bearer $AIGENTLY_API_KEY" \
  --json '{
  "attributes": {
    "first_name": "Sara",
    "member_since": "2021"
  }
}'
```

**JavaScript**

```js
// Change a contact. attributes is replaced whole: send every one they should have.
const response = await fetch("https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d", {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.AIGENTLY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "attributes": {
      "first_name": "Sara",
      "member_since": "2021"
    }
  }),
});
const answer = await response.json();
if (!response.ok) throw new Error(`${answer.code}: ${answer.detail}`);
console.log(answer);
```

**Python**

```python
# Change a contact. attributes is replaced whole: send every one they should have.
# pip install httpx
import os

import httpx

response = httpx.patch(
    "https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d",
    headers={
        "Authorization": f"Bearer {os.environ['AIGENTLY_API_KEY']}",
    },
    json={
        "attributes": {
            "first_name": "Sara",
            "member_since": "2021",
        },
    },
)
if response.is_error:
    raise SystemExit(response.text)
print(response.json())
```

**Go**

```go
// Change a contact. attributes is replaced whole: send every one they should have.
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	payload := []byte(`{
  "attributes": {
    "first_name": "Sara",
    "member_since": "2021"
  }
}`)
	request, err := http.NewRequest("PATCH", "https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d", bytes.NewReader(payload))
	if err != nil {
		panic(err)
	}
	request.Header.Set("Authorization", "Bearer "+os.Getenv("AIGENTLY_API_KEY"))
	request.Header.Set("Content-Type", "application/json")
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		panic(err)
	}
	defer response.Body.Close()
	body, _ := io.ReadAll(response.Body)
	if response.StatusCode >= 400 {
		fmt.Fprintln(os.Stderr, string(body))
		os.Exit(1)
	}
	fmt.Println(string(body))
}
```

**Java**

```java
// Change a contact. attributes is replaced whole: send every one they should have.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Main {
    public static void main(String[] args) throws Exception {
        String body = """
            {
              "attributes": {
                "first_name": "Sara",
                "member_since": "2021"
              }
            }
            """;
        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d"))
            .header("Authorization", "Bearer " + System.getenv("AIGENTLY_API_KEY"))
            .header("Content-Type", "application/json")
            .method("PATCH", HttpRequest.BodyPublishers.ofString(body))
            .build();
        // HTTP/1.1: on a plain-http address Java's default asks to upgrade, which not every
        // server allows.
        HttpClient client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build();
        HttpResponse<String> response =
            client.send(request, HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() >= 400) {
            System.err.println(response.body());
            System.exit(1);
        }
        System.out.println(response.body());
    }
}
```

**C#**

```csharp
// Change a contact. attributes is replaced whole: send every one they should have.
using System.Net.Http.Headers;
using System.Text;

using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("AIGENTLY_API_KEY"));
var request = new HttpRequestMessage(HttpMethod.Patch, "https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d")
{
    Content = new StringContent(
        """
        {
          "attributes": {
            "first_name": "Sara",
            "member_since": "2021"
          }
        }
        """,
        Encoding.UTF8,
        "application/json"),
};
var response = await client.SendAsync(request);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
    Console.Error.WriteLine(body);
    return 1;
}
Console.WriteLine(body);
return 0;
```

**PHP**

```php
<?php
// Change a contact. attributes is replaced whole: send every one they should have.
$curl = curl_init("https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d");
curl_setopt_array($curl, [
    CURLOPT_CUSTOMREQUEST => "PATCH",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("AIGENTLY_API_KEY"),
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "attributes" => [
            "first_name" => "Sara",
            "member_since" => "2021",
        ],
    ]),
]);
$body = curl_exec($curl);
if (curl_getinfo($curl, CURLINFO_RESPONSE_CODE) >= 400) {
    fwrite(STDERR, $body . "\n");
    exit(1);
}
echo $body, "\n";
```

A change keeps every field you do not send. `attributes` is replaced whole, so send all of them. A
campaign already made keeps the details it copied; the next campaign and the next call read the new
ones.

## Import a list

**curl**

```sh
#!/bin/sh
# Import a list into the phonebook. Matched by number: people already there are updated, so sending it again is safe.
curl -sS --fail-with-body -X POST "https://api.aigently.ai/v1/contacts/import" \
  -H "Authorization: Bearer $AIGENTLY_API_KEY" \
  --json '{
  "project_id": "0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5e",
  "contacts": [
    {
      "phone": "+12025550132",
      "name": "Omar Nasser",
      "attributes": {
        "first_name": "Omar"
      }
    },
    {
      "phone": "+12025550133",
      "name": "Lina Saleh",
      "attributes": {
        "first_name": "Lina"
      }
    }
  ]
}'
```

**JavaScript**

```js
// Import a list into the phonebook. Matched by number: people already there are updated, so sending it again is safe.
const response = await fetch("https://api.aigently.ai/v1/contacts/import", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.AIGENTLY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "project_id": "0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5e",
    "contacts": [
      {
        "phone": "+12025550132",
        "name": "Omar Nasser",
        "attributes": {
          "first_name": "Omar"
        }
      },
      {
        "phone": "+12025550133",
        "name": "Lina Saleh",
        "attributes": {
          "first_name": "Lina"
        }
      }
    ]
  }),
});
const answer = await response.json();
if (!response.ok) throw new Error(`${answer.code}: ${answer.detail}`);
console.log(answer);
```

**Python**

```python
# Import a list into the phonebook. Matched by number: people already there are updated, so sending it again is safe.
# pip install httpx
import os

import httpx

response = httpx.post(
    "https://api.aigently.ai/v1/contacts/import",
    headers={
        "Authorization": f"Bearer {os.environ['AIGENTLY_API_KEY']}",
    },
    json={
        "project_id": "0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5e",
        "contacts": [{"phone": "+12025550132", "name": "Omar Nasser", "attributes": {"first_name": "Omar"}}, {"phone": "+12025550133", "name": "Lina Saleh", "attributes": {"first_name": "Lina"}}],
    },
)
if response.is_error:
    raise SystemExit(response.text)
print(response.json())
```

**Go**

```go
// Import a list into the phonebook. Matched by number: people already there are updated, so sending it again is safe.
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	payload := []byte(`{
  "project_id": "0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5e",
  "contacts": [
    {
      "phone": "+12025550132",
      "name": "Omar Nasser",
      "attributes": {
        "first_name": "Omar"
      }
    },
    {
      "phone": "+12025550133",
      "name": "Lina Saleh",
      "attributes": {
        "first_name": "Lina"
      }
    }
  ]
}`)
	request, err := http.NewRequest("POST", "https://api.aigently.ai/v1/contacts/import", bytes.NewReader(payload))
	if err != nil {
		panic(err)
	}
	request.Header.Set("Authorization", "Bearer "+os.Getenv("AIGENTLY_API_KEY"))
	request.Header.Set("Content-Type", "application/json")
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		panic(err)
	}
	defer response.Body.Close()
	body, _ := io.ReadAll(response.Body)
	if response.StatusCode >= 400 {
		fmt.Fprintln(os.Stderr, string(body))
		os.Exit(1)
	}
	fmt.Println(string(body))
}
```

**Java**

```java
// Import a list into the phonebook. Matched by number: people already there are updated, so sending it again is safe.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Main {
    public static void main(String[] args) throws Exception {
        String body = """
            {
              "project_id": "0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5e",
              "contacts": [
                {
                  "phone": "+12025550132",
                  "name": "Omar Nasser",
                  "attributes": {
                    "first_name": "Omar"
                  }
                },
                {
                  "phone": "+12025550133",
                  "name": "Lina Saleh",
                  "attributes": {
                    "first_name": "Lina"
                  }
                }
              ]
            }
            """;
        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.aigently.ai/v1/contacts/import"))
            .header("Authorization", "Bearer " + System.getenv("AIGENTLY_API_KEY"))
            .header("Content-Type", "application/json")
            .method("POST", HttpRequest.BodyPublishers.ofString(body))
            .build();
        // HTTP/1.1: on a plain-http address Java's default asks to upgrade, which not every
        // server allows.
        HttpClient client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build();
        HttpResponse<String> response =
            client.send(request, HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() >= 400) {
            System.err.println(response.body());
            System.exit(1);
        }
        System.out.println(response.body());
    }
}
```

**C#**

```csharp
// Import a list into the phonebook. Matched by number: people already there are updated, so sending it again is safe.
using System.Net.Http.Headers;
using System.Text;

using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("AIGENTLY_API_KEY"));
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.aigently.ai/v1/contacts/import")
{
    Content = new StringContent(
        """
        {
          "project_id": "0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5e",
          "contacts": [
            {
              "phone": "+12025550132",
              "name": "Omar Nasser",
              "attributes": {
                "first_name": "Omar"
              }
            },
            {
              "phone": "+12025550133",
              "name": "Lina Saleh",
              "attributes": {
                "first_name": "Lina"
              }
            }
          ]
        }
        """,
        Encoding.UTF8,
        "application/json"),
};
var response = await client.SendAsync(request);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
    Console.Error.WriteLine(body);
    return 1;
}
Console.WriteLine(body);
return 0;
```

**PHP**

```php
<?php
// Import a list into the phonebook. Matched by number: people already there are updated, so sending it again is safe.
$curl = curl_init("https://api.aigently.ai/v1/contacts/import");
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("AIGENTLY_API_KEY"),
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "project_id" => "0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5e",
        "contacts" => [
            [
                "phone" => "+12025550132",
                "name" => "Omar Nasser",
                "attributes" => [
                    "first_name" => "Omar",
                ],
            ],
            [
                "phone" => "+12025550133",
                "name" => "Lina Saleh",
                "attributes" => [
                    "first_name" => "Lina",
                ],
            ],
        ],
    ]),
]);
$body = curl_exec($curl);
if (curl_getinfo($curl, CURLINFO_RESPONSE_CODE) >= 400) {
    fwrite(STDERR, $body . "\n");
    exit(1);
}
echo $body, "\n";
```

Up to 1,000 people a request, matched by number, with or without its `+`: `+966501234567` and
`966501234567` are one person. A number already there takes the new details, or
is left as it is and counted as `skipped` when you send `update_existing: false`. A row that does
not fit — not a number, not a time zone, the same number twice — is listed in `errors` by its place
in `contacts`, and the rest are taken, so sending a corrected list again is how you fix one.

## Delete someone

**curl**

```sh
#!/bin/sh
# Delete a contact. Calls already made to them stay where they are.
curl -sS --fail-with-body -X DELETE "https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d" \
  -H "Authorization: Bearer $AIGENTLY_API_KEY"
```

**JavaScript**

```js
// Delete a contact. Calls already made to them stay where they are.
const response = await fetch("https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d", {
  method: "DELETE",
  headers: {
    Authorization: `Bearer ${process.env.AIGENTLY_API_KEY}`,
  },
});
const answer = await response.json();
if (!response.ok) throw new Error(`${answer.code}: ${answer.detail}`);
console.log(answer);
```

**Python**

```python
# Delete a contact. Calls already made to them stay where they are.
# pip install httpx
import os

import httpx

response = httpx.delete(
    "https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d",
    headers={
        "Authorization": f"Bearer {os.environ['AIGENTLY_API_KEY']}",
    },
)
if response.is_error:
    raise SystemExit(response.text)
print(response.json())
```

**Go**

```go
// Delete a contact. Calls already made to them stay where they are.
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	request, err := http.NewRequest("DELETE", "https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d", nil)
	if err != nil {
		panic(err)
	}
	request.Header.Set("Authorization", "Bearer "+os.Getenv("AIGENTLY_API_KEY"))
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		panic(err)
	}
	defer response.Body.Close()
	body, _ := io.ReadAll(response.Body)
	if response.StatusCode >= 400 {
		fmt.Fprintln(os.Stderr, string(body))
		os.Exit(1)
	}
	fmt.Println(string(body))
}
```

**Java**

```java
// Delete a contact. Calls already made to them stay where they are.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Main {
    public static void main(String[] args) throws Exception {
        HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d"))
            .header("Authorization", "Bearer " + System.getenv("AIGENTLY_API_KEY"))
            .method("DELETE", HttpRequest.BodyPublishers.noBody())
            .build();
        // HTTP/1.1: on a plain-http address Java's default asks to upgrade, which not every
        // server allows.
        HttpClient client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build();
        HttpResponse<String> response =
            client.send(request, HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() >= 400) {
            System.err.println(response.body());
            System.exit(1);
        }
        System.out.println(response.body());
    }
}
```

**C#**

```csharp
// Delete a contact. Calls already made to them stay where they are.
using System.Net.Http.Headers;
using System.Text;

using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("AIGENTLY_API_KEY"));
var request = new HttpRequestMessage(HttpMethod.Delete, "https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d")
{
};
var response = await client.SendAsync(request);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
    Console.Error.WriteLine(body);
    return 1;
}
Console.WriteLine(body);
return 0;
```

**PHP**

```php
<?php
// Delete a contact. Calls already made to them stay where they are.
$curl = curl_init("https://api.aigently.ai/v1/contacts/5d7f9b1c-3e5a-4c7e-9b1d-3f5a7c9e1b3d");
curl_setopt_array($curl, [
    CURLOPT_CUSTOMREQUEST => "DELETE",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("AIGENTLY_API_KEY"),
    ],
]);
$body = curl_exec($curl);
if (curl_getinfo($curl, CURLINFO_RESPONSE_CODE) >= 400) {
    fwrite(STDERR, $body . "\n");
    exit(1);
}
echo $body, "\n";
```

They leave every group they were in. The calls already made to them stay where they are.
