curl --request POST \
--url https://app.manypi.com/api/integrations/migrations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"provider": "instantly",
"credentials": {
"api_key": "your-instantly-v2-key"
}
}
'import requests
url = "https://app.manypi.com/api/integrations/migrations"
payload = {
"provider": "instantly",
"credentials": { "api_key": "your-instantly-v2-key" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({provider: 'instantly', credentials: {api_key: 'your-instantly-v2-key'}})
};
fetch('https://app.manypi.com/api/integrations/migrations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.manypi.com/api/integrations/migrations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'provider' => 'instantly',
'credentials' => [
'api_key' => 'your-instantly-v2-key'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.manypi.com/api/integrations/migrations"
payload := strings.NewReader("{\n \"provider\": \"instantly\",\n \"credentials\": {\n \"api_key\": \"your-instantly-v2-key\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.manypi.com/api/integrations/migrations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"provider\": \"instantly\",\n \"credentials\": {\n \"api_key\": \"your-instantly-v2-key\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.manypi.com/api/integrations/migrations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"provider\": \"instantly\",\n \"credentials\": {\n \"api_key\": \"your-instantly-v2-key\"\n }\n}"
response = http.request(request)
puts response.read_body{
"job": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"provider": "<string>",
"account_label": "<string>",
"status": "scanned",
"scan": {
"label": "<string>",
"campaigns": [
{
"id": "<string>",
"name": "<string>",
"status": "<string>",
"emailSteps": 123,
"leads": 123
}
],
"leadsTotal": 123,
"blocklistTotal": 123,
"accounts": [
{
"email": "<string>",
"provider": "google",
"name": "<string>"
}
],
"notes": [
"<string>"
]
},
"options": {
"campaigns": [],
"recreateCampaigns": true,
"importLeads": true,
"doNotContact": true,
"enrollNotContacted": true,
"duplicates": "merge",
"asCustomers": false
},
"progress": {
"phase": "blocklist",
"campaignIndex": 123,
"campaignMap": {},
"counts": {
"suppressed": 123,
"campaigns": 123,
"steps": 123,
"created": 123,
"updated": 123,
"skipped": 123,
"overLimit": 123,
"failed": 123,
"enrolled": 123,
"customFields": 123
},
"warnings": [
"<string>"
],
"skippedSteps": {},
"leadsSeen": 123
},
"result": {},
"error": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"started_at": "2023-11-07T05:31:56Z",
"finished_at": "2023-11-07T05:31:56Z"
}
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}Scan another tool
Check a key for another outreach tool and scan that account, before anything is imported. Opens an import in status scanned that holds the scan; POST /api/integrations/migrations/{id} starts it.
Supported tools and the credentials each takes:
provider | credentials |
|---|---|
instantly | api_key (an API V2 key) |
smartlead | api_key |
lemlist | api_key |
apollo | api_key (a master key, for sequences to come over) |
snovio | client_id, client_secret |
saleshandy | api_key |
Only the fields a tool takes are kept. The key is stored encrypted on the import and erased when the import finishes or is cancelled. It is never returned.
To import contacts from a CRM or support tool already connected under Integrations (HubSpot, Pipedrive, Attio, Close, Zendesk, Intercom, Freshdesk), send connection_id instead. The connection’s stored credentials are used and nothing is pasted.
Requires the write permission.
curl --request POST \
--url https://app.manypi.com/api/integrations/migrations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"provider": "instantly",
"credentials": {
"api_key": "your-instantly-v2-key"
}
}
'import requests
url = "https://app.manypi.com/api/integrations/migrations"
payload = {
"provider": "instantly",
"credentials": { "api_key": "your-instantly-v2-key" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({provider: 'instantly', credentials: {api_key: 'your-instantly-v2-key'}})
};
fetch('https://app.manypi.com/api/integrations/migrations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.manypi.com/api/integrations/migrations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'provider' => 'instantly',
'credentials' => [
'api_key' => 'your-instantly-v2-key'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.manypi.com/api/integrations/migrations"
payload := strings.NewReader("{\n \"provider\": \"instantly\",\n \"credentials\": {\n \"api_key\": \"your-instantly-v2-key\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.manypi.com/api/integrations/migrations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"provider\": \"instantly\",\n \"credentials\": {\n \"api_key\": \"your-instantly-v2-key\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.manypi.com/api/integrations/migrations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"provider\": \"instantly\",\n \"credentials\": {\n \"api_key\": \"your-instantly-v2-key\"\n }\n}"
response = http.request(request)
puts response.read_body{
"job": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"provider": "<string>",
"account_label": "<string>",
"status": "scanned",
"scan": {
"label": "<string>",
"campaigns": [
{
"id": "<string>",
"name": "<string>",
"status": "<string>",
"emailSteps": 123,
"leads": 123
}
],
"leadsTotal": 123,
"blocklistTotal": 123,
"accounts": [
{
"email": "<string>",
"provider": "google",
"name": "<string>"
}
],
"notes": [
"<string>"
]
},
"options": {
"campaigns": [],
"recreateCampaigns": true,
"importLeads": true,
"doNotContact": true,
"enrollNotContacted": true,
"duplicates": "merge",
"asCustomers": false
},
"progress": {
"phase": "blocklist",
"campaignIndex": 123,
"campaignMap": {},
"counts": {
"suppressed": 123,
"campaigns": 123,
"steps": 123,
"created": 123,
"updated": 123,
"skipped": 123,
"overLimit": 123,
"failed": 123,
"enrolled": 123,
"customFields": 123
},
"warnings": [
"<string>"
],
"skippedSteps": {},
"leadsSeen": 123
},
"result": {},
"error": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"started_at": "2023-11-07T05:31:56Z",
"finished_at": "2023-11-07T05:31:56Z"
}
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"code": "<string>",
"details": "<unknown>"
}Authorizations
A ManyPI API key (mpi_...) from the profile menu → API Access in the dashboard, or an OAuth 2.1 access token obtained through the MCP consent flow.
Body
Response
The import, in status scanned, with what the scan found.
Show child attributes
Show child attributes
