Mark a lead as contacted (partner-api)
Records that you emailed or called the lead. A lead in status new becomes contacted (and contacted_at is set); a lead in any other status is returned unchanged. Always answers 200 with the lead as it stands.
Required scopes: partner-api and partner-leads-write.
HTTP:
PartnerApiKey
Partner API key. A bearer token that a Reseller Admin generates in the partner
portal under Settings, API keys. It belongs to the reseller partner, not to a
person, and carries the scopes ticked at creation time. Send it on every request as
Authorization: Bearer <partner_api_key>.
Every response is confined to the partner the key belongs to. Keep the key secret and call the API from your server only, never from a browser app.
- HTTP Authorization Scheme
bearer- Bearer format
Bearer <partner_api_key>
lead
path · string · uuid
*
Lead id (UUID). It must belong to your partner, otherwise the answer is `404`.
accept
header · string
example:
application/jsonRequest body · required · application/json
Request schema
channel*string
How you reached out.
enum:
email callResponses
Response schema
dataobject
A lead of the partner that owns the API key: somebody who left an address on your signup
link from a country the self-signup funnel does not serve. The dedupe key, signup IP and
browser are not exposed.
idstring · uuid
Unique identifier of the lead.
example:
550e8400-e29b-41d4-a716-446655440101emailstring · email
The address the lead left.
example:
prospect@example.comcountry_isostring
ISO 3166-1 alpha-2 code of the lead's country (`ZZ` when unknown).
example:
CHlocalestring | null
Language the lead used on the signup page.
example:
frplan_idstring | null · uuid
The plan the lead wanted, when known. Cleared if that plan is later deleted.
example:
550e8400-e29b-41d4-a716-446655440201plan_namestring | null
Name of that plan when the lead arrived (a snapshot, kept if the plan is renamed).
example:
Business Trialstatusstring
Follow-up status. `converted` is set only by the convert action.
enum:
new contacted qualified converted lostexample:
newsourcestring | null
Where the lead came from, when recorded.
notesstring | null
Free-text notes kept by your team.
example:
Asked for a callback on Monday.contacted_atstring | null · date-time
When the lead was first marked contacted.
odoo_syncedboolean
True when the lead has a matching `crm.lead` in your Odoo.
example:
created_atstring · date-time
When the lead arrived.
example:
2026-10-28T09:12:00+00:00updated_atstring · date-time
When the lead was last updated.
example:
2026-10-29T14:05:00+00:00Unauthenticated. The `Authorization: Bearer <token>` header was missing,
malformed, or names a token that has been revoked or deleted.
Response schema
messagestring
Forbidden. Three different situations share this status, told apart by `message`:
* the token is not a partner API key (a user token, a PBX API key, or any other token);
* the partner is not an active reseller;
* the key lacks a scope the endpoint needs. The body then also lists `required_scopes`.
Response schema
messagestring
Human-readable reason.
example:
This API key is missing a required scope.required_scopesarray<string>
Present on the missing-scope 403 only. Scopes the endpoint needs that the key lacks.
[]string
Not Found. No lead with this id belongs to your partner (a lead of another partner, a
nonexistent id and an id that is not a UUID answer the same way), or the signup funnel is
switched off for the platform, in which case every leads endpoint answers `404`.
Response schema
messagestring
Human-readable reason.
example:
This API key is missing a required scope.required_scopesarray<string>
Present on the missing-scope 403 only. Scopes the endpoint needs that the key lacks.
[]string
Unprocessable Content. Either the body failed validation (`errors` keyed by field), or the
lead is already a customer (`message` only): a converted lead can no longer change status
or be converted again. Nothing was changed.
Response schema
messagestring
The first validation error, or the reason the action was refused.
errorsobject
Validation errors keyed by field. Absent when the action itself was refused.
Free-form object
Too Many Requests. Two budgets apply: 120 requests per minute per API key, and 600 per
minute across all of a partner's keys together. Wait for the number of seconds in the `Retry-After` header before retrying.
Response schema
messagestring
post
https://cockpit.voxbi.com/api/v1/api/v1/leads/{lead}/contacted
Base URL
Request sample
curl -X POST 'https://cockpit.voxbi.com/api/v1/api/v1/leads/{lead}/contacted' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
--data '{"channel":"call"}'
const response = await fetch('https://cockpit.voxbi.com/api/v1/api/v1/leads/{lead}/contacted', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${YOUR_TOKEN}`,
},
body: JSON.stringify({
"channel": "call"
}),
});
const data = await response.json();
console.log(data);
import requests
response = requests.post('https://cockpit.voxbi.com/api/v1/api/v1/leads/{lead}/contacted',
headers={'Authorization': f'Bearer {YOUR_TOKEN}'},
json={
"channel": "call"
}
)
response.raise_for_status()
data = response.json()
print(data)
<?php
$context = stream_context_create([
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\nAuthorization: Bearer YOUR_TOKEN",
'content' => '{
\"channel\": \"call\"
}',
],
]);
$response = file_get_contents('https://cockpit.voxbi.com/api/v1/api/v1/leads/{lead}/contacted', false, $context);
$data = json_decode($response, true);
print_r($data);
Sample request
{ … }
"channel": "call"
}
{ … }
"data": { … }
"id": "550e8400-e29b-41d4-a716-446655440101",
"email": "prospect@example.com",
"country_iso": "CH",
"locale": "fr",
"plan_id": "550e8400-e29b-41d4-a716-446655440201",
"plan_name": "Business Trial",
"status": "contacted",
"source": null,
"notes": null,
"contacted_at": "2026-11-03T08:30:00+00:00",
"odoo_synced": false,
"created_at": "2026-10-28T09:12:00+00:00",
"updated_at": "2026-10-29T14:05:00+00:00"
}
}
{ … }
"message": "Unauthenticated."
}
Content-Type
string
example:
application/json{ … }
"message": "This endpoint requires a partner API key."
}
Content-Type
string
example:
application/json{ … }
"message": "Lead not found."
}
Content-Type
string
example:
application/json{ … }
"message": "The selected status is invalid.",
"errors": { … }
"status": [ … ]
"The selected status is invalid."
]
}
}
Content-Type
string
example:
application/json{ … }
"message": "Too Many Attempts."
}
Retry-After
integer
Seconds to wait before retrying.
example:
30
Content-Type
string
example:
application/json